diff --git a/app/controllers/course/wiki.php b/app/controllers/course/wiki.php index 567e2853e99cdda93c6df510c5049a375e23c6f9..cbd63cf5c0f28dae9b61ca16bc3418f81bd88c52 100644 --- a/app/controllers/course/wiki.php +++ b/app/controllers/course/wiki.php @@ -976,6 +976,30 @@ class Course_WikiController extends AuthenticatedController Sidebar::Get()->addWidget($search); } + public function searchpage_action(WikiPage $page) + { + if (!$page->isReadable()) { + throw new AccessDeniedException(); + } + Navigation::activateItem('/course/wiki/allpages'); + if (!Request::get('search')) { + throw new Exception('No search text.'); + } + $search = str_replace(['\\', '_', '%'], ['\\\\', '\\_', '\\%'], Request::get('search')); + $this->versions = WikiVersion::findBySQL("`page_id` = :page_id AND (`wiki_versions`.`content` LIKE :searchterm OR `wiki_versions`.`name` LIKE :searchterm) ORDER BY `mkdate` DESC ", [ + 'page_id' => $page->id, + 'searchterm' => '%' . $search . '%' + ]); + + $search = new SearchWidget($this->searchURL()); + $search->addNeedle( + _('Im Wiki suchen'), + 'search', + true + ); + Sidebar::Get()->addWidget($search); + } + public function pdf_action(WikiPage $page) { if (!$page->isReadable()) { @@ -1217,4 +1241,41 @@ class Course_WikiController extends AuthenticatedController return $from_end ? mb_strlen($str0) - $length : $length; } + + public function findTextualHits($text, $search, $length = 80) + { + $content = Studip\Markup::removeHtml($text); + $offset = 0; + $output = []; + + // find all occurences + while ($offset < mb_strlen($content)) { + $pos = mb_stripos($content, Request::get('search'), $offset); + if ($pos === false) { + break; + } + $offset = $pos + 1; + + // show max 200 chars + $fragment = ''; + $split_fragment = preg_split( + '/(' . preg_quote(Request::get('search'), '/') . ')/i', + mb_substr($content, max(0, $pos - floor($length / 2)), $length), + -1, + PREG_SPLIT_DELIM_CAPTURE + ); + for ($i = 0; $i < count($split_fragment); ++$i) { + if ($i % 2) { + $fragment .= '<span class="wiki_highlight">'; + $fragment .= htmlready($split_fragment[$i], false); + $fragment .= '</span>'; + } else { + $fragment .= htmlready($split_fragment[$i], false); + } + } + $found_in_fragment = (count($split_fragment) - 1) / 2; // number of hits in fragment + $output[] = '...' . $fragment . '...'; + } + return implode('<br>', $output); + } } diff --git a/app/views/course/wiki/search.php b/app/views/course/wiki/search.php index daf88fe113c7995f6d55d727a9e2d7f3fef0a548..8ef886ab802c2929e28905cf493f00c064b2dca8 100644 --- a/app/views/course/wiki/search.php +++ b/app/views/course/wiki/search.php @@ -10,7 +10,7 @@ <table class="default"> <caption> - <?= sprintf(_('Treffer für Suche nach <em>%s</em> in allen Versionen'), htmlReady(Request::get('search'))) ?> + <?= sprintf(_('Treffer für Suche nach <em>%s</em>'), htmlReady(Request::get('search'))) ?> </caption> <thead> <tr> @@ -96,6 +96,20 @@ <? endif ?> </td> </tr> + <? if ($pagedata['is_in_history'] && count($pagedata['versions']) > 1 || ($pagedata['is_in_content'] && count($pagedata['versions']) > 0)) : ?> + <tr> + <td colspan="3"> + <a href="<?= $controller->searchpage($page_id, ['search' => Request::get('search')]) ?>"> + <?= Icon::create('add')->asImg(['class' => 'text-bottom']) ?> + <? if (count($pagedata['versions']) === 1) : ?> + <?= _('Weiterer Treffer in einer älteren Version.') ?> + <? else : ?> + <?= sprintf(_('Weitere Treffer in %d älteren Versionen.'), count($pagedata['versions'])) ?> + <? endif ?> + </a> + </td> + </tr> + <? endif ?> <? endforeach ?> </tbody> </table> diff --git a/app/views/course/wiki/searchpage.php b/app/views/course/wiki/searchpage.php new file mode 100644 index 0000000000000000000000000000000000000000..95b6ff40af50da0b3c0cf3e4f2cced3c7e068f35 --- /dev/null +++ b/app/views/course/wiki/searchpage.php @@ -0,0 +1,48 @@ +<table class="default"> + <caption> + <?= sprintf(_('Treffer für Suche nach <em>%s</em> auf Seite %s'), htmlReady(Request::get('search')), htmlReady($page->name)) ?> + </caption> + <thead> + <tr> + <th><?= _('Seite') ?></th> + <th><?= _('Treffer') ?></th> + <th><?= _('Datum') ?></th> + </tr> + </thead> + <tbody> + <? $pos_name = mb_stripos($page->name, Request::get('search')) ?> + <? $pos_content = mb_stripos($page->content, Request::get('search')) ?> + <? if ($pos_name !== false || $pos_content !== false) : ?> + <tr> + <td> + <a href="<?= $controller->page($page) ?>"> + <?= htmlReady($page->name) ?> + </a> + </td> + <td> + <?= $controller->findTextualHits($page->content, Request::get('search'), 200) ?> + </td> + <td> + <?= $page->chdate > 0 ? date('d.m.Y H:i:s', $page->chdate) : _('unbekannt') ?> + (<?= _('Version').' '.htmlReady($page->versionnumber) ?>) + </td> + </tr> + <? endif ?> + <? foreach ($versions as $version) : ?> + <tr> + <td> + <a href="<?= $controller->version($version) ?>"> + <?= htmlReady($version->name) ?> + </a> + </td> + <td> + <?= $controller->findTextualHits($version->content, Request::get('search'), 200) ?> + </td> + <td> + <?= $version->mkdate > 0 ? date('d.m.Y H:i:s', $version->mkdate) : _('unbekannt') ?> + (<?= _('Version').' '.htmlReady($version->versionnumber) ?>) + </td> + </tr> + <? endforeach ?> + </tbody> +</table>