PageRenderTime 53ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/app/Module/Filebrowser/Controller.php

https://github.com/stackboxcms/stackboxcms
PHP | 313 lines | 174 code | 54 blank | 85 comment | 25 complexity | fecc67ac3f9d2b6c5bf5a19b1e015a15 MD5 | raw file
  1. <?php
  2. namespace Module\Filebrowser;
  3. use Alloy, Stackbox;
  4. use Imagine, Imagine\Image;
  5. /**
  6. * Filebrowser Controller
  7. */
  8. class Controller extends Stackbox\Module\ControllerAbstract
  9. {
  10. // So template helper knows where to find views... (not in standard modules directory at www/content)
  11. protected $_path = __DIR__;
  12. /**
  13. * Ensure user is logged-in to see ANY of this module
  14. */
  15. public function init($action = null)
  16. {
  17. // Always allow images to be resized (even for visitors - no auth)
  18. if('imageSizeAction' == $action || 'imageSize' == $action) {
  19. return;
  20. }
  21. $user = \Kernel()->user();
  22. if(!$user || !$user->isLoggedIn()) {
  23. throw new Alloy\Exception\Auth("User must be logged in to view files");
  24. }
  25. }
  26. /**
  27. * @method GET
  28. */
  29. public function indexAction(Alloy\Request $request)
  30. {
  31. return false;
  32. }
  33. /**
  34. * List all images
  35. * @method GET
  36. */
  37. public function imagesAction(Alloy\Request $request)
  38. {
  39. $kernel = $this->kernel;
  40. $request = $kernel->request();
  41. $user = $kernel->user();
  42. // Ensure proper directories exist and are writable
  43. $dir = \Kernel()->config('cms.path.files') . 'images/';
  44. $this->ensureDirectoryAvailable($dir);
  45. return $this->template('directoryList')
  46. ->set(array('directory' => $dir))
  47. ->layout('ajax');
  48. }
  49. /**
  50. * List all other files
  51. * @method GET
  52. */
  53. public function filesAction(Alloy\Request $request)
  54. {
  55. $kernel = $this->kernel;
  56. $request = $kernel->request();
  57. $user = $kernel->user();
  58. // Ensure proper directories exist and are writable
  59. $dir = \Kernel()->config('cms.path.files') . 'files/';
  60. $this->ensureDirectoryAvailable($dir);
  61. return $this->template('directoryList')
  62. ->set(array('directory' => $dir))
  63. ->layout('ajax');
  64. }
  65. /**
  66. * Resize and save image on the fly
  67. * @method GET
  68. */
  69. public function imageSizeAction(Alloy\Request $request)
  70. {
  71. $kernel = $this->kernel;
  72. $request = $kernel->request();
  73. $user = $kernel->user();
  74. // Ensure proper directories exist and are writable
  75. $dir = \Kernel()->config('cms.path.files') . 'images';
  76. $this->ensureDirectoryAvailable($dir);
  77. // Sort out request data
  78. $image = $request->image;
  79. $width = (int) $request->width;
  80. $height = (int) $request->height;
  81. $imagePath = realpath(dirname($dir . '/' . $image));
  82. // Ensure directory is beginning part of fully expanded path (security issues with '../' in path)
  83. if(0 !== strpos($imagePath, $dir)) {
  84. return false;
  85. }
  86. // Ensure image file exists
  87. if(!file_exists($imagePath . '/' . $image)) {
  88. return false;
  89. }
  90. // Ensure resize directory exists and is writable
  91. $resizeDir = $dir . '/_size/' . $width . 'x' . $height . '/';
  92. $this->ensureDirectoryAvailable(dirname($resizeDir . $image));
  93. // Resize to requested width/height
  94. $image = $kernel->imagine()
  95. ->open($imagePath . '/' . $image)
  96. ->thumbnail(new Imagine\Image\Box($width, $height), Imagine\Image\ImageInterface::THUMBNAIL_INSET)
  97. ->save($resizeDir . $image);
  98. // Send image content to browser
  99. header('Content-type: image/png');
  100. echo $image->get('png');
  101. exit();
  102. }
  103. /**
  104. * Form to create a new page
  105. * @method GET
  106. */
  107. public function newAction(Alloy\Request $request)
  108. {
  109. return $this->template(__FUNCTION__);
  110. }
  111. /**
  112. * @method GET
  113. */
  114. public function editAction(Alloy\Request $request)
  115. {
  116. $kernel = $this->kernel;
  117. // Ensure page exists
  118. $mapper = $this->kernel->mapper('Module\Page\Mapper');
  119. $page = $mapper->getPageByUrl($request->page);
  120. if(!$page) {
  121. throw new \Alloy\Exception_FileNotFound("Page not found: '" . $request->page . "'");
  122. }
  123. return $this->newAction($request)
  124. ->data($page->data());
  125. }
  126. /**
  127. * New file upload
  128. * @method POST
  129. */
  130. public function postMethod(Alloy\Request $request)
  131. {
  132. $kernel = \Kernel();
  133. $mapper = $kernel->mapper();
  134. $user = $kernel->user();
  135. // Upload File
  136. // ===========================================================================
  137. $saveResult = false;
  138. // Project file path (full root path)
  139. $uploadDir = $kernel->config('cms.path.files');
  140. // @todo Support multiple file uploads
  141. $subDir = 'files';
  142. if(isset($_FILES['upload'])) {
  143. $fileData = $_FILES['upload'];
  144. $fileName = $kernel->formatUrl($fileData['name']);
  145. $fileName = substr($fileName, 0, strrpos($fileName, '-')) . strrchr($fileData['name'], '.');
  146. // May want to take into account all the file upload errors...
  147. // @link http://us3.php.net/manual/en/features.file-upload.errors.php
  148. if($fileData['error'] == UPLOAD_ERR_OK) {
  149. // See if file is image or not
  150. if(false !== strpos($fileData['type'], 'image')) {
  151. $subDir = 'images';
  152. }
  153. // Attempt to move file to new location
  154. $uploadDir .= $subDir; // 'images' or 'files'
  155. // Save file to new location
  156. $this->ensureDirectoryAvailable($uploadDir);
  157. if(move_uploaded_file($fileData['tmp_name'], $uploadDir . '/' . $fileName)) {
  158. $saveResult = true;
  159. }
  160. }
  161. }
  162. // ===========================================================================
  163. if($saveResult) {
  164. // Redirect to images or files
  165. if($subDir = 'images') {
  166. return $kernel->redirect($kernel->url(array('action' => 'images'), 'filebrowser', $request->query()));
  167. }
  168. return $kernel->redirect($kernel->url(array('action' => 'files'), 'filebrowser', $request->query()));
  169. } else {
  170. return $kernel->resource()
  171. ->status(400)
  172. ->errors(array(
  173. 'file' => array('Unable to upload file')
  174. ));
  175. }
  176. return $kernel->redirect($kernel->url(array('action' => 'images'), 'filebrowser', $request->query()));
  177. }
  178. public function postAction($request)
  179. {
  180. if($request->isPost()) {
  181. return $this->postMethod($request);
  182. }
  183. return false;
  184. }
  185. /**
  186. * Display delete confirmation
  187. * @method GET
  188. */
  189. public function deleteAction(Alloy\Request $request)
  190. {
  191. if($request->format == 'html') {
  192. $view = new \Alloy\View\Generic\Form('form');
  193. $form = $view
  194. ->method('delete')
  195. ->action($this->kernel->url(array('page' => $request->page), 'page'))
  196. ->submitButtonText('Delete');
  197. return "<p>Are you sure you want to delete this file?</p>" . $form;
  198. }
  199. return false;
  200. }
  201. /**
  202. * Delete file
  203. * @method DELETE
  204. */
  205. public function deleteMethod(Alloy\Request $request)
  206. {
  207. }
  208. /**
  209. * Install Module
  210. *
  211. * @see \Stackbox\Module\ControllerAbstract
  212. */
  213. public function install($action = null, array $params = array())
  214. {
  215. // Ensure proper directories exist and are writable
  216. $uploadDir = \Kernel()->config('cms.path.uploads');
  217. $imagesDir = $uploadDir . 'images/';
  218. $filesDir = $uploadDir . 'files/';
  219. $this->ensureDirectoryAvailable($imagesDir);
  220. $this->ensureDirectoryAvailable($filesDir);
  221. }
  222. /**
  223. * Uninstall Module
  224. *
  225. * @see \Stackbox\Module\ControllerAbstract
  226. */
  227. public function uninstall()
  228. {
  229. }
  230. /**
  231. * Kind of helper function to ensure the proper directories exist and are writable.
  232. *
  233. * Private because this particular implementation may be changed soon.
  234. * Not sure I like a helper function on a controller...
  235. *
  236. * @throws \Exception
  237. */
  238. private function ensureDirectoryAvailable($dir, $chmod = 0755)
  239. {
  240. // Directory exists?
  241. $dirAvailable = false;
  242. if(is_dir($dir)) {
  243. $dirAvailable = true;
  244. } else {
  245. $dirAvailable = mkdir($dir, $chmod, true);
  246. }
  247. // Directory is writeable?
  248. if($dirAvailable && !is_writable($dir)) {
  249. $dirAvailable = chmod($dir, $chmod);
  250. }
  251. // Exception if not available
  252. if(!$dirAvailable) {
  253. throw new \Exception("Unable to ensure directory exists and are writable.\n
  254. Directory: " . $dir . "\n
  255. ");
  256. }
  257. return $dirAvailable;
  258. }
  259. }