summaryrefslogtreecommitdiff
path: root/app/Controller
diff options
context:
space:
mode:
Diffstat (limited to 'app/Controller')
-rw-r--r--app/Controller/AvatarFile.php92
-rw-r--r--app/Controller/Doc.php83
-rw-r--r--app/Controller/FileViewer.php26
3 files changed, 166 insertions, 35 deletions
diff --git a/app/Controller/AvatarFile.php b/app/Controller/AvatarFile.php
new file mode 100644
index 00000000..a47cca66
--- /dev/null
+++ b/app/Controller/AvatarFile.php
@@ -0,0 +1,92 @@
+<?php
+
+namespace Kanboard\Controller;
+
+use Kanboard\Core\ObjectStorage\ObjectStorageException;
+use Kanboard\Core\Thumbnail;
+
+/**
+ * Avatar File Controller
+ *
+ * @package controller
+ * @author Frederic Guillot
+ */
+class AvatarFile extends Base
+{
+ /**
+ * Display avatar page
+ */
+ public function show()
+ {
+ $user = $this->getUser();
+
+ $this->response->html($this->helper->layout->user('avatar_file/show', array(
+ 'user' => $user,
+ )));
+ }
+
+ /**
+ * Upload Avatar
+ */
+ public function upload()
+ {
+ $user = $this->getUser();
+
+ if (! $this->avatarFile->uploadFile($user['id'], $this->request->getFileInfo('avatar'))) {
+ $this->flash->failure(t('Unable to upload the file.'));
+ }
+
+ $this->response->redirect($this->helper->url->to('AvatarFile', 'show', array('user_id' => $user['id'])));
+ }
+
+ /**
+ * Remove Avatar image
+ */
+ public function remove()
+ {
+ $this->checkCSRFParam();
+ $user = $this->getUser();
+ $this->avatarFile->remove($user['id']);
+ $this->response->redirect($this->helper->url->to('AvatarFile', 'show', array('user_id' => $user['id'])));
+ }
+
+ /**
+ * Show Avatar image (public)
+ */
+ public function image()
+ {
+ $user_id = $this->request->getIntegerParam('user_id');
+ $size = $this->request->getStringParam('size', 48);
+ $filename = $this->avatarFile->getFilename($user_id);
+ $etag = md5($filename.$size);
+
+ $this->response->cache(365 * 86400, $etag);
+ $this->response->contentType('image/jpeg');
+
+ if ($this->request->getHeader('If-None-Match') !== '"'.$etag.'"') {
+ $this->render($filename, $size);
+ } else {
+ $this->response->status(304);
+ }
+ }
+
+ /**
+ * Render thumbnail from object storage
+ *
+ * @access private
+ * @param string $filename
+ * @param integer $size
+ */
+ private function render($filename, $size)
+ {
+ try {
+ $blob = $this->objectStorage->get($filename);
+
+ Thumbnail::createFromString($blob)
+ ->resize($size, $size)
+ ->toOutput();
+ } catch (ObjectStorageException $e) {
+ $this->logger->error($e->getMessage());
+ }
+ }
+}
diff --git a/app/Controller/Doc.php b/app/Controller/Doc.php
index f85326ac..9164c6b9 100644
--- a/app/Controller/Doc.php
+++ b/app/Controller/Doc.php
@@ -5,54 +5,32 @@ namespace Kanboard\Controller;
use Parsedown;
/**
- * Documentation controller
+ * Documentation Viewer
*
* @package controller
* @author Frederic Guillot
*/
class Doc extends Base
{
- private function readFile($filename)
- {
- $url = $this->helper->url;
- $data = file_get_contents($filename);
- list($title, ) = explode("\n", $data, 2);
-
- $replaceUrl = function (array $matches) use ($url) {
- return '('.$url->to('doc', 'show', array('file' => str_replace('.markdown', '', $matches[1]))).')';
- };
-
- $content = preg_replace_callback('/\((.*.markdown)\)/', $replaceUrl, $data);
-
- return array(
- 'content' => Parsedown::instance()->text($content),
- 'title' => $title !== 'Documentation' ? t('Documentation: %s', $title) : $title,
- );
- }
-
public function show()
{
$page = $this->request->getStringParam('file', 'index');
- if (! preg_match('/^[a-z0-9\-]+/', $page)) {
+ if (!preg_match('/^[a-z0-9\-]+/', $page)) {
$page = 'index';
}
- $filenames = array(__DIR__.'/../../doc/'.$page.'.markdown');
- $filename = __DIR__.'/../../doc/index.markdown';
-
if ($this->config->getCurrentLanguage() === 'fr_FR') {
- array_unshift($filenames, __DIR__.'/../../doc/fr/'.$page.'.markdown');
+ $filename = __DIR__.'/../../doc/fr/' . $page . '.markdown';
+ } else {
+ $filename = __DIR__ . '/../../doc/' . $page . '.markdown';
}
- foreach ($filenames as $file) {
- if (file_exists($file)) {
- $filename = $file;
- break;
- }
+ if (!file_exists($filename)) {
+ $filename = __DIR__.'/../../doc/index.markdown';
}
- $this->response->html($this->helper->layout->app('doc/show', $this->readFile($filename)));
+ $this->response->html($this->helper->layout->app('doc/show', $this->render($filename)));
}
/**
@@ -62,4 +40,49 @@ class Doc extends Base
{
$this->response->html($this->template->render('config/keyboard_shortcuts'));
}
+
+ /**
+ * Prepare Markdown file
+ *
+ * @access private
+ * @param string $filename
+ * @return array
+ */
+ private function render($filename)
+ {
+ $data = file_get_contents($filename);
+ $content = preg_replace_callback('/\((.*.markdown)\)/', array($this, 'replaceMarkdownUrl'), $data);
+ $content = preg_replace_callback('/\((screenshots.*\.png)\)/', array($this, 'replaceImageUrl'), $content);
+
+ list($title, ) = explode("\n", $data, 2);
+
+ return array(
+ 'content' => Parsedown::instance()->text($content),
+ 'title' => $title !== 'Documentation' ? t('Documentation: %s', $title) : $title,
+ );
+ }
+
+ /**
+ * Regex callback to replace Markdown links
+ *
+ * @access public
+ * @param array $matches
+ * @return string
+ */
+ public function replaceMarkdownUrl(array $matches)
+ {
+ return '('.$this->helper->url->to('doc', 'show', array('file' => str_replace('.markdown', '', $matches[1]))).')';
+ }
+
+ /**
+ * Regex callback to replace image links
+ *
+ * @access public
+ * @param array $matches
+ * @return string
+ */
+ public function replaceImageUrl(array $matches)
+ {
+ return '('.$this->helper->url->base().'doc/'.$matches[1].')';
+ }
}
diff --git a/app/Controller/FileViewer.php b/app/Controller/FileViewer.php
index bc91c3d8..3be4ea14 100644
--- a/app/Controller/FileViewer.php
+++ b/app/Controller/FileViewer.php
@@ -66,9 +66,16 @@ class FileViewer extends Base
*/
public function image()
{
+ $file = $this->getFile();
+ $etag = md5($file['path']);
+ $this->response->contentType($this->helper->file->getImageMimeType($file['name']));
+ $this->response->cache(5 * 86400, $etag);
+
+ if ($this->request->getHeader('If-None-Match') === '"'.$etag.'"') {
+ return $this->response->status(304);
+ }
+
try {
- $file = $this->getFile();
- $this->response->contentType($this->helper->file->getImageMimeType($file['name']));
$this->objectStorage->output($file['path']);
} catch (ObjectStorageException $e) {
$this->logger->error($e->getMessage());
@@ -82,12 +89,21 @@ class FileViewer extends Base
*/
public function thumbnail()
{
+ $file = $this->getFile();
+ $model = $file['model'];
+ $filename = $this->$model->getThumbnailPath($file['path']);
+ $etag = md5($filename);
+
+ $this->response->cache(5 * 86400, $etag);
$this->response->contentType('image/jpeg');
+ if ($this->request->getHeader('If-None-Match') === '"'.$etag.'"') {
+ return $this->response->status(304);
+ }
+
try {
- $file = $this->getFile();
- $model = $file['model'];
- $this->objectStorage->output($this->$model->getThumbnailPath($file['path']));
+
+ $this->objectStorage->output($filename);
} catch (ObjectStorageException $e) {
$this->logger->error($e->getMessage());