ContentApiController.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. <?php
  2. namespace Typemill\Controllers;
  3. use Slim\Http\Request;
  4. use Slim\Http\Response;
  5. use Typemill\Models\Folder;
  6. use Typemill\Models\Write;
  7. use Typemill\Extensions\ParsedownExtension;
  8. class ContentApiController extends ContentController
  9. {
  10. public function publishArticle(Request $request, Response $response, $args)
  11. {
  12. # get params from call
  13. $this->params = $request->getParams();
  14. $this->uri = $request->getUri();
  15. # validate input
  16. if(!$this->validateEditorInput()){ return $response->withJson($this->errors,422); }
  17. # set structure
  18. if(!$this->setStructure($draft = true)){ return $response->withJson($this->errors, 404); }
  19. # set item
  20. if(!$this->setItem()){ return $response->withJson($this->errors, 404); }
  21. # set the status for published and drafted
  22. $this->setPublishStatus();
  23. # set path for the file (or folder)
  24. $this->setItemPath('md');
  25. # merge title with content for complete markdown document
  26. $updatedContent = '# ' . $this->params['title'] . "\r\n\r\n" . $this->params['content'];
  27. # update the file
  28. if($this->write->writeFile($this->settings['contentFolder'], $this->path, $updatedContent))
  29. {
  30. # update the file
  31. $delete = $this->deleteContentFiles(['txt']);
  32. # update the structure
  33. $this->setStructure($draft = false, $cache = false);
  34. return $response->withJson(['success'], 200);
  35. }
  36. else
  37. {
  38. return $response->withJson(['errors' => ['message' => 'Could not write to file. Please check if the file is writable']], 404);
  39. }
  40. }
  41. public function unpublishArticle(Request $request, Response $response, $args)
  42. {
  43. # get params from call
  44. $this->params = $request->getParams();
  45. $this->uri = $request->getUri();
  46. # set structure
  47. if(!$this->setStructure($draft = true)){ return $response->withJson($this->errors, 404); }
  48. # set item
  49. if(!$this->setItem()){ return $response->withJson($this->errors, 404); }
  50. # set the status for published and drafted
  51. $this->setPublishStatus();
  52. # check if draft exists, if not, create one.
  53. if(!$this->item->drafted)
  54. {
  55. # set path for the file (or folder)
  56. $this->setItemPath('md');
  57. # set content of markdown-file
  58. if(!$this->setContent()){ return $response->withJson($this->errors, 404); }
  59. # initialize parsedown extension
  60. $parsedown = new ParsedownExtension();
  61. # turn markdown into an array of markdown-blocks
  62. $contentArray = $parsedown->markdownToArrayBlocks($this->content);
  63. # encode the content into json
  64. $contentJson = json_encode($contentArray);
  65. # set path for the file (or folder)
  66. $this->setItemPath('txt');
  67. /* update the file */
  68. if(!$this->write->writeFile($this->settings['contentFolder'], $this->path, $contentJson))
  69. {
  70. return $response->withJson(['errors' => ['message' => 'Could not create a draft of the page. Please check if the folder is writable']], 404);
  71. }
  72. }
  73. # update the file
  74. $delete = $this->deleteContentFiles(['md']);
  75. if($delete)
  76. {
  77. # update the live structure
  78. $this->setStructure($draft = false, $cache = false);
  79. return $response->withJson(['success'], 200);
  80. }
  81. else
  82. {
  83. return $response->withJson(['errors' => ['message' => "Could not delete some files. Please check if the files exists and are writable"]], 404);
  84. }
  85. }
  86. public function deleteArticle(Request $request, Response $response, $args)
  87. {
  88. # get params from call
  89. $this->params = $request->getParams();
  90. $this->uri = $request->getUri();
  91. # set structure
  92. if(!$this->setStructure($draft = true)){ return $response->withJson($this->errors, 404); }
  93. # set item
  94. if(!$this->setItem()){ return $response->withJson($this->errors, 404); }
  95. # update the file
  96. $delete = $this->deleteContentFiles(['md','txt']);
  97. if($delete)
  98. {
  99. # update the live structure
  100. $this->setStructure($draft = false, $cache = false);
  101. #update the backend structure
  102. $this->setStructure($draft = true, $cache = false);
  103. return $response->withJson(['success'], 200);
  104. }
  105. else
  106. {
  107. return $response->withJson(['errors' => ['message' => "Could not delete some files. Please check if the files exists and are writable"]], 404);
  108. }
  109. }
  110. public function updateArticle(Request $request, Response $response, $args)
  111. {
  112. # get params from call
  113. $this->params = $request->getParams();
  114. $this->uri = $request->getUri();
  115. # validate input
  116. if(!$this->validateEditorInput()){ return $response->withJson($this->errors,422); }
  117. # set structure
  118. if(!$this->setStructure($draft = true)){ return $response->withJson($this->errors, 404); }
  119. # set item
  120. if(!$this->setItem()){ return $response->withJson($this->errors, 404); }
  121. # set path for the file (or folder)
  122. $this->setItemPath('txt');
  123. # merge title with content for complete markdown document
  124. $updatedContent = '# ' . $this->params['title'] . "\r\n\r\n" . $this->params['content'];
  125. # initialize parsedown extension
  126. $parsedown = new ParsedownExtension();
  127. # turn markdown into an array of markdown-blocks
  128. $contentArray = $parsedown->markdownToArrayBlocks($updatedContent);
  129. # encode the content into json
  130. $contentJson = json_encode($contentArray);
  131. /* update the file */
  132. if($this->write->writeFile($this->settings['contentFolder'], $this->path, $contentJson))
  133. {
  134. return $response->withJson(['success'], 200);
  135. }
  136. else
  137. {
  138. return $response->withJson(['errors' => ['message' => 'Could not write to file. Please check if the file is writable']], 404);
  139. }
  140. }
  141. public function sortArticle(Request $request, Response $response, $args)
  142. {
  143. # get params from call
  144. $this->params = $request->getParams();
  145. $this->uri = $request->getUri();
  146. # url is only needed, if an active page is moved
  147. $url = false;
  148. # set structure
  149. if(!$this->setStructure($draft = true)){ return $response->withJson(array('data' => false, 'errors' => $this->errors, 'url' => $url), 404); }
  150. # validate input
  151. if(!$this->validateNavigationSort()){ return $response->withJson(array('data' => $this->structure, 'errors' => 'Data not valid. Please refresh the page and try again.', 'url' => $url), 422); }
  152. # get the ids (key path) for item, old folder and new folder
  153. $itemKeyPath = explode('.', $this->params['item_id']);
  154. $parentKeyFrom = explode('.', $this->params['parent_id_from']);
  155. $parentKeyTo = explode('.', $this->params['parent_id_to']);
  156. # get the item from structure
  157. $item = Folder::getItemWithKeyPath($this->structure, $itemKeyPath);
  158. if(!$item){ return $response->withJson(array('data' => $this->structure, 'errors' => 'We could not find this page. Please refresh and try again.', 'url' => $url), 404); }
  159. # if a folder is moved on the first level
  160. if($this->params['parent_id_from'] == 'navi')
  161. {
  162. # create empty and default values so that the logic below still works
  163. $newFolder = new \stdClass();
  164. $newFolder->path = '';
  165. $folderContent = $this->structure;
  166. }
  167. else
  168. {
  169. # get the target folder from structure
  170. $newFolder = Folder::getItemWithKeyPath($this->structure, $parentKeyTo);
  171. # get the content of the target folder
  172. $folderContent = $newFolder->folderContent;
  173. }
  174. # if the item has been moved within the same folder
  175. if($this->params['parent_id_from'] == $this->params['parent_id_to'])
  176. {
  177. # get key of item
  178. $itemKey = end($itemKeyPath);
  179. reset($itemKeyPath);
  180. # delete item from folderContent
  181. unset($folderContent[$itemKey]);
  182. }
  183. elseif($this->params['active'] == 'active')
  184. {
  185. # an active file has been moved to another folder
  186. $url = $this->uri->getBaseUrl() . '/tm/content' . $newFolder->urlRelWoF . '/' . $item->slug;
  187. }
  188. # add item to newFolder
  189. array_splice($folderContent, $this->params['index_new'], 0, array($item));
  190. # initialize index
  191. $index = 0;
  192. # initialise write object
  193. $write = new Write();
  194. # iterate through the whole content of the new folder
  195. $writeError = false;
  196. foreach($folderContent as $folderItem)
  197. {
  198. if(!$write->moveElement($folderItem, $newFolder->path, $index))
  199. {
  200. $writeError = true;
  201. }
  202. $index++;
  203. }
  204. if($writeError){ return $response->withJson(array('data' => $this->structure, 'errors' => 'Something went wrong. Please refresh the page and check, if all folders and files are writable.', 'url' => $url), 404); }
  205. # update the structure for editor
  206. $this->setStructure($draft = true, $cache = false);
  207. # get item for url and set it active again
  208. if(isset($this->params['url']))
  209. {
  210. $activeItem = Folder::getItemForUrl($this->structure, $this->params['url']);
  211. }
  212. # keep the internal structure for response
  213. $internalStructure = $this->structure;
  214. # update the structure for website
  215. $this->setStructure($draft = false, $cache = false);
  216. return $response->withJson(array('data' => $internalStructure, 'errors' => false, 'url' => $url));
  217. }
  218. public function createBlock(Request $request, Response $response, $args)
  219. {
  220. /* get params from call */
  221. $this->params = $request->getParams();
  222. $this->uri = $request->getUri();
  223. /* validate input */
  224. if(!$this->validateInput()){ return $response->withJson($this->errors,422); }
  225. /* set structure */
  226. if(!$this->setStructure()){ return $response->withJson($this->errors, 404); }
  227. /* set item */
  228. if(!$this->setItem()){ return $response->withJson($this->errors, 404); }
  229. /* set path */
  230. $this->setItemPath();
  231. /* get markdown-file */
  232. if(!$this->setMarkdownFile()){ return $response->withJson($this->errors, 404); }
  233. /* get txt-file with content array */
  234. $contentArray = NULL;
  235. /*
  236. create a txt-file with parsedown-array.
  237. you will have .md and .txt file.
  238. scan folder with option to show drafts.
  239. but what is with structure? We use the cached structure, do not forget!!!
  240. if there is a draft, replace the md file with txt-file.
  241. display content: you have to check if md or txt. if txt, then directly open the txt-file.
  242. in here set markdown-file or
  243. set txt-file.
  244. if publish, render txt-content, replace markdown-file, delete txt-file
  245. */
  246. /* initialize pagedown */
  247. /* turn input into array */
  248. /* add input to contentArray */
  249. /* store updated contentArray */
  250. /* transform input to html */
  251. /* send html to client */
  252. }
  253. }