SproutCMS

This is the code documentation for the SproutCMS project

source of /sprout/Widgets/ImageGalleryWidget.php

  1. <?php
  2. /*
  3.  * Copyright (C) 2017 Karmabunny Pty Ltd.
  4.  *
  5.  * This file is a part of SproutCMS.
  6.  *
  7.  * SproutCMS is free software: you can redistribute it and/or modify it under the terms
  8.  * of the GNU General Public License as published by the Free Software Foundation, either
  9.  * version 2 of the License, or (at your option) any later version.
  10.  *
  11.  * For more information, visit <http://getsproutcms.com>.
  12.  */
  13.  
  14. namespace Sprout\Widgets;
  15.  
  16. use Kohana;
  17.  
  18. use Sprout\Helpers\FileConstants;
  19. use Sprout\Helpers\Pdb;
  20. use Sprout\Helpers\View;
  21. use Sprout\Helpers\WidgetArea;
  22. use Sprout\Helpers\Widgets;
  23.  
  24.  
  25. /**
  26. * Shows a list of pages that are related to this one
  27. **/
  28. class ImageGalleryWidget extends Widget
  29. {
  30. protected $friendly_name = "Image Gallery";
  31. protected $friendly_desc = 'A gallery of images from your media repository';
  32. protected $default_settings = [
  33. 'limit' => 100,
  34. 'captions' => 1,
  35. 'order' => 1,
  36. ];
  37. public $classname = 'ImageGallery';
  38.  
  39. private $order_opts = array(
  40. 1 => 'Date (most recent at top)',
  41. 2 => 'Date (oldest at top)',
  42. 3 => 'Alphabetical by name',
  43. 4 => 'Alphabetical (reverse)',
  44. 5 => 'Manual (in category options)',
  45. 6 => 'Stable random',
  46. 7 => 'True random',
  47. );
  48.  
  49. // Thumbnail cropping directions
  50. private $crop_opts = array(
  51. 'lt' => 'Top left',
  52. 'ct' => 'Top center',
  53. 'rt' => 'Top right',
  54. 'lc' => 'Middle left',
  55. 'cc' => 'Middle center',
  56. 'rc' => 'Middle right',
  57. 'lb' => 'Bottom left',
  58. 'cb' => 'Bottom center',
  59. 'rb' => 'Bottom right',
  60. );
  61.  
  62. // Whether this widget displays as grid or slider
  63. private $display_opts = array(
  64. 'grid' => 'Gallery',
  65. 'slider' => 'Slider',
  66. );
  67.  
  68.  
  69. /**
  70.   * Validate and cleanup the settings fields
  71.   * @param bool True on success false on failure
  72.   **/
  73. private function validateSettings()
  74. {
  75. $this->settings['category'] = (int) @$this->settings['category'];
  76. if ($this->settings['category'] <= 0) return false;
  77.  
  78. $this->settings['limit'] = (int) @$this->settings['limit'];
  79. if ($this->settings['limit'] <= 0) $this->settings['limit'] = 100;
  80.  
  81. $this->settings['captions'] = (@$this->settings['captions'] == 1);
  82.  
  83. $this->settings['order'] = (int) @$this->settings['order'];
  84. if ($this->settings['order'] <= 0) $this->settings['order'] = 1;
  85.  
  86. $this->settings['thumb_rows'] = (int) @$this->settings['thumb_rows'];
  87. if ($this->settings['thumb_rows'] < 2) $this->settings['thumb_rows'] = 5;
  88.  
  89. $this->settings['num_images'] = (int) @$this->settings['num_images'];
  90. if ($this->settings['num_images'] < 1) $this->settings['num_images'] = 1;
  91.  
  92. if (empty($this->settings['cropping']) or !array_key_exists($this->settings['cropping'], $this->crop_opts)) {
  93. $this->settings['cropping'] = 'cc';
  94. }
  95.  
  96. if (empty($this->settings['display_opts']) or !array_key_exists($this->settings['display_opts'], $this->display_opts)) {
  97. $this->settings['display_opts'] = 'grid';
  98. }
  99.  
  100. $this->settings['slider_dots'] = (int) @$this->settings['slider_dots'];
  101. $this->settings['slider_arrows'] = (int) @$this->settings['slider_arrows'];
  102. $this->settings['slider_autoplay'] = (int) @$this->settings['slider_autoplay'];
  103. $this->settings['slider_speed'] = (int) @$this->settings['slider_speed'];
  104.  
  105. if ($this->settings['slider_speed'] <= 0) {
  106. $this->settings['slider_speed'] = 3;
  107. }
  108.  
  109. return true;
  110. }
  111.  
  112.  
  113. /**
  114.   * Does the front-end rendering of this widget
  115.   *
  116.   * @param int $orientation The orientation of the widget
  117.   **/
  118. public function render($orientation)
  119. {
  120. if (!$this->validateSettings()) return null;
  121.  
  122. if ($this->settings['limit'] > 0) {
  123. $limit = 'LIMIT ' . $this->settings['limit'];
  124. } else {
  125. $limit = 'LIMIT 100';
  126. }
  127.  
  128. // Load the files from the database
  129. $order = $this->orderSql($this->settings['order']);
  130. $q = "SELECT
  131. files.name,
  132. files.filename,
  133. files.description
  134. FROM ~files AS files
  135. INNER JOIN ~files_cat_join AS joiner
  136. ON joiner.file_id = files.id
  137. WHERE joiner.cat_id = ?
  138. ORDER BY {$order}
  139. {$limit}";
  140. $res = Pdb::query($q, [$this->settings['category']], 'arr');
  141.  
  142. // Filter to allow only jpg files
  143. $images = array();
  144. foreach ($res as $row) {
  145. if (strpos($row['filename'], 'jpg') !== false or strpos($row['filename'], 'jpeg') !== false) {
  146. $images[] = $row;
  147. }
  148. }
  149.  
  150. // Load configuration details from sprout skin config if present
  151. $config = Kohana::config('sprout.image_gallery');
  152. if (! $config) {
  153. $config = array(
  154. 'thumb_size_2' => 'c600x600',
  155. 'thumb_size_3' => 'c400x400',
  156. 'thumb_size_4' => 'c300x300',
  157. 'thumb_size_5' => 'c220x220',
  158. 'full_size' => 'm800x600',
  159. 'slider_size' => 'c800x450',
  160. );
  161. }
  162.  
  163. if ($orientation == WidgetArea::ORIENTATION_TALL) {
  164. $view = new View('sprout/image_gallery_tall_' . $this->settings['display_opts']);
  165. } else {
  166. $view = new View('sprout/image_gallery_wide_' . $this->settings['display_opts']);
  167. }
  168.  
  169. switch ($this->settings['thumb_rows']) {
  170. case 2:
  171. $image_resize = 'thumb_size_2';
  172. break;
  173.  
  174. case 3:
  175. $image_resize = 'thumb_size_3';
  176. break;
  177.  
  178. case 4:
  179. $image_resize = 'thumb_size_4';
  180. break;
  181.  
  182. default:
  183. $image_resize = 'thumb_size_5';
  184. break;
  185. }
  186.  
  187. $view->config = $config;
  188. $view->captions = $this->settings['captions'];
  189. $view->num_thumbs = $this->settings['limit'];
  190. $view->images = $images;
  191. $view->idx = 1;
  192. $view->cropping = $this->settings['cropping'];
  193. $view->row_count = $this->settings['thumb_rows'];
  194. $view->slider_dots = $this->settings['slider_dots'];
  195. $view->slider_arrows = $this->settings['slider_arrows'];
  196. $view->slider_autoplay = $this->settings['slider_autoplay'];
  197. $view->slider_speed = $this->settings['slider_speed'];
  198. $view->slider_images = $this->settings['num_images'];
  199.  
  200. return $view->render();
  201. }
  202.  
  203.  
  204. /**
  205.   * Returns the settings HTML
  206.   **/
  207. public function getSettingsForm()
  208. {
  209. // Get categories
  210. $q = "SELECT cat.id, CONCAT(cat.name, ' (', COUNT(file.id), ')')
  211. FROM ~files_cat_list AS cat
  212. LEFT JOIN ~files_cat_join AS joiner ON cat.id = joiner.cat_id
  213. LEFT JOIN ~files AS file ON joiner.file_id = file.id AND file.type = ?
  214. AND (file.filename LIKE '%.jpg' OR file.filename LIKE '%.jpeg')
  215. GROUP BY cat.id
  216. ORDER BY cat.name";
  217. $cats = Pdb::query($q, [FileConstants::TYPE_IMAGE], 'map');
  218.  
  219. $view = new View('sprout/gallery_widget_settings');
  220. $view->cats = $cats;
  221. $view->ordering = $this->order_opts;
  222. $view->cropping = $this->crop_opts;
  223. $view->display = $this->display_opts;
  224.  
  225. return $view->render();
  226. }
  227.  
  228.  
  229. /**
  230.   * Returns the SQL which should be used for ordering the images
  231.   *
  232.   * @param $order One of the $this->order_opts order types
  233.   **/
  234. private function orderSql($order)
  235. {
  236. switch ($order) {
  237. case 1:
  238. return 'files.date_file_modified DESC';
  239.  
  240. case 2:
  241. return 'files.date_file_modified ASC';
  242.  
  243. case 3:
  244. return 'files.name ASC';
  245.  
  246. case 4:
  247. return 'files.name DESC';
  248.  
  249. case 5:
  250. return 'joiner.record_order ASC';
  251.  
  252. case 6:
  253. return 'MD5(CONCAT(name, filename, date_file_modified)) ASC';
  254.  
  255. case 7:
  256. return 'RAND()';
  257.  
  258. default:
  259. return 'files.id ASC';
  260. }
  261. }
  262.  
  263.  
  264.  
  265. /**
  266.   * Returns a URL for editing the contents of this widget
  267.   * See {@link Widget::getEditUrl} for full documentation
  268.   **/
  269. public function getEditUrl()
  270. {
  271. if (empty($this->settings['category'])) return null;
  272. return 'admin/contents/file?_category_id=' . $this->settings['category'];
  273. }
  274.  
  275.  
  276. /**
  277.   * Returns a label which describes the contents of this widget
  278.   * See {@link Widget::get_info_label} for full documentation
  279.   **/
  280. public function getInfoLabels()
  281. {
  282. if (empty($this->settings['category'])) return null;
  283. $cats = Pdb::lookup('files_cat_list');
  284. return array(
  285. 'Category' => $cats[$this->settings['category']],
  286. 'Order' => $this->order_opts[$this->settings['order']],
  287. );
  288. }
  289.  
  290.  
  291. /**
  292.   * Is there sufficent content to add this addon at the moment?
  293.   * If this widget is not available, a string message should be returned
  294.   * If this widget *is* available, NULL should be returned.
  295.   **/
  296. public function getNotAvailableReason()
  297. {
  298. $cats = Pdb::lookup('files_cat_list');
  299. if (count($cats) == 0) {
  300. return 'No media repository categories found';
  301. }
  302. return NULL;
  303. }
  304.  
  305.  
  306. /**
  307.   * Registered content replacement for embedded gallery via the editor
  308.   *
  309.   * @param string $html HTML content
  310.   * @return string Modified HTML content
  311.   */
  312. public static function contentReplace($html)
  313. {
  314. $pattern = '<div class="sprout-editor--widget sprout-editor--gallery"';
  315. $pattern .= ' data-id="([0-9]+)"';
  316. $pattern .= ' data-max="([0-9]+)"';
  317. $pattern .= ' data-captions="([0-9]+)"';
  318. $pattern .= ' data-crop="([a-z]+)"';
  319. $pattern .= ' data-thumbs="([0-9]+)"';
  320. $pattern .= ' data-type="([a-z]+)"';
  321. $pattern .= ' data-ordering="([0-9]+)"';
  322. $pattern .= ' data-slider-dots="([0-9]+)"';
  323. $pattern .= ' data-slider-arrows="([0-9]+)"';
  324. $pattern .= ' data-slider-autoplay="([0-9]+)"';
  325. $pattern .= ' data-slider-speed="([0-9]+)"';
  326. $pattern .= '>';
  327.  
  328. preg_match_all('/' . $pattern . '/s', $html, $matches, PREG_PATTERN_ORDER);
  329. list($title, $id, $max, $captions, $crop, $thumbs, $type, $ordering, $slider_dots, $slider_arrows, $slider_autoplay, $slider_speed) = $matches;
  330.  
  331. if (!empty($id)) {
  332. for ($i = 0; $i < count($id); $i++) {
  333. $widget = Widgets::render(WidgetArea::ORIENTATION_EMAIL, 'Sprout\Widgets\ImageGalleryWidget', [
  334. 'category' => (int) $id[$i],
  335. 'captions' => (int) $captions[$i],
  336. 'thumb_rows' => (int) $thumbs[$i],
  337. 'cropping' => $crop[$i],
  338. 'limit' => (int) $max[$i],
  339. 'order' => (int) $ordering[$i],
  340. 'display_opts' => $type[$i],
  341. 'slider_dots' => $slider_dots[$i],
  342. 'slider_arrows' => $slider_arrows[$i],
  343. 'slider_autoplay' => $slider_autoplay[$i],
  344. 'slider_speed' => $slider_speed[$i],
  345. ]);
  346.  
  347. $html = preg_replace('/<div class="sprout-editor--widget sprout-editor--gallery" (.*?)<\/div>/s', $widget, $html, 1);
  348. }
  349. }
  350.  
  351. return $html;
  352. }
  353. }
  354.