diff --git a/Controller/BackendController.php b/Controller/BackendController.php index 65ba2b4..6ee687a 100755 --- a/Controller/BackendController.php +++ b/Controller/BackendController.php @@ -159,8 +159,8 @@ final class BackendController extends Controller $devSummaryPath = __DIR__ . '/../../' . $request->getData('id') . '/Docs/Dev/en/SUMMARY.md'; $toParse = $path === '' ? '' : \file_get_contents($path); - $summary = \file_exists($summaryPath) ? \file_get_contents($summaryPath) : ''; - $devSummary = \file_exists($devSummaryPath) ? \file_get_contents($devSummaryPath) : ''; + $summary = \is_file($summaryPath) ? \file_get_contents($summaryPath) : ''; + $devSummary = \is_file($devSummaryPath) ? \file_get_contents($devSummaryPath) : ''; $content = Markdown::parse($toParse === false ? '' : $toParse); $navigation = Markdown::parse($summary === false ? '' : $summary); diff --git a/Controller/SearchController.php b/Controller/SearchController.php index 535a225..cd5ad70 100755 --- a/Controller/SearchController.php +++ b/Controller/SearchController.php @@ -16,6 +16,8 @@ namespace Modules\Help\Controller; use phpOMS\Message\RequestAbstract; use phpOMS\Message\ResponseAbstract; +use phpOMS\System\File\Local\Directory; +use phpOMS\System\MimeType; /** * Help class. @@ -40,8 +42,86 @@ final class SearchController extends Controller * * @since 1.0.0 */ - public function searchHelp(RequestAbstract $request, ResponseAbstract $response, $data = null) : array + public function searchHelp(RequestAbstract $request, ResponseAbstract $response, $data = null) : void { - return ['found']; + $lang = 'en'; + + if (\is_dir(__DIR__ . '/../Docs/Help/' . $request->getHeader()->getL11n()->getLanguage())) { + $lang = $request->getHeader()->getL11n()->getLanguage(); + } elseif (\is_dir(__DIR__ . '/../Docs/Help/' . $this->app->l11nServer->getLanguage())) { + $lang = $this->app->l11nServer->getLanguage(); + } + + $pattern = \substr( + $request->getData('search'), + \stripos( + $request->getData('search'), + ' ', + \stripos($request->getData('search'), ':') + ) + 1 + ); + + $files = []; + $activeModules = $this->app->moduleManager->getActiveModules(); + + foreach ($activeModules as $module) { + $path = __DIR__ . '/../../' . $module['name']['internal'] . '/Docs/Help/' . $lang; + $toCheck = Directory::listByExtension($path, 'md'); + foreach ($toCheck as $file) { + // @todo: create better matching + $content = \file_get_contents($path . '/' . $file); + if (($found = \stripos($content, $pattern)) !== false) { + $contentLength = \strlen($content); + $headline = \strtok($content, "\n"); + + $t1 = \strripos($content, "\n", -$contentLength + $found); + $t2 = \strripos($content, '.', -$contentLength + $found); + $summaryStart = ($t1 !== false && $t2 !== false) || $t1 === $t2 + ? \min( + $t1 === false ? 0 : $t1, + $t2 === false ? 0 : $t2, + ) : \max( + $t1 === false ? 0 : $t1, + $t2 === false ? 0 : $t2, + ); + + $t1 = \stripos($content, "\n", $found); + $t2 = \stripos($content, '.', $found); + $summaryEnd = ($t1 !== false && $t2 !== false) || $t1 === $t2 ? \max( + $t1 === false ? $contentLength : $t1, + $t2 === false ? $contentLength : $t2, + ) : \min( + $t1 === false ? $contentLength : $t1, + $t2 === false ? $contentLength : $t2, + ); + + $summary = \substr( + $content, + $summaryStart + 1, + $summaryEnd - $summaryStart + ); + + $files[$module['name']['internal']][] = [ + 'title' => $module['name']['external'] . ': ' . \trim($headline, " #\r\n\t"), + 'summary' => \trim($summary, " #\r\n\t"), + 'link' => $path . '/' . $file, + 'account' => '', + 'createdAt' => \max( + \filectime($path . '/' . $file), + \filemtime($path . '/' . $file) + ), + 'image' => '', + 'tags' => [], + 'type' => 'list_links' + ]; + // @todo: add match score for sorted return + } + } + } + + // @todo: probably cleanup return for link generation + sort by best match + $response->getHeader()->set('Content-Type', MimeType::M_JSON . '; charset=utf-8', true); + + $response->set($request->getUri()->__toString(), $files); } } diff --git a/tests/Controller/SearchControllerTest.php b/tests/Controller/SearchControllerTest.php new file mode 100644 index 0000000..7dd08d5 --- /dev/null +++ b/tests/Controller/SearchControllerTest.php @@ -0,0 +1,103 @@ +app = new class() extends ApplicationAbstract + { + protected string $appName = 'Search'; + }; + + $this->app->dbPool = $GLOBALS['dbpool']; + $this->app->orgId = 1; + $this->app->appName = 'Backend'; + $this->app->accountManager = new AccountManager($GLOBALS['session']); + $this->app->appSettings = new CoreSettings($this->app->dbPool->get()); + $this->app->moduleManager = new ModuleManager($this->app, __DIR__ . '/../../../../Modules'); + $this->app->dispatcher = new Dispatcher($this->app); + $this->app->eventManager = new EventManager($this->app->dispatcher); + $this->app->eventManager->importFromFile(__DIR__ . '/../../../../Web/Api/Hooks.php'); + + $account = new Account(); + TestUtils::setMember($account, 'id', 1); + + $permission = new AccountPermission(); + $permission->setUnit(1); + $permission->setApp('backend'); + $permission->setPermission( + PermissionType::READ + | PermissionType::CREATE + | PermissionType::MODIFY + | PermissionType::DELETE + | PermissionType::PERMISSION + ); + + $account->addPermission($permission); + + $this->app->accountManager->add($account); + $this->app->router = new WebRouter(); + + $this->module = $this->app->moduleManager->get('Help'); + + TestUtils::setMember($this->module, 'app', $this->app); + } + + /** + * @covers Modules\Help\Controller\SearchController + * @group module + */ + public function testHelpSearch() : void + { + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->getHeader()->setAccount(1); + $request->setData('search', ':help file'); + + $this->module->searchHelp($request, $response); + self::assertCount(3, $response->get('')); + } +}