PageRenderTime 25ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/test/core/Files/CheckAttachmentGalleryTest.php

https://gitlab.com/ElvisAns/tiki
PHP | 404 lines | 264 code | 57 blank | 83 comment | 6 complexity | b56a03eec52205e463656557338ca8bb MD5 | raw file
  1. <?php
  2. // (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
  3. //
  4. // All Rights Reserved. See copyright.txt for details and a complete list of authors.
  5. // Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
  6. // $Id$
  7. namespace Tiki\Test\Files;
  8. use Comments;
  9. use Exception;
  10. use org\bovigo\vfs\vfsStream;
  11. use PHPUnit\Framework\TestCase;
  12. use Tiki\Files\CheckAttachmentGallery;
  13. use TikiLib;
  14. use TrackerLib;
  15. use WikiLib;
  16. class CheckAttachmentGalleryTest extends TestCase
  17. {
  18. protected $file_root;
  19. protected $files_dir;
  20. protected $default_file_content = 'this is a test';
  21. protected function setUp(): void
  22. {
  23. global $prefs;
  24. $prefs['feature_user_watches'] = 'n';
  25. $this->refreshDirectory();
  26. // Remove existing attachments
  27. $this->removeAttachmentsFromDb();
  28. }
  29. protected function tearDown(): void
  30. {
  31. $this->removeAttachmentsFromDb();
  32. }
  33. /**
  34. * @dataProvider getTypes
  35. * @param $type
  36. */
  37. public function testAttachmentEmptyAttachmentsNoProblemOnDB($type)
  38. {
  39. $to_assert = [
  40. 'usesDatabase' => true,
  41. 'path' => [''],
  42. 'mixedLocation' => false,
  43. 'count' => 0,
  44. 'countFilesDb' => 0,
  45. 'countFilesDisk' => 0,
  46. 'issueCount' => 0,
  47. 'missing' => [],
  48. 'mismatch' => [],
  49. 'unknown' => [],
  50. ];
  51. $this->configToStoreFiles($type, true);
  52. $checkInstance = new CheckAttachmentGallery($type);
  53. $result = $checkInstance->analyse();
  54. $this->assertEquals($to_assert, $result);
  55. }
  56. /**
  57. * @dataProvider getTypes()
  58. *
  59. * @param $type
  60. */
  61. public function testAttachmentEmptyAttachmentsNoProblemOnDisk($type)
  62. {
  63. $to_assert = [
  64. 'usesDatabase' => false,
  65. 'path' => [$this->files_dir],
  66. 'mixedLocation' => false,
  67. 'count' => 0,
  68. 'countFilesDb' => 0,
  69. 'countFilesDisk' => 0,
  70. 'issueCount' => 0,
  71. 'missing' => [],
  72. 'mismatch' => [],
  73. 'unknown' => [],
  74. ];
  75. $this->configToStoreFiles($type, false);
  76. $checkInstance = new CheckAttachmentGallery($type);
  77. $result = $checkInstance->analyse();
  78. $this->assertEquals($to_assert, $result);
  79. }
  80. /**
  81. * @dataProvider getTypes
  82. * @param $type
  83. * @throws Exception
  84. */
  85. public function testAttachmentWithOneFileOnDisk($type)
  86. {
  87. $this->configToStoreFiles($type, false);
  88. $this->insertAttachment(['name' => uniqid(), 'type' => $type]);
  89. $checkInstance = new CheckAttachmentGallery($type);
  90. $result = $checkInstance->analyse();
  91. $this->assertFalse($result['usesDatabase']);
  92. $this->assertFalse($result['mixedLocation']);
  93. $this->assertEquals(1, $result['count']);
  94. $this->assertEquals(0, $result['issueCount']);
  95. }
  96. /**
  97. * @dataProvider getTypes()
  98. * @param $type
  99. * @throws Exception
  100. */
  101. public function testAttachmentWithOneFileOnDb($type)
  102. {
  103. $this->configToStoreFiles($type, true);
  104. $checkInstance = new CheckAttachmentGallery($type);
  105. $this->insertAttachment([
  106. 'name' => 'testAttachmentWithOneFileOnDb',
  107. 'type' => $type,
  108. 'db' => true
  109. ]);
  110. $result = $checkInstance->analyse();
  111. $this->assertFalse($result['mixedLocation']);
  112. $this->assertEquals(1, $result['count']);
  113. $this->assertEquals(0, $result['issueCount']);
  114. }
  115. /**
  116. * @dataProvider getTypes
  117. * @param $type
  118. */
  119. public function testAttachmentUnknownFile($type)
  120. {
  121. global $tikilib;
  122. $this->configToStoreFiles($type, false);
  123. $filename = md5($tikilib->now);
  124. $this->createFileOnDisk($filename, 'Invalid file');
  125. $checkInstance = new CheckAttachmentGallery($type);
  126. $result = $checkInstance->analyse();
  127. $this->assertFalse($result['usesDatabase']);
  128. $this->assertFalse($result['mixedLocation']);
  129. $this->assertEquals(0, $result['count'], 'Count'); // Attachment not registered in db
  130. $this->assertEquals(1, $result['issueCount'], 'Issue Count');
  131. $this->assertEquals(
  132. [
  133. [
  134. 'name' => $filename,
  135. 'path' => $this->files_dir,
  136. 'size' => strlen('Invalid file')
  137. ]
  138. ],
  139. $result['unknown']
  140. );
  141. }
  142. /**
  143. * @dataProvider getTypes
  144. * @param $type
  145. * @throws Exception
  146. */
  147. public function testAttachmentMismatchFile($type)
  148. {
  149. global $tikilib;
  150. $this->configToStoreFiles($type, false);
  151. $filename = md5($tikilib->now);
  152. $id = $this->insertAttachment([
  153. 'name' => $filename,
  154. 'fhash' => $filename,
  155. 'type' => $type,
  156. 'size' => 1 // the size will create the mismatch
  157. ]);
  158. $checkInstance = new CheckAttachmentGallery($type);
  159. $result = $checkInstance->analyse();
  160. $this->assertFalse($result['usesDatabase']);
  161. $this->assertFalse($result['mixedLocation']);
  162. $this->assertEquals(1, $result['count'], 'Count');
  163. $this->assertEquals(1, $result['issueCount'], 'Issue Count');
  164. $this->assertEquals(
  165. [
  166. [
  167. 'name' => $filename,
  168. 'path' => $this->files_dir,
  169. 'size' => 1,
  170. 'id' => $id
  171. ]
  172. ],
  173. $result['mismatch']
  174. );
  175. }
  176. /**
  177. * Test that a file that should be stored in filesystem is missing
  178. *
  179. * @dataProvider getTypes
  180. * @param $type
  181. * @throws Exception
  182. */
  183. public function testAttachmentMissingFile($type)
  184. {
  185. global $tikilib;
  186. $this->configToStoreFiles($type, false);
  187. $filename = md5($tikilib->now);
  188. $id = $this->insertAttachment([
  189. 'name' => $filename,
  190. 'fhash' => $filename,
  191. 'type' => $type,
  192. ]);
  193. if (file_exists($this->files_dir . $filename)) {
  194. unlink($this->files_dir . $filename);
  195. }
  196. $checkInstance = new CheckAttachmentGallery($type);
  197. $result = $checkInstance->analyse();
  198. $this->assertFalse($result['usesDatabase']);
  199. $this->assertFalse($result['mixedLocation']);
  200. $this->assertEquals(1, $result['count'], 'Count');
  201. $this->assertEquals(1, $result['issueCount'], 'Issue Count');
  202. $this->assertEquals([
  203. [
  204. 'name' => $filename,
  205. 'path' => $this->files_dir,
  206. 'size' => (int)strlen($this->default_file_content),
  207. 'id' => $id,
  208. ]
  209. ], $result['missing']);
  210. }
  211. /**
  212. * Configures the preferences to set the storage in the disk for a specific type
  213. * @param $type
  214. * @param bool $use_db
  215. */
  216. protected function configToStoreFiles($type, $use_db = false)
  217. {
  218. global $prefs;
  219. $prefs[$type . '_use_db'] = $use_db ? 'y' : 'n';
  220. $prefs[$type . '_use_dir'] = $use_db ? '' : $this->files_dir;
  221. }
  222. /**
  223. * Inserts a TXT file attachment for a specific type
  224. * @param $file
  225. * @return mixed
  226. * @throws Exception
  227. */
  228. protected function insertAttachment($file)
  229. {
  230. global $tikilib;
  231. $id = null;
  232. $base_name = $file['name'];
  233. $useDB = isset($file['db']) && $file['db'];
  234. $string = $this->default_file_content;
  235. $size = $file['size'] ?? strlen($string);
  236. $type = $file['type'];
  237. $lib = $this->getLib($type);
  238. $dir = $useDB ? '' : $this->files_dir;
  239. $fhash = null;
  240. if (! $useDB) {
  241. $fhash = $file['fhash'] ?? md5($base_name . $tikilib->now);
  242. $this->createFileOnDisk($fhash, $string);
  243. $string = null;
  244. }
  245. switch ($type) {
  246. case 'w':
  247. $id = $lib->wiki_attach_file('test', $base_name, '.txt', (int)$size, $string, 0, 0, $fhash, time());
  248. break;
  249. case 't':
  250. $id = $lib->replace_item_attachment(null, $base_name, '.txt', (int)$size, $string, 0, 0, $fhash, '', '', 0, 0, [], []);
  251. break;
  252. case 'f':
  253. $id = $lib->forum_attach_file(0, 0, $base_name, '.txt', (int)$size, $string, $fhash, $dir, 0);
  254. break;
  255. }
  256. return $id;
  257. }
  258. /**
  259. * Function to create a local file with a specific content
  260. * @param $file_name
  261. * @param $content
  262. */
  263. protected function createFileOnDisk($file_name, $content)
  264. {
  265. $full_path = $this->files_dir . $file_name;
  266. $myfile = fopen($full_path, "w") or die("Unable to open file!");
  267. fwrite($myfile, $content);
  268. fclose($myfile);
  269. }
  270. /**
  271. * Clears and prepares the DB to run the tests
  272. * @throws Exception
  273. */
  274. protected function removeAttachmentsFromDb()
  275. {
  276. $types = ['f', 't', 'w'];
  277. foreach ($types as $type) {
  278. $lib = $this->getLib($type);
  279. $attachments = $lib->list_all_attachments();
  280. foreach ($attachments['data'] as $attachment) {
  281. $this->removeAttachment($type, $attachment['attId']);
  282. }
  283. }
  284. }
  285. /**
  286. * Gets the lib related to a specific attachment type
  287. *
  288. * @param $type
  289. *
  290. * @return WikiLib|TrackerLib|Comments
  291. * @throws Exception
  292. */
  293. protected function getLib($type)
  294. {
  295. switch ($type) {
  296. case 'w':
  297. return TikiLib::lib('wiki');
  298. case 't':
  299. return TikiLib::lib('trk');
  300. case 'f':
  301. return TikiLib::lib('comments');
  302. }
  303. }
  304. /**
  305. * Gets the method responsible for removing an attachment based on the type
  306. * @param $type
  307. * @param $id
  308. * @throws Exception
  309. */
  310. protected function removeAttachment($type, $id)
  311. {
  312. $lib = $this->getLib($type);
  313. switch ($type) {
  314. case 'w':
  315. $lib->remove_wiki_attachment($id);
  316. break;
  317. case 't':
  318. $lib->remove_item_attachment($id);
  319. break;
  320. case 'f':
  321. $lib->remove_thread_attachment($id);
  322. break;
  323. }
  324. }
  325. /**
  326. * Refreshes mock directory to store files for test purposes
  327. */
  328. protected function refreshDirectory()
  329. {
  330. $this->file_root = vfsStream::setup(uniqid('', true), null);
  331. $this->files_dir = $this->file_root->url() . '/test/';
  332. mkdir($this->files_dir);
  333. }
  334. /**
  335. * Data provider to test all attachment galleries
  336. *
  337. * @return array
  338. */
  339. public function getTypes()
  340. {
  341. return [
  342. 'forum' => ['f'],
  343. 'tracker' => ['t'],
  344. 'wiki' => ['w'],
  345. ];
  346. }
  347. }