MediaApiController.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. <?php
  2. namespace Typemill\Controllers;
  3. use Slim\Http\Request;
  4. use Slim\Http\Response;
  5. use Typemill\Models\ProcessImage;
  6. use Typemill\Models\ProcessFile;
  7. use Typemill\Controllers\BlockApiController;
  8. use \URLify;
  9. class MediaApiController extends ContentController
  10. {
  11. public function getMediaLibImages(Request $request, Response $response, $args)
  12. {
  13. # get params from call
  14. $this->params = $request->getParams();
  15. $this->uri = $request->getUri()->withUserInfo('');
  16. $imageProcessor = new ProcessImage($this->settings['images']);
  17. if(!$imageProcessor->checkFolders('images'))
  18. {
  19. return $response->withJson(['errors' => 'Please check if your media-folder exists and all folders inside are writable.'], 500);
  20. }
  21. $imagelist = $imageProcessor->scanMediaFlat();
  22. return $response->withJson(['images' => $imagelist]);
  23. }
  24. public function getMediaLibFiles(Request $request, Response $response, $args)
  25. {
  26. # get params from call
  27. $this->params = $request->getParams();
  28. $this->uri = $request->getUri()->withUserInfo('');
  29. $fileProcessor = new ProcessFile();
  30. if(!$fileProcessor->checkFolders())
  31. {
  32. return $response->withJson(['errors' => 'Please check if your media-folder exists and all folders inside are writable.'], 500);
  33. }
  34. $filelist = $fileProcessor->scanFilesFlat();
  35. return $response->withJson(['files' => $filelist]);
  36. }
  37. public function getImage(Request $request, Response $response, $args)
  38. {
  39. # get params from call
  40. $this->params = $request->getParams();
  41. $this->uri = $request->getUri()->withUserInfo('');
  42. $this->setStructure($draft = true, $cache = false);
  43. $imageProcessor = new ProcessImage($this->settings['images']);
  44. if(!$imageProcessor->checkFolders('images'))
  45. {
  46. return $response->withJson(['errors' => 'Please check if your media-folder exists and all folders inside are writable.'], 500);
  47. }
  48. $imageDetails = $imageProcessor->getImageDetails($this->params['name'], $this->structure);
  49. if($imageDetails)
  50. {
  51. return $response->withJson(['image' => $imageDetails]);
  52. }
  53. return $response->withJson(['errors' => 'Image not found or image name not valid.'], 404);
  54. }
  55. public function getFile(Request $request, Response $response, $args)
  56. {
  57. # get params from call
  58. $this->params = $request->getParams();
  59. $this->uri = $request->getUri()->withUserInfo('');
  60. $this->setStructure($draft = true, $cache = false);
  61. $fileProcessor = new ProcessFile();
  62. if(!$fileProcessor->checkFolders())
  63. {
  64. return $response->withJson(['errors' => 'Please check if your media-folder exists and all folders inside are writable.'], 500);
  65. }
  66. $fileDetails = $fileProcessor->getFileDetails($this->params['name'], $this->structure);
  67. if($fileDetails)
  68. {
  69. return $response->withJson(['file' => $fileDetails]);
  70. }
  71. return $response->withJson(['errors' => 'file not found or file name invalid'],404);
  72. }
  73. public function createImage(Request $request, Response $response, $args)
  74. {
  75. # get params from call
  76. $this->params = $request->getParams();
  77. $this->uri = $request->getUri()->withUserInfo('');
  78. $imageProcessor = new ProcessImage($this->settings['images']);
  79. if(!$imageProcessor->checkFolders('images'))
  80. {
  81. return $response->withJson(['errors' => 'Please check if your media-folder exists and all folders inside are writable.'], 500);
  82. }
  83. if($imageProcessor->createImage($this->params['image'], $this->params['name'], $this->settings['images']))
  84. {
  85. # publish image directly, used for example by image field for meta-tabs
  86. if($this->params['publish'])
  87. {
  88. $imageProcessor->publishImage();
  89. }
  90. return $response->withJson(['name' => 'media/live/' . $imageProcessor->getFullName(),'errors' => false]);
  91. }
  92. return $response->withJson(['errors' => 'could not store image to temporary folder']);
  93. }
  94. public function uploadFile(Request $request, Response $response, $args)
  95. {
  96. # get params from call
  97. $this->params = $request->getParams();
  98. $this->uri = $request->getUri()->withUserInfo('');
  99. # make sure only allowed filetypes are uploaded
  100. $finfo = finfo_open( FILEINFO_MIME_TYPE );
  101. $mtype = finfo_file( $finfo, $this->params['file'] );
  102. finfo_close( $finfo );
  103. $allowedMimes = $this->getAllowedMtypes();
  104. if(!in_array($mtype, $allowedMimes))
  105. {
  106. return $response->withJson(array('errors' => 'File-type is not allowed'));
  107. }
  108. $fileProcessor = new ProcessFile();
  109. if(!$fileProcessor->checkFolders())
  110. {
  111. return $response->withJson(['errors' => 'Please check if your media-folder exists and all folders inside are writable.'], 500);
  112. }
  113. $fileinfo = $fileProcessor->storeFile($this->params['file'], $this->params['name']);
  114. if($fileinfo)
  115. {
  116. return $response->withJson(['errors' => false, 'info' => $fileinfo]);
  117. }
  118. return $response->withJson(['errors' => 'could not store file to temporary folder'],500);
  119. }
  120. public function publishImage(Request $request, Response $response, $args)
  121. {
  122. $params = $request->getParsedBody();
  123. $imageProcessor = new ProcessImage($this->settings['images']);
  124. if(!$imageProcessor->checkFolders())
  125. {
  126. return $response->withJson(['errors' => 'Please check if your media-folder exists and all folders inside are writable.'], 500);
  127. }
  128. if($imageProcessor->publishImage())
  129. {
  130. $request = $request->withParsedBody($params);
  131. $block = new BlockApiController($this->c);
  132. if($params['new'])
  133. {
  134. return $block->addBlock($request, $response, $args);
  135. }
  136. return $block->updateBlock($request, $response, $args);
  137. }
  138. return $response->withJson(['errors' => 'could not store image to media folder'],500);
  139. }
  140. public function publishFile(Request $request, Response $response, $args)
  141. {
  142. $params = $request->getParsedBody();
  143. $fileProcessor = new ProcessFile();
  144. if(!$fileProcessor->checkFolders())
  145. {
  146. return $response->withJson(['errors' => 'Please check if your media-folder exists and all folders inside are writable.'], 500);
  147. }
  148. if($fileProcessor->publishFile())
  149. {
  150. $request = $request->withParsedBody($params);
  151. $block = new BlockApiController($this->c);
  152. if($params['new'])
  153. {
  154. return $block->addBlock($request, $response, $args);
  155. }
  156. return $block->updateBlock($request, $response, $args);
  157. }
  158. return $response->withJson(['errors' => 'could not store file to media folder'],500);
  159. }
  160. public function deleteImage(Request $request, Response $response, $args)
  161. {
  162. # get params from call
  163. $this->params = $request->getParams();
  164. $this->uri = $request->getUri()->withUserInfo('');
  165. # minimum permission is that user is allowed to delete content
  166. if(!$this->c->acl->isAllowed($_SESSION['role'], 'content', 'delete'))
  167. {
  168. return $response->withJson(array('data' => false, 'errors' => 'You are not allowed to delete images.'), 403);
  169. }
  170. if(!isset($this->params['name']))
  171. {
  172. return $response->withJson(['errors' => 'image name is missing'],500);
  173. }
  174. $imageProcessor = new ProcessImage($this->settings['images']);
  175. if(!$imageProcessor->checkFolders('images'))
  176. {
  177. return $response->withJson(['errors' => 'Please check if your media-folder exists and all folders inside are writable.'], 500);
  178. }
  179. if($imageProcessor->deleteImage($this->params['name']))
  180. {
  181. return $response->withJson(['errors' => false]);
  182. }
  183. return $response->withJson(['errors' => 'Oops, looks like we could not delete all sizes of that image.'], 500);
  184. }
  185. public function deleteFile(Request $request, Response $response, $args)
  186. {
  187. # get params from call
  188. $this->params = $request->getParams();
  189. $this->uri = $request->getUri()->withUserInfo('');
  190. # minimum permission is that user is allowed to delete content
  191. if(!$this->c->acl->isAllowed($_SESSION['role'], 'content', 'delete'))
  192. {
  193. return $response->withJson(array('data' => false, 'errors' => 'You are not allowed to delete files.'), 403);
  194. }
  195. if(!isset($this->params['name']))
  196. {
  197. return $response->withJson(['errors' => 'file name is missing'],500);
  198. }
  199. $fileProcessor = new ProcessFile();
  200. if($fileProcessor->deleteFile($this->params['name']))
  201. {
  202. return $response->withJson(['errors' => false]);
  203. }
  204. return $response->withJson(['errors' => 'could not delete the file'],500);
  205. }
  206. public function saveVideoImage(Request $request, Response $response, $args)
  207. {
  208. /* get params from call */
  209. $this->params = $request->getParams();
  210. $this->uri = $request->getUri()->withUserInfo('');
  211. $class = false;
  212. $imageUrl = $this->params['markdown'];
  213. if(strpos($imageUrl, 'https://www.youtube.com/watch?v=') !== false)
  214. {
  215. $videoID = str_replace('https://www.youtube.com/watch?v=', '', $imageUrl);
  216. $videoID = strpos($videoID, '&') ? substr($videoID, 0, strpos($videoID, '&')) : $videoID;
  217. $class = 'youtube';
  218. }
  219. if(strpos($imageUrl, 'https://youtu.be/') !== false)
  220. {
  221. $videoID = str_replace('https://youtu.be/', '', $imageUrl);
  222. $videoID = strpos($videoID, '?') ? substr($videoID, 0, strpos($videoID, '?')) : $videoID;
  223. $class = 'youtube';
  224. }
  225. if($class == 'youtube')
  226. {
  227. $videoURLmaxres = 'https://i1.ytimg.com/vi/' . $videoID . '/maxresdefault.jpg';
  228. $videoURL0 = 'https://i1.ytimg.com/vi/' . $videoID . '/0.jpg';
  229. }
  230. $ctx = stream_context_create(array(
  231. 'https' => array(
  232. 'timeout' => 1
  233. )
  234. )
  235. );
  236. $imageData = @file_get_contents($videoURLmaxres, 0, $ctx);
  237. if($imageData === false)
  238. {
  239. $imageData = @file_get_contents($videoURL0, 0, $ctx);
  240. if($imageData === false)
  241. {
  242. return $response->withJson(array('errors' => 'could not get the video image'));
  243. }
  244. }
  245. $imageData64 = 'data:image/jpeg;base64,' . base64_encode($imageData);
  246. $desiredSizes = ['live' => ['width' => 560, 'height' => 315]];
  247. $imageProcessor = new ProcessImage($this->settings['images']);
  248. if(!$imageProcessor->checkFolders())
  249. {
  250. return $response->withJson(['errors' => ['message' => 'Please check if your media-folder exists and all folders inside are writable.']], 500);
  251. }
  252. $tmpImage = $imageProcessor->createImage($imageData64, $desiredSizes);
  253. if(!$tmpImage)
  254. {
  255. return $response->withJson(array('errors' => 'could not create temporary image'));
  256. }
  257. $imageUrl = $imageProcessor->publishImage($desiredSizes, $videoID);
  258. if($imageUrl)
  259. {
  260. $this->params['markdown'] = '![' . $class . '-video](' . $imageUrl . ' "click to load video"){#' . $videoID. ' .' . $class . '}';
  261. $request = $request->withParsedBody($this->params);
  262. $block = new BlockApiController($this->c);
  263. if($params['new'])
  264. {
  265. return $block->addBlock($request, $response, $args);
  266. }
  267. return $block->updateBlock($request, $response, $args);
  268. }
  269. return $response->withJson(array('errors' => 'could not store the preview image'));
  270. }
  271. # https://www.sitepoint.com/mime-types-complete-list/
  272. # https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
  273. private function getAllowedMtypes()
  274. {
  275. return array(
  276. 'application/zip',
  277. 'application/gzip',
  278. 'application/x-gzip',
  279. 'application/x-compressed',
  280. 'application/x-zip-compressed',
  281. 'application/vnd.rar',
  282. 'application/x-7z-compressed',
  283. 'application/x-visio',
  284. 'application/vnd.visio',
  285. 'application/excel',
  286. 'application/x-excel',
  287. 'application/x-msexcel',
  288. 'application/vnd.ms-excel',
  289. 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  290. 'application/powerpoint',
  291. 'application/mspowerpoint',
  292. 'application/x-mspowerpoint',
  293. 'application/vnd.ms-powerpoint',
  294. 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
  295. 'application/msword',
  296. 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  297. 'application/x-project',
  298. 'application/vnd.ms-project',
  299. 'application/vnd.apple.keynote',
  300. 'application/vnd.apple.mpegurl',
  301. 'application/vnd.apple.numbers',
  302. 'application/vnd.apple.pages',
  303. 'application/vnd.amazon.mobi8-ebook',
  304. 'application/epub+zip',
  305. 'application/pdf',
  306. 'application/x-latex',
  307. 'image/png',
  308. 'image/jpeg',
  309. 'image/gif',
  310. 'image/tiff',
  311. 'image/x-tiff',
  312. 'image/svg+xml',
  313. 'image/x-icon',
  314. 'text/plain',
  315. 'application/plain',
  316. 'text/richtext',
  317. 'text/vnd.rn-realtext',
  318. 'application/rtf',
  319. 'application/x-rtf',
  320. 'font/*',
  321. 'audio/mpeg',
  322. 'audio/mp4',
  323. 'audio/ogg',
  324. 'audio/3gpp',
  325. 'audio/3gpp2',
  326. 'video/mpeg',
  327. 'video/mp4',
  328. 'video/ogg',
  329. 'video/3gpp',
  330. 'video/3gpp2',
  331. );
  332. }
  333. }