1<?php 2namespace Fisharebest\Webtrees\Module; 3 4/** 5 * webtrees: online genealogy 6 * Copyright (C) 2015 webtrees development team 7 * This program is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18use Fisharebest\Webtrees\Auth; 19use Fisharebest\Webtrees\Database; 20use Fisharebest\Webtrees\Filter; 21use Fisharebest\Webtrees\Functions\FunctionsEdit; 22use Fisharebest\Webtrees\Functions\FunctionsPrint; 23use Fisharebest\Webtrees\GedcomTag; 24use Fisharebest\Webtrees\I18N; 25use Fisharebest\Webtrees\Media; 26use Fisharebest\Webtrees\Theme; 27 28/** 29 * Class SlideShowModule 30 */ 31class SlideShowModule extends AbstractModule implements ModuleBlockInterface { 32 /** {@inheritdoc} */ 33 public function getTitle() { 34 return /* I18N: Name of a module */ I18N::translate('Slide show'); 35 } 36 37 /** {@inheritdoc} */ 38 public function getDescription() { 39 return /* I18N: Description of the “Slide show” module */ I18N::translate('Random images from the current family tree.'); 40 } 41 42 /** {@inheritdoc} */ 43 public function getBlock($block_id, $template = true, $cfg = null) { 44 global $ctype, $WT_TREE; 45 46 $filter = $this->getBlockSetting($block_id, 'filter', 'all'); 47 $controls = $this->getBlockSetting($block_id, 'controls', '1'); 48 $start = $this->getBlockSetting($block_id, 'start', '0') || Filter::getBool('start'); 49 50 // We can apply the filters using SQL 51 // Do not use "ORDER BY RAND()" - it is very slow on large tables. Use PHP::array_rand() instead. 52 $all_media = Database::prepare( 53 "SELECT m_id FROM `##media`" . 54 " WHERE m_file = ?" . 55 " AND m_ext IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '')" . 56 " AND m_type IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '')" 57 )->execute(array( 58 $WT_TREE->getTreeId(), 59 $this->getBlockSetting($block_id, 'filter_avi', '0') ? 'avi' : null, 60 $this->getBlockSetting($block_id, 'filter_bmp', '1') ? 'bmp' : null, 61 $this->getBlockSetting($block_id, 'filter_gif', '1') ? 'gif' : null, 62 $this->getBlockSetting($block_id, 'filter_jpeg', '1') ? 'jpg' : null, 63 $this->getBlockSetting($block_id, 'filter_jpeg', '1') ? 'jpeg' : null, 64 $this->getBlockSetting($block_id, 'filter_mp3', '0') ? 'mp3' : null, 65 $this->getBlockSetting($block_id, 'filter_ole', '1') ? 'ole' : null, 66 $this->getBlockSetting($block_id, 'filter_pcx', '1') ? 'pcx' : null, 67 $this->getBlockSetting($block_id, 'filter_pdf', '0') ? 'pdf' : null, 68 $this->getBlockSetting($block_id, 'filter_png', '1') ? 'png' : null, 69 $this->getBlockSetting($block_id, 'filter_tiff', '1') ? 'tiff' : null, 70 $this->getBlockSetting($block_id, 'filter_wav', '0') ? 'wav' : null, 71 $this->getBlockSetting($block_id, 'filter_audio', '0') ? 'audio' : null, 72 $this->getBlockSetting($block_id, 'filter_book', '1') ? 'book' : null, 73 $this->getBlockSetting($block_id, 'filter_card', '1') ? 'card' : null, 74 $this->getBlockSetting($block_id, 'filter_certificate', '1') ? 'certificate' : null, 75 $this->getBlockSetting($block_id, 'filter_coat', '1') ? 'coat' : null, 76 $this->getBlockSetting($block_id, 'filter_document', '1') ? 'document' : null, 77 $this->getBlockSetting($block_id, 'filter_electronic', '1') ? 'electronic' : null, 78 $this->getBlockSetting($block_id, 'filter_fiche', '1') ? 'fiche' : null, 79 $this->getBlockSetting($block_id, 'filter_film', '1') ? 'film' : null, 80 $this->getBlockSetting($block_id, 'filter_magazine', '1') ? 'magazine' : null, 81 $this->getBlockSetting($block_id, 'filter_manuscript', '1') ? 'manuscript' : null, 82 $this->getBlockSetting($block_id, 'filter_map', '1') ? 'map' : null, 83 $this->getBlockSetting($block_id, 'filter_newspaper', '1') ? 'newspaper' : null, 84 $this->getBlockSetting($block_id, 'filter_other', '1') ? 'other' : null, 85 $this->getBlockSetting($block_id, 'filter_painting', '1') ? 'painting' : null, 86 $this->getBlockSetting($block_id, 'filter_photo', '1') ? 'photo' : null, 87 $this->getBlockSetting($block_id, 'filter_tombstone', '1') ? 'tombstone' : null, 88 $this->getBlockSetting($block_id, 'filter_video', '0') ? 'video' : null, 89 ))->fetchOneColumn(); 90 91 // Keep looking through the media until a suitable one is found. 92 $random_media = null; 93 while ($all_media) { 94 $n = array_rand($all_media); 95 $media = Media::getInstance($all_media[$n], $WT_TREE); 96 if ($media->canShow() && !$media->isExternal()) { 97 // Check if it is linked to a suitable individual 98 foreach ($media->linkedIndividuals('OBJE') as $indi) { 99 if ( 100 $filter === 'all' || 101 $filter === 'indi' && strpos($indi->getGedcom(), "\n1 OBJE @" . $media->getXref() . '@') !== false || 102 $filter === 'event' && strpos($indi->getGedcom(), "\n2 OBJE @" . $media->getXref() . '@') !== false 103 ) { 104 // Found one :-) 105 $random_media = $media; 106 break 2; 107 } 108 } 109 } 110 unset($all_media[$n]); 111 }; 112 113 $id = $this->getName() . $block_id; 114 $class = $this->getName() . '_block'; 115 if ($ctype === 'gedcom' && Auth::isManager($WT_TREE) || $ctype === 'user' && Auth::check()) { 116 $title = '<a class="icon-admin" title="' . I18N::translate('Configure') . '" href="block_edit.php?block_id=' . $block_id . '&ged=' . $WT_TREE->getNameHtml() . '&ctype=' . $ctype . '"></a>'; 117 } else { 118 $title = ''; 119 } 120 $title .= $this->getTitle(); 121 122 if ($random_media) { 123 $content = "<div id=\"random_picture_container$block_id\">"; 124 if ($controls) { 125 if ($start) { 126 $icon_class = 'icon-media-stop'; 127 } else { 128 $icon_class = 'icon-media-play'; 129 } 130 $content .= '<div dir="ltr" class="center" id="random_picture_controls' . $block_id . '"><br>'; 131 $content .= "<a href=\"#\" onclick=\"togglePlay(); return false;\" id=\"play_stop\" class=\"" . $icon_class . "\" title=\"" . I18N::translate('Play') . "/" . I18N::translate('Stop') . '"></a>'; 132 $content .= '<a href="#" onclick="jQuery(\'#block_' . $block_id . '\').load(\'index.php?ctype=' . $ctype . '&action=ajax&block_id=' . $block_id . '\');return false;" title="' . I18N::translate('Next image') . '" class="icon-media-next"></a>'; 133 $content .= '</div><script> 134 var play = false; 135 function togglePlay() { 136 if (play) { 137 play = false; 138 jQuery("#play_stop").removeClass("icon-media-stop").addClass("icon-media-play"); 139 } 140 else { 141 play = true; 142 playSlideShow(); 143 jQuery("#play_stop").removeClass("icon-media-play").addClass("icon-media-stop"); 144 } 145 } 146 147 function playSlideShow() { 148 if (play) { 149 window.setTimeout("reload_image()", 6000); 150 } 151 } 152 function reload_image() { 153 if (play) { 154 jQuery("#block_' . $block_id . '").load("index.php?ctype=' . $ctype . '&action=ajax&block_id=' . $block_id . '&start=1"); 155 } 156 } 157 </script>'; 158 } 159 if ($start) { 160 $content .= '<script>togglePlay();</script>'; 161 } 162 $content .= '<div class="center" id="random_picture_content' . $block_id . '">'; 163 $content .= '<table id="random_picture_box"><tr><td class="details1">'; 164 $content .= $random_media->displayImage(); 165 166 $content .= '<br>'; 167 $content .= '<a href="' . $random_media->getHtmlUrl() . '"><b>' . $random_media->getFullName() . '</b></a><br>'; 168 foreach ($random_media->linkedIndividuals('OBJE') as $individual) { 169 $content .= '<a href="' . $individual->getHtmlUrl() . '">' . I18N::translate('View individual') . ' — ' . $individual->getFullname() . '</a><br>'; 170 } 171 foreach ($random_media->linkedFamilies('OBJE') as $family) { 172 $content .= '<a href="' . $family->getHtmlUrl() . '">' . I18N::translate('View family') . ' — ' . $family->getFullname() . '</a><br>'; 173 } 174 foreach ($random_media->linkedSources('OBJE') as $source) { 175 $content .= '<a href="' . $source->getHtmlUrl() . '">' . I18N::translate('View source') . ' — ' . $source->getFullname() . '</a><br>'; 176 } 177 $content .= '<br><div class="indent">'; 178 $content .= FunctionsPrint::printFactNotes($random_media->getGedcom(), "1", false); 179 $content .= '</div>'; 180 $content .= '</td></tr></table>'; 181 $content .= '</div>'; // random_picture_content 182 $content .= '</div>'; // random_picture_container 183 } else { 184 $content = I18N::translate('This family tree has no images to display.'); 185 } 186 if ($template) { 187 return Theme::theme()->formatBlock($id, $title, $class, $content); 188 } else { 189 return $content; 190 } 191 } 192 193 /** {@inheritdoc} */ 194 public function loadAjax() { 195 return true; 196 } 197 198 /** {@inheritdoc} */ 199 public function isUserBlock() { 200 return true; 201 } 202 203 /** {@inheritdoc} */ 204 public function isGedcomBlock() { 205 return true; 206 } 207 208 /** {@inheritdoc} */ 209 public function configureBlock($block_id) { 210 if (Filter::postBool('save') && Filter::checkCsrf()) { 211 $this->setBlockSetting($block_id, 'filter', Filter::post('filter', 'indi|event|all', 'all')); 212 $this->setBlockSetting($block_id, 'controls', Filter::postBool('controls')); 213 $this->setBlockSetting($block_id, 'start', Filter::postBool('start')); 214 $this->setBlockSetting($block_id, 'filter_avi', Filter::postBool('filter_avi')); 215 $this->setBlockSetting($block_id, 'filter_bmp', Filter::postBool('filter_bmp')); 216 $this->setBlockSetting($block_id, 'filter_gif', Filter::postBool('filter_gif')); 217 $this->setBlockSetting($block_id, 'filter_jpeg', Filter::postBool('filter_jpeg')); 218 $this->setBlockSetting($block_id, 'filter_mp3', Filter::postBool('filter_mp3')); 219 $this->setBlockSetting($block_id, 'filter_ole', Filter::postBool('filter_ole')); 220 $this->setBlockSetting($block_id, 'filter_pcx', Filter::postBool('filter_pcx')); 221 $this->setBlockSetting($block_id, 'filter_pdf', Filter::postBool('filter_pdf')); 222 $this->setBlockSetting($block_id, 'filter_png', Filter::postBool('filter_png')); 223 $this->setBlockSetting($block_id, 'filter_tiff', Filter::postBool('filter_tiff')); 224 $this->setBlockSetting($block_id, 'filter_wav', Filter::postBool('filter_wav')); 225 $this->setBlockSetting($block_id, 'filter_audio', Filter::postBool('filter_audio')); 226 $this->setBlockSetting($block_id, 'filter_book', Filter::postBool('filter_book')); 227 $this->setBlockSetting($block_id, 'filter_card', Filter::postBool('filter_card')); 228 $this->setBlockSetting($block_id, 'filter_certificate', Filter::postBool('filter_certificate')); 229 $this->setBlockSetting($block_id, 'filter_coat', Filter::postBool('filter_coat')); 230 $this->setBlockSetting($block_id, 'filter_document', Filter::postBool('filter_document')); 231 $this->setBlockSetting($block_id, 'filter_electronic', Filter::postBool('filter_electronic')); 232 $this->setBlockSetting($block_id, 'filter_fiche', Filter::postBool('filter_fiche')); 233 $this->setBlockSetting($block_id, 'filter_film', Filter::postBool('filter_film')); 234 $this->setBlockSetting($block_id, 'filter_magazine', Filter::postBool('filter_magazine')); 235 $this->setBlockSetting($block_id, 'filter_manuscript', Filter::postBool('filter_manuscript')); 236 $this->setBlockSetting($block_id, 'filter_map', Filter::postBool('filter_map')); 237 $this->setBlockSetting($block_id, 'filter_newspaper', Filter::postBool('filter_newspaper')); 238 $this->setBlockSetting($block_id, 'filter_other', Filter::postBool('filter_other')); 239 $this->setBlockSetting($block_id, 'filter_painting', Filter::postBool('filter_painting')); 240 $this->setBlockSetting($block_id, 'filter_photo', Filter::postBool('filter_photo')); 241 $this->setBlockSetting($block_id, 'filter_tombstone', Filter::postBool('filter_tombstone')); 242 $this->setBlockSetting($block_id, 'filter_video', Filter::postBool('filter_video')); 243 } 244 245 $filter = $this->getBlockSetting($block_id, 'filter', 'all'); 246 $controls = $this->getBlockSetting($block_id, 'controls', '1'); 247 $start = $this->getBlockSetting($block_id, 'start', '0') || Filter::getBool('start'); 248 249 echo '<tr><td class="descriptionbox wrap width33">'; 250 echo I18N::translate('Show only individuals, events, or all?'); 251 echo '</td><td class="optionbox">'; 252 echo FunctionsEdit::selectEditControl('filter', array('indi' => I18N::translate('Individuals'), 'event' => I18N::translate('Facts and events'), 'all' => I18N::translate('All')), null, $filter, ''); 253 echo '</td></tr>'; 254 255 $filters = array( 256 'avi' => $this->getBlockSetting($block_id, 'filter_avi', '0'), 257 'bmp' => $this->getBlockSetting($block_id, 'filter_bmp', '1'), 258 'gif' => $this->getBlockSetting($block_id, 'filter_gif', '1'), 259 'jpeg' => $this->getBlockSetting($block_id, 'filter_jpeg', '1'), 260 'mp3' => $this->getBlockSetting($block_id, 'filter_mp3', '0'), 261 'ole' => $this->getBlockSetting($block_id, 'filter_ole', '1'), 262 'pcx' => $this->getBlockSetting($block_id, 'filter_pcx', '1'), 263 'pdf' => $this->getBlockSetting($block_id, 'filter_pdf', '0'), 264 'png' => $this->getBlockSetting($block_id, 'filter_png', '1'), 265 'tiff' => $this->getBlockSetting($block_id, 'filter_tiff', '1'), 266 'wav' => $this->getBlockSetting($block_id, 'filter_wav', '0'), 267 'audio' => $this->getBlockSetting($block_id, 'filter_audio', '0'), 268 'book' => $this->getBlockSetting($block_id, 'filter_book', '1'), 269 'card' => $this->getBlockSetting($block_id, 'filter_card', '1'), 270 'certificate' => $this->getBlockSetting($block_id, 'filter_certificate', '1'), 271 'coat' => $this->getBlockSetting($block_id, 'filter_coat', '1'), 272 'document' => $this->getBlockSetting($block_id, 'filter_document', '1'), 273 'electronic' => $this->getBlockSetting($block_id, 'filter_electronic', '1'), 274 'fiche' => $this->getBlockSetting($block_id, 'filter_fiche', '1'), 275 'film' => $this->getBlockSetting($block_id, 'filter_film', '1'), 276 'magazine' => $this->getBlockSetting($block_id, 'filter_magazine', '1'), 277 'manuscript' => $this->getBlockSetting($block_id, 'filter_manuscript', '1'), 278 'map' => $this->getBlockSetting($block_id, 'filter_map', '1'), 279 'newspaper' => $this->getBlockSetting($block_id, 'filter_newspaper', '1'), 280 'other' => $this->getBlockSetting($block_id, 'filter_other', '1'), 281 'painting' => $this->getBlockSetting($block_id, 'filter_painting', '1'), 282 'photo' => $this->getBlockSetting($block_id, 'filter_photo', '1'), 283 'tombstone' => $this->getBlockSetting($block_id, 'filter_tombstone', '1'), 284 'video' => $this->getBlockSetting($block_id, 'filter_video', '0'), 285 ); 286 287 echo '<tr><td class="descriptionbox wrap width33">'; 288 echo I18N::translate('Filter'); 289 ?> 290 </td> 291 <td class="optionbox"> 292 <center><b><?php echo GedcomTag::getLabel('FORM'); ?></b></center> 293 <table class="width100"> 294 <tr> 295 <td class="width33"> 296 <label> 297 <input type="checkbox" value="yes" name="filter_avi" <?php echo $filters['avi'] ? 'checked' : ''; ?>> 298 avi 299 </td> 300 <td class="width33"> 301 <label> 302 <input type="checkbox" value="yes" name="filter_bmp" <?php echo $filters['bmp'] ? 'checked' : ''; ?>> 303 bmp 304 </label> 305 </td> 306 <td class="width33"> 307 <label> 308 <input type="checkbox" value="yes" name="filter_gif" <?php echo $filters['gif'] ? 'checked' : ''; ?>> 309 gif 310 </label> 311 </td> 312 </tr> 313 <tr> 314 <td class="width33"> 315 <label> 316 <input type="checkbox" value="yes" name="filter_jpeg" <?php echo $filters['jpeg'] ? 'checked' : ''; ?>> 317 jpeg 318 </label> 319 </td> 320 <td class="width33"> 321 <label> 322 <input type="checkbox" value="yes" name="filter_mp3" <?php echo $filters['mp3'] ? 'checked' : ''; ?>> 323 mp3 324 </label> 325 </td> 326 <td class="width33"> 327 <label> 328 <input type="checkbox" value="yes" name="filter_ole" <?php echo $filters['ole'] ? 'checked' : ''; ?>> 329 ole 330 </label> 331 </td> 332 </tr> 333 <tr> 334 <td class="width33"> 335 <label> 336 <input type="checkbox" value="yes" name="filter_pcx" <?php echo $filters['pcx'] ? 'checked' : ''; ?>> 337 pcx 338 </label> 339 </td> 340 <td class="width33"> 341 <label> 342 <input type="checkbox" value="yes" name="filter_pdf" <?php echo $filters['pdf'] ? 'checked' : ''; ?>> 343 pdf 344 </label> 345 </td> 346 <td class="width33"> 347 <label> 348 <input type="checkbox" value="yes" name="filter_png" <?php echo $filters['png'] ? 'checked' : ''; ?>> 349 png 350 </label> 351 </td> 352 </tr> 353 <tr> 354 <td class="width33"> 355 <label> 356 <input type="checkbox" value="yes" name="filter_tiff" <?php echo $filters['tiff'] ? 'checked' : ''; ?>> 357 tiff 358 </label> 359 </td> 360 <td class="width33"> 361 <label> 362 <input type="checkbox" value="yes" name="filter_wav" <?php echo $filters['wav'] ? 'checked' : ''; ?>> 363 wav 364 </label> 365 </td> 366 <td class="width33"></td> 367 <td class="width33"></td> 368 </tr> 369 </table> 370 <br> 371 <center><b><?php echo GedcomTag::getLabel('TYPE'); ?></b></center> 372 <table class="width100"> 373 <tr> 374 <?php 375 //-- Build the list of checkboxes 376 $i = 0; 377 foreach (GedcomTag::getFileFormTypes() as $typeName => $typeValue) { 378 $i++; 379 if ($i > 3) { 380 $i = 1; 381 echo '</tr><tr>'; 382 } 383 echo '<td class="width33"><label><input type="checkbox" value="yes" name="filter_' . $typeName . '" '; 384 echo $filters[$typeName] ? 'checked' : ''; 385 echo '> ' . $typeValue . '</label></td>'; 386 } 387 ?> 388 </tr> 389 </table> 390 </td> 391 </tr> 392 393 <?php 394 395 echo '<tr><td class="descriptionbox wrap width33">'; 396 echo I18N::translate('Show slide show controls?'); 397 echo '</td><td class="optionbox">'; 398 echo FunctionsEdit::editFieldYesNo('controls', $controls); 399 echo '</td></tr>'; 400 401 echo '<tr><td class="descriptionbox wrap width33">'; 402 echo I18N::translate('Start slide show on page load?'); 403 echo '</td><td class="optionbox">'; 404 echo FunctionsEdit::editFieldYesNo('start', $start); 405 echo '</td></tr>'; 406 } 407} 408