PageRenderTime 67ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/sly/Controller/Mediapool/Base.php

https://bitbucket.org/phoenixh/sallycms-backend
PHP | 431 lines | 312 code | 90 blank | 29 comment | 47 complexity | 44f327858bbc80cad9edb33163fa7458 MD5 | raw file
  1. <?php
  2. /*
  3. * Copyright (c) 2014, webvariants GmbH & Co. KG, http://www.webvariants.de
  4. *
  5. * This file is released under the terms of the MIT license. You can find the
  6. * complete text in the attached LICENSE file or online at:
  7. *
  8. * http://www.opensource.org/licenses/mit-license.php
  9. */
  10. use sly\Assets\Util;
  11. abstract class sly_Controller_Mediapool_Base extends sly_Controller_Backend implements sly_Controller_Interface {
  12. protected $args;
  13. protected $category;
  14. protected $selectBox;
  15. protected $categories = null;
  16. protected $popupHelper;
  17. private $init = false;
  18. protected function init() {
  19. if ($this->init) return;
  20. $this->init = true;
  21. // init custom query string params
  22. $this->initPopupHelper();
  23. // init category filter
  24. $cats = $this->popupHelper->getArgument('categories');
  25. // do NOT use empty(), as '0' is a valid value!
  26. if (strlen($cats) > 0) {
  27. $cats = array_unique(array_map('intval', explode('|', $cats)));
  28. $this->categories = count($cats) === 0 ? null : $cats;
  29. }
  30. $this->getCurrentCategory();
  31. // build navigation
  32. $app = $this->getContainer()->getApplication();
  33. $cur = $app->getCurrentControllerName();
  34. $menu = new sly_Layout_Navigation_Page('');
  35. $values = $this->popupHelper->getValues();
  36. $menu->addSubpage('mediapool', t('media_list'));
  37. $menu->addSubpage('mediapool_upload', t('upload_file'));
  38. if ($this->isMediaAdmin()) {
  39. $menu->addSubpage('mediapool_structure', t('categories'));
  40. $menu->addSubpage('mediapool_sync', t('sync_files'));
  41. }
  42. if ($this->canRestore() || $this->canDeletePermanent()) {
  43. $menu->addSubpage('mediapool_trash', t('recycle_bin'));
  44. }
  45. if (!empty($values)) {
  46. foreach ($menu->getSubpages() as $sp) {
  47. $sp->setExtraParams($values);
  48. // ignore the extra params when detecting the current page
  49. if ($cur === $sp->getPageParam()) $sp->forceStatus(true);
  50. }
  51. }
  52. $layout = $this->getContainer()->getLayout();
  53. $layout->showNavigation(false);
  54. $layout->pageHeader(t('media_list'), $menu);
  55. $layout->setBodyAttr('class', 'sly-popup sly-mediapool');
  56. $this->render('mediapool/javascript.phtml', array(), false);
  57. }
  58. protected function initPopupHelper() {
  59. $request = $this->getRequest();
  60. $dispatcher = $this->container->getDispatcher();
  61. // init custom query string params
  62. $params = array('callback' => 'string', 'args' => 'array');
  63. $this->popupHelper = new sly_Helper_Popup($params, 'SLY_MEDIAPOOL_URL_PARAMS');
  64. $this->popupHelper->init($request, $dispatcher);
  65. }
  66. protected function appendQueryString($url, $separator = '&amp;') {
  67. return $this->popupHelper->appendQueryString($url, $separator);
  68. }
  69. protected function appendParamsToForm(sly_Form $form, $appendToAction = false) {
  70. return $this->popupHelper->appendParamsToForm($form, $appendToAction);
  71. }
  72. protected function getCurrentCategory() {
  73. if ($this->category === null) {
  74. $request = $this->getRequest();
  75. $category = $request->request('category', 'int', -1);
  76. $service = $this->getContainer()->getMediaCategoryService();
  77. $session = $this->getContainer()->getSession();
  78. if ($category === -1) {
  79. $category = $session->get('sly-media-category', 'int', 0);
  80. }
  81. // respect category filter
  82. if (!empty($this->categories) && !in_array($category, $this->categories)) {
  83. $category = reset($this->categories);
  84. }
  85. $category = $service->findById($category);
  86. $category = $category ? $category->getId() : 0;
  87. $session->set('sly-media-category', $category);
  88. $this->category = $category;
  89. }
  90. return $this->category;
  91. }
  92. protected function getOpenerLink(sly_Model_Medium $file) {
  93. $link = '';
  94. $callback = $this->popupHelper->get('callback');
  95. if (!empty($callback)) {
  96. $filename = $file->getFilename();
  97. $title = $file->getTitle();
  98. $link = '<a href="#" data-filename="'.sly_html($filename).'" data-title="'.sly_html($title).'">'.t('apply_file').'</a>';
  99. }
  100. return $link;
  101. }
  102. protected function deleteMedium(sly_Model_Medium $medium, sly_Util_FlashMessage $msg) {
  103. $filename = $medium->getFileName();
  104. $user = $this->getCurrentUser();
  105. $service = $this->getContainer()->getMediumService();
  106. if ($this->canAccessCategory($medium->getCategoryId())) {
  107. $usages = $this->isInUse($medium);
  108. $blocked = false;
  109. if ($usages !== false) {
  110. $tmp = array();
  111. foreach ($usages as $usage) {
  112. $title = sly_html($usage['title']);
  113. if (isset($usage['type']) && $usage['type'] === 'sly-article') {
  114. $blocked = $blocked && $usage['object']->isOnline();
  115. $title .= $usage['object']->isOnline() ? '' : ' ('.t('status_offline').')';
  116. }
  117. else {
  118. $blocked = true;
  119. }
  120. if (!empty($usage['link'])) {
  121. $tmp[] = '<li><a class="sly-blank" target="_blank" href="'.$usage['link'].'">'.$title.'</a></li>';
  122. }
  123. else {
  124. $tmp[] = '<li>'.$title.'</li>';
  125. }
  126. }
  127. if ($blocked) {
  128. array_unshift($tmp, t('file_is_in_use_blocked', $filename));
  129. }
  130. else {
  131. array_unshift($tmp, t('file_is_in_use', $filename));
  132. }
  133. array_unshift($tmp, '<ul>');
  134. $tmp[] = '</ul>';
  135. $msg->appendWarning(implode("\n", $tmp));
  136. }
  137. if ($blocked === false) {
  138. try {
  139. $service->deleteByMedium($medium);
  140. $msg->appendInfo($filename.': '.t('medium_deleted'));
  141. }
  142. catch (sly_Exception $e) {
  143. $msg->appendWarning($filename.': '.$e->getMessage());
  144. }
  145. }
  146. }
  147. else {
  148. $msg->appendWarning($filename.': '.t('no_permission'));
  149. }
  150. }
  151. public function checkPermission($action) {
  152. $user = $this->getCurrentUser();
  153. if (!$user || (!$user->isAdmin() && !$user->hasRight('pages', 'mediapool'))) {
  154. return false;
  155. }
  156. if ($action === 'batch') {
  157. sly_Util_Csrf::checkToken();
  158. }
  159. return true;
  160. }
  161. protected function isMediaAdmin() {
  162. $user = $this->getCurrentUser();
  163. return $user->isAdmin() || $user->hasRight('mediacategory', 'access', sly_Authorisation_ListProvider::ALL);
  164. }
  165. protected function canAccessFile(sly_Model_Medium $medium) {
  166. return $this->canAccessCategory($medium->getCategoryId());
  167. }
  168. protected function canAccessCategory($cat) {
  169. $user = $this->getCurrentUser();
  170. return $this->isMediaAdmin() || $user->hasRight('mediacategory', 'access', intval($cat));
  171. }
  172. protected function getCategorySelect() {
  173. $user = $this->getCurrentUser();
  174. if ($this->selectBox === null) {
  175. $this->selectBox = sly_Backend_Form_Helper::getMediaCategorySelect('category', null, $user);
  176. $this->selectBox->setLabel(t('categories'));
  177. $this->selectBox->setMultiple(false);
  178. $this->selectBox->setAttribute('value', $this->getCurrentCategory());
  179. // filter categories
  180. if (!empty($this->categories)) {
  181. $values = array_keys($this->selectBox->getValues());
  182. foreach ($values as $catID) {
  183. if (!in_array($catID, $this->categories)) {
  184. $this->selectBox->removeValue($catID);
  185. }
  186. }
  187. }
  188. }
  189. return $this->selectBox;
  190. }
  191. protected function getDimensions($width, $height, $maxWidth, $maxHeight) {
  192. if ($width > $maxWidth) {
  193. $factor = (float) $maxWidth / $width;
  194. $width = $maxWidth;
  195. $height *= $factor;
  196. }
  197. if ($height > $maxHeight) {
  198. $factor = (float) $maxHeight / $height;
  199. $height = $maxHeight;
  200. $width *= $factor;
  201. }
  202. return array(ceil($width), ceil($height));
  203. }
  204. protected function getMimeIcon(sly_Model_Medium $medium) {
  205. $mapping = array(
  206. 'compressed' => array('gz', 'gzip', 'tar', 'zip', 'tgz', 'bz', 'bz2', '7zip', '7z', 'rar'),
  207. 'audio' => array('mp3', 'flac', 'aac', 'wav', 'ac3', 'ogg', 'wma'),
  208. 'document' => array('doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'odt', 'rtf'),
  209. 'executable' => array('sh', 'exe', 'bin', 'com', 'bat'),
  210. 'pdf' => array('pdf'),
  211. 'text' => array('txt', 'java', 'css', 'markdown', 'textile', 'md'),
  212. 'vector' => array('svg', 'eps'),
  213. 'video' => array('mkv', 'avi', 'swf', 'mov', 'flv', 'ogv', 'vp8')
  214. );
  215. $extension = $medium->getExtension();
  216. $base = 'sly-mime-icon-';
  217. if (!$medium->exists()) {
  218. // @edge css instead of images
  219. // return Util::appUri($base.'missing.png');
  220. return '&times;';
  221. }
  222. foreach ($mapping as $type => $exts) {
  223. if (in_array($extension, $exts, true)) {
  224. // @edge css instead of images
  225. // return Util::appUri($base.$type.'.png');
  226. return $type;
  227. }
  228. }
  229. // @edge css instead of images
  230. // return Util::appUri($base.'unknown.png');
  231. return '&hellip;';
  232. }
  233. protected function isImage(sly_Model_Medium $medium) {
  234. static $exts = array('gif', 'jpeg', 'jpg', 'png', 'webp');
  235. return in_array($medium->getExtension(), $exts);
  236. }
  237. protected function getThumbnailTag(sly_Model_Medium $medium, $width, $height) {
  238. if (!$medium->exists()) {
  239. // @edge use css instead of images
  240. // $thumbnail = '<img src="'.$this->getMimeIcon($medium).'" width="44" height="38" alt="'.ht('file_not_found').'" />';
  241. $thumbnail = '<span class="sly-mime-icon-'.$this->getMimeIcon($medium).'" data-mime-type="'.$this->getMimeIcon($medium).'"></span>';
  242. }
  243. else {
  244. $icon_src = $this->getMimeIcon($medium);
  245. $alt = $medium->getTitle();
  246. // @edge use css instead of images
  247. // $thumbnail = '<img src="'.$icon_src.'" alt="'.sly_html($alt).'" title="'.sly_html($alt).'" />';
  248. $thumbnail = '<span class="sly-mime-icon-'.$this->getMimeIcon($medium).'" data-mime-type="'.$this->getMimeIcon($medium).'"></span>';
  249. if ($this->isImage($medium)) {
  250. $mwidth = $medium->getWidth();
  251. $mheight = $medium->getHeight();
  252. $timestamp = $medium->getUpdateDate();
  253. $encoded = urlencode($medium->getFilename());
  254. list($width, $height) = $this->getDimensions($mwidth, $mheight, $width, $height);
  255. $attrs = array(
  256. 'alt' => $alt,
  257. 'title' => $alt,
  258. // 'width' => $width, // @edge no fixed image sizes - use css
  259. // 'height' => $height, // @edge no fixed image sizes - use css
  260. 'src' => sly\Assets\Util::mediapoolUri($encoded.'?t='.$timestamp)
  261. );
  262. $thumbnail = '<img '.sly_Util_HTML::buildAttributeString($attrs, array('alt')).' />';
  263. }
  264. }
  265. $dispatcher = $this->getContainer()->getDispatcher();
  266. $thumbnail = $dispatcher->filter('SLY_BACKEND_MEDIAPOOL_THUMBNAIL', $thumbnail, array(
  267. 'medium' => $medium,
  268. 'width' => $width,
  269. 'height' => $height,
  270. 'isImage' => $this->isImage($medium)
  271. ));
  272. return $thumbnail;
  273. }
  274. protected function isInUse(sly_Model_Medium $medium) {
  275. $container = $this->getContainer();
  276. $service = $container->getMediumService();
  277. $router = $container->getApplication()->getRouter();
  278. $usages = $service->getUsages($medium);
  279. foreach ($usages as $idx => $usage) {
  280. // properly setup object
  281. if (!empty($usage['link']) && !empty($usage['title'])) {
  282. continue;
  283. }
  284. switch ($usage['type']) {
  285. case 'sly-article':
  286. $article = $usage['object'];
  287. $title = $article->getName();
  288. $link = $router->getPlainUrl('content', null, array(
  289. 'article_id' => $article->getId(),
  290. 'clang' => $article->getClang(),
  291. 'revision' => $article->getRevision()
  292. ));
  293. break;
  294. case 'sly-category':
  295. $category = $usage['object'];
  296. $title = $category->getCatName();
  297. $link = $router->getPlainUrl('structure', null, array(
  298. 'category_id' => $category->getId(),
  299. 'clang' => $category->getClang()
  300. ));
  301. break;
  302. case 'sly-medium':
  303. $medium = $usage['object'];
  304. $title = $medium->getTitle();
  305. $link = $router->getPlainUrl('mediapool_detail', null, array('file_id' => $medium->getId()));
  306. break;
  307. case 'sly-user':
  308. $user = $usage['object'];
  309. $title = $obj->getName()?: $obj->getLogin();
  310. $link = $router->getPlainUrl('user', 'edit', array('id' => $user->getId()));
  311. }
  312. $usages[$idx]['link'] = $link;
  313. $usages[$idx]['title'] = $title;
  314. }
  315. return empty($usages) ? false : $usages;
  316. }
  317. protected function redirect($params = array(), $page = null, $code = 302) {
  318. if (!$this->popupHelper) {
  319. $this->initPopupHelper();
  320. }
  321. $values = $this->popupHelper->getValues();
  322. $params = array_merge($values, sly_makeArray($params));
  323. $this->container->getApplication()->redirect($page, $params, $code);
  324. }
  325. protected function redirectResponse($params = array(), $controller = null, $action = null, $code = 302) {
  326. if (!$this->popupHelper) {
  327. $this->initPopupHelper();
  328. }
  329. $values = $this->popupHelper->getValues();
  330. $params = array_merge($values, sly_makeArray($params));
  331. return $this->container->getApplication()->redirectResponse($controller, $action, $params, $code);
  332. }
  333. protected function canDeletePermanent() {
  334. $user = $this->getCurrentUser();
  335. return $user->isAdmin() || $user->hasPermission('media', 'delete_permanent');
  336. }
  337. protected function canRestore() {
  338. $user = $this->getCurrentUser();
  339. return $user->isAdmin() || $user->hasPermission('media', 'restore');
  340. }
  341. }