CommentsContext.php 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  6. * @author Joas Schilling <coding@schilljs.com>
  7. * @author Julius Härtl <jus@bitgrid.net>
  8. * @author Lukas Reschke <lukas@statuscode.ch>
  9. * @author Robin Appelman <robin@icewind.nl>
  10. * @author Roeland Jago Douma <roeland@famdouma.nl>
  11. *
  12. * @license AGPL-3.0
  13. *
  14. * This code is free software: you can redistribute it and/or modify
  15. * it under the terms of the GNU Affero General Public License, version 3,
  16. * as published by the Free Software Foundation.
  17. *
  18. * This program is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU Affero General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU Affero General Public License, version 3,
  24. * along with this program. If not, see <http://www.gnu.org/licenses/>
  25. *
  26. */
  27. require __DIR__ . '/../../vendor/autoload.php';
  28. class CommentsContext implements \Behat\Behat\Context\Context {
  29. /** @var string */
  30. private $baseUrl;
  31. /** @var array */
  32. private $response;
  33. /** @var int */
  34. private $commentId;
  35. /** @var int */
  36. private $fileId;
  37. /**
  38. * @param string $baseUrl
  39. */
  40. public function __construct($baseUrl) {
  41. $this->baseUrl = $baseUrl;
  42. // in case of ci deployment we take the server url from the environment
  43. $testServerUrl = getenv('TEST_SERVER_URL');
  44. if ($testServerUrl !== false) {
  45. $this->baseUrl = substr($testServerUrl, 0, -5);
  46. }
  47. }
  48. /**
  49. * get a named entry from response instead of picking a random entry from values
  50. *
  51. * @param string $path
  52. *
  53. * @return array|string
  54. * @throws Exception
  55. */
  56. private function getValueFromNamedEntries(string $path, array $response): mixed {
  57. $next = '';
  58. if (str_contains($path, ' ')) {
  59. [$key, $next] = explode(' ', $path, 2);
  60. } else {
  61. $key = $path;
  62. }
  63. foreach ($response as $entry) {
  64. if ($entry['name'] === $key) {
  65. if ($next !== '') {
  66. return $this->getValueFromNamedEntries($next, $entry['value']);
  67. } else {
  68. return $entry['value'];
  69. }
  70. }
  71. }
  72. return null;
  73. }
  74. /** @AfterScenario */
  75. public function teardownScenario() {
  76. $client = new \GuzzleHttp\Client();
  77. try {
  78. $client->delete(
  79. $this->baseUrl . '/remote.php/webdav/myFileToComment.txt',
  80. [
  81. 'auth' => [
  82. 'user0',
  83. '123456',
  84. ],
  85. 'headers' => [
  86. 'Content-Type' => 'application/json',
  87. ],
  88. ]
  89. );
  90. } catch (\GuzzleHttp\Exception\ClientException $e) {
  91. $e->getResponse();
  92. }
  93. }
  94. /**
  95. * @param string $path
  96. * @return int
  97. */
  98. private function getFileIdForPath($path) {
  99. $url = $this->baseUrl . '/remote.php/webdav/' . $path;
  100. $context = stream_context_create([
  101. 'http' => [
  102. 'method' => 'PROPFIND',
  103. 'header' => "Authorization: Basic dXNlcjA6MTIzNDU2\r\nContent-Type: application/x-www-form-urlencoded",
  104. 'content' => '<?xml version="1.0"?>
  105. <d:propfind xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns">
  106. <d:prop>
  107. <oc:fileid />
  108. </d:prop>
  109. </d:propfind>'
  110. ]
  111. ]);
  112. $response = file_get_contents($url, false, $context);
  113. preg_match_all('/\<oc:fileid\>(.*)\<\/oc:fileid\>/', $response, $matches);
  114. return (int)$matches[1][0];
  115. }
  116. /**
  117. * @When :user posts a comment with content :content on the file named :fileName it should return :statusCode
  118. * @param string $user
  119. * @param string $content
  120. * @param string $fileName
  121. * @param int $statusCode
  122. * @throws \Exception
  123. */
  124. public function postsACommentWithContentOnTheFileNamedItShouldReturn($user, $content, $fileName, $statusCode) {
  125. $fileId = $this->getFileIdForPath($fileName);
  126. $this->fileId = (int)$fileId;
  127. $url = $this->baseUrl . '/remote.php/dav/comments/files/' . $fileId . '/';
  128. $client = new \GuzzleHttp\Client();
  129. try {
  130. $res = $client->post(
  131. $url,
  132. [
  133. 'body' => '{"actorId":"user0","actorDisplayName":"user0","actorType":"users","verb":"comment","message":"' . $content . '","creationDateTime":"Thu, 18 Feb 2016 17:04:18 GMT","objectType":"files"}',
  134. 'auth' => [
  135. $user,
  136. '123456',
  137. ],
  138. 'headers' => [
  139. 'Content-Type' => 'application/json',
  140. ],
  141. ]
  142. );
  143. } catch (\GuzzleHttp\Exception\ClientException $e) {
  144. $res = $e->getResponse();
  145. }
  146. if ($res->getStatusCode() !== (int)$statusCode) {
  147. throw new \Exception("Response status code was not $statusCode (" . $res->getStatusCode() . ")");
  148. }
  149. }
  150. /**
  151. * @Then As :user load all the comments of the file named :fileName it should return :statusCode
  152. * @param string $user
  153. * @param string $fileName
  154. * @param int $statusCode
  155. * @throws \Exception
  156. */
  157. public function asLoadloadAllTheCommentsOfTheFileNamedItShouldReturn($user, $fileName, $statusCode) {
  158. $fileId = $this->getFileIdForPath($fileName);
  159. $url = $this->baseUrl . '/remote.php/dav/comments/files/' . $fileId . '/';
  160. try {
  161. $client = new \GuzzleHttp\Client();
  162. $res = $client->request(
  163. 'REPORT',
  164. $url,
  165. [
  166. 'body' => '<?xml version="1.0" encoding="utf-8" ?>
  167. <oc:filter-comments xmlns:oc="http://owncloud.org/ns">
  168. <oc:limit>200</oc:limit>
  169. <oc:offset>0</oc:offset>
  170. </oc:filter-comments>
  171. ',
  172. 'auth' => [
  173. $user,
  174. '123456',
  175. ],
  176. 'headers' => [
  177. 'Content-Type' => 'application/json',
  178. ],
  179. ]
  180. );
  181. } catch (\GuzzleHttp\Exception\ClientException $e) {
  182. $res = $e->getResponse();
  183. }
  184. if ($res->getStatusCode() !== (int)$statusCode) {
  185. throw new \Exception("Response status code was not $statusCode (" . $res->getStatusCode() . ")");
  186. }
  187. if ($res->getStatusCode() === 207) {
  188. $service = new Sabre\Xml\Service();
  189. $this->response = $service->parse($res->getBody()->getContents());
  190. $this->commentId = (int) ($this->getValueFromNamedEntries('{DAV:}response {DAV:}propstat {DAV:}prop {http://owncloud.org/ns}id', $this->response ?? []) ?? 0);
  191. }
  192. }
  193. /**
  194. * @Given As :user sending :verb to :url with
  195. * @param string $user
  196. * @param string $verb
  197. * @param string $url
  198. * @param \Behat\Gherkin\Node\TableNode $body
  199. * @throws \Exception
  200. */
  201. public function asUserSendingToWith($user, $verb, $url, \Behat\Gherkin\Node\TableNode $body) {
  202. $client = new \GuzzleHttp\Client();
  203. $options = [];
  204. $options['auth'] = [$user, '123456'];
  205. $fd = $body->getRowsHash();
  206. $options['form_params'] = $fd;
  207. $options['headers'] = [
  208. 'OCS-APIREQUEST' => 'true',
  209. ];
  210. $client->request($verb, $this->baseUrl . '/ocs/v1.php/' . $url, $options);
  211. }
  212. /**
  213. * @Then As :user delete the created comment it should return :statusCode
  214. * @param string $user
  215. * @param int $statusCode
  216. * @throws \Exception
  217. */
  218. public function asDeleteTheCreatedCommentItShouldReturn($user, $statusCode) {
  219. $url = $this->baseUrl . '/remote.php/dav/comments/files/' . $this->fileId . '/' . $this->commentId;
  220. $client = new \GuzzleHttp\Client();
  221. try {
  222. $res = $client->delete(
  223. $url,
  224. [
  225. 'auth' => [
  226. $user,
  227. '123456',
  228. ],
  229. 'headers' => [
  230. 'Content-Type' => 'application/json',
  231. ],
  232. ]
  233. );
  234. } catch (\GuzzleHttp\Exception\ClientException $e) {
  235. $res = $e->getResponse();
  236. }
  237. if ($res->getStatusCode() !== (int)$statusCode) {
  238. throw new \Exception("Response status code was not $statusCode (" . $res->getStatusCode() . ")");
  239. }
  240. }
  241. /**
  242. * @Then the response should contain a property :key with value :value
  243. * @param string $key
  244. * @param string $value
  245. * @throws \Exception
  246. */
  247. public function theResponseShouldContainAPropertyWithValue($key, $value) {
  248. // $keys = $this->response[0]['value'][1]['value'][0]['value'];
  249. $keys = $this->getValueFromNamedEntries('{DAV:}response {DAV:}propstat {DAV:}prop', $this->response);
  250. $found = false;
  251. foreach ($keys as $singleKey) {
  252. if ($singleKey['name'] === '{http://owncloud.org/ns}' . substr($key, 3)) {
  253. if ($singleKey['value'] === $value) {
  254. $found = true;
  255. }
  256. }
  257. }
  258. if ($found === false) {
  259. throw new \Exception("Cannot find property $key with $value");
  260. }
  261. }
  262. /**
  263. * @Then the response should contain only :number comments
  264. * @param int $number
  265. * @throws \Exception
  266. */
  267. public function theResponseShouldContainOnlyComments($number) {
  268. $count = 0;
  269. if ($this->response !== null) {
  270. $count = count($this->response);
  271. }
  272. if ($count !== (int)$number) {
  273. throw new \Exception("Found more comments than $number (" . $count . ")");
  274. }
  275. }
  276. /**
  277. * @Then As :user edit the last created comment and set text to :text it should return :statusCode
  278. * @param string $user
  279. * @param string $text
  280. * @param int $statusCode
  281. * @throws \Exception
  282. */
  283. public function asEditTheLastCreatedCommentAndSetTextToItShouldReturn($user, $text, $statusCode) {
  284. $client = new \GuzzleHttp\Client();
  285. $options = [];
  286. $options['auth'] = [$user, '123456'];
  287. $options['body'] = '<?xml version="1.0"?>
  288. <d:propertyupdate xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns">
  289. <d:set>
  290. <d:prop>
  291. <oc:message>' . $text . '</oc:message>
  292. </d:prop>
  293. </d:set>
  294. </d:propertyupdate>';
  295. try {
  296. $res = $client->request('PROPPATCH', $this->baseUrl . '/remote.php/dav/comments/files/' . $this->fileId . '/' . $this->commentId, $options);
  297. } catch (\GuzzleHttp\Exception\ClientException $e) {
  298. $res = $e->getResponse();
  299. }
  300. if ($res->getStatusCode() !== (int)$statusCode) {
  301. throw new \Exception("Response status code was not $statusCode (" . $res->getStatusCode() . ")");
  302. }
  303. }
  304. }