mirror of
https://github.com/nextcloud/integration_moodle.git
synced 2025-12-17 21:02:05 +01:00
implement basic unified search for courses
Signed-off-by: Julien Veyssier <eneiluj@posteo.net>
This commit is contained in:
parent
1c0226ba05
commit
f975d70b51
6 changed files with 228 additions and 2 deletions
|
|
@ -19,6 +19,7 @@ use OCP\AppFramework\Bootstrap\IBootstrap;
|
|||
|
||||
use OCA\Moodle\Controller\PageController;
|
||||
use OCA\Moodle\Dashboard\MoodleWidget;
|
||||
use OCA\Moodle\Search\MoodleSearchProvider;
|
||||
|
||||
/**
|
||||
* Class Application
|
||||
|
|
@ -42,6 +43,7 @@ class Application extends App implements IBootstrap {
|
|||
|
||||
public function register(IRegistrationContext $context): void {
|
||||
$context->registerDashboardWidget(MoodleWidget::class);
|
||||
$context->registerSearchProvider(MoodleSearchProvider::class);
|
||||
}
|
||||
|
||||
public function boot(IBootContext $context): void {
|
||||
|
|
|
|||
162
lib/Search/MoodleSearchProvider.php
Normal file
162
lib/Search/MoodleSearchProvider.php
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2020, Julien Veyssier
|
||||
*
|
||||
* @author Julien Veyssier <eneiluj@posteo.net>
|
||||
*
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
namespace OCA\Moodle\Search;
|
||||
|
||||
use OCA\Moodle\Service\MoodleAPIService;
|
||||
use OCA\Moodle\AppInfo\Application;
|
||||
use OCP\App\IAppManager;
|
||||
use OCP\IL10N;
|
||||
use OCP\IConfig;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUser;
|
||||
use OCP\Search\IProvider;
|
||||
use OCP\Search\ISearchQuery;
|
||||
use OCP\Search\SearchResult;
|
||||
|
||||
class MoodleSearchProvider implements IProvider {
|
||||
|
||||
/** @var IAppManager */
|
||||
private $appManager;
|
||||
|
||||
/** @var IL10N */
|
||||
private $l10n;
|
||||
|
||||
/** @var IURLGenerator */
|
||||
private $urlGenerator;
|
||||
|
||||
/**
|
||||
* CospendSearchProvider constructor.
|
||||
*
|
||||
* @param IAppManager $appManager
|
||||
* @param IL10N $l10n
|
||||
* @param IURLGenerator $urlGenerator
|
||||
* @param MoodleAPIService $service
|
||||
*/
|
||||
public function __construct(IAppManager $appManager,
|
||||
IL10N $l10n,
|
||||
IConfig $config,
|
||||
IURLGenerator $urlGenerator,
|
||||
MoodleAPIService $service) {
|
||||
$this->appManager = $appManager;
|
||||
$this->l10n = $l10n;
|
||||
$this->config = $config;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
$this->service = $service;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getId(): string {
|
||||
return 'moodle-search';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getName(): string {
|
||||
return $this->l10n->t('Moodle');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getOrder(string $route, array $routeParameters): int {
|
||||
if (strpos($route, Application::APP_ID . '.') === 0) {
|
||||
// Active app, prefer Moodle results
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 20;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function search(IUser $user, ISearchQuery $query): SearchResult {
|
||||
if (!$this->appManager->isEnabledForUser(Application::APP_ID, $user)) {
|
||||
return SearchResult::complete($this->getName(), []);
|
||||
}
|
||||
|
||||
$limit = $query->getLimit();
|
||||
$term = $query->getTerm();
|
||||
$offset = $query->getCursor();
|
||||
|
||||
$theme = $this->config->getUserValue($user->getUID(), 'accessibility', 'theme', '');
|
||||
$thumbnailUrl = ($theme === 'dark') ?
|
||||
$this->urlGenerator->imagePath(Application::APP_ID, 'app.svg') :
|
||||
$this->urlGenerator->imagePath(Application::APP_ID, 'app-dark.svg');
|
||||
|
||||
$resultBills = [];
|
||||
|
||||
$moodleUrl = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'url', '');
|
||||
$accessToken = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'token', '');
|
||||
$searchEnabled = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'search_enabled', '0') === '1';
|
||||
if ($accessToken === '' || !$searchEnabled) {
|
||||
return SearchResult::paginated($this->getName(), [], 0);
|
||||
}
|
||||
|
||||
$searchResults = $this->service->search($moodleUrl, $accessToken, $term);
|
||||
|
||||
$formattedResults = \array_map(function (array $entry) use ($thumbnailUrl, $moodleUrl): MoodleSearchResultEntry {
|
||||
return new MoodleSearchResultEntry(
|
||||
$thumbnailUrl,
|
||||
$this->getMainText($entry),
|
||||
$this->getSubline($entry),
|
||||
$this->getLinkToMoodle($entry, $moodleUrl),
|
||||
'',
|
||||
true
|
||||
);
|
||||
}, $searchResults);
|
||||
|
||||
return SearchResult::paginated(
|
||||
$this->getName(),
|
||||
$formattedResults,
|
||||
$query->getCursor() + count($formattedResults)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function getMainText(array $entry): string {
|
||||
return $entry['displayname'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function getSubline(array $entry): string {
|
||||
return $this->l10n->t('Moodle course');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function getLinkToMoodle(array $entry, string $url): string {
|
||||
return $url . '/course/view.php?id=' . $entry['id'];
|
||||
}
|
||||
|
||||
}
|
||||
30
lib/Search/MoodleSearchResultEntry.php
Normal file
30
lib/Search/MoodleSearchResultEntry.php
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2020, Julien Veyssier
|
||||
*
|
||||
* @author Julien Veyssier <eneiluj@posteo.net>
|
||||
*
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
namespace OCA\Moodle\Search;
|
||||
|
||||
use OCP\Search\SearchResultEntry;
|
||||
|
||||
class MoodleSearchResultEntry extends SearchResultEntry {
|
||||
}
|
||||
|
|
@ -103,6 +103,18 @@ class MoodleAPIService {
|
|||
];
|
||||
}
|
||||
|
||||
public function search(string $url, string $accessToken, string $query): array {
|
||||
$params = [
|
||||
'wstoken' => $accessToken,
|
||||
'wsfunction' => 'core_course_search_courses',
|
||||
'moodlewsrestformat' => 'json',
|
||||
'criterianame' => 'search',
|
||||
'criteriavalue' => $query,
|
||||
];
|
||||
$searchResult = $this->request($url, 'webservice/rest/server.php', $params);
|
||||
return $searchResult['courses'];
|
||||
}
|
||||
|
||||
public function getMoodleAvatar($url) {
|
||||
$rawResult = $this->client->get($url)->getBody();
|
||||
$success = preg_match('/<svg.*/', $rawResult, $matches);
|
||||
|
|
@ -113,7 +125,7 @@ class MoodleAPIService {
|
|||
} else {
|
||||
$result = $rawResult;
|
||||
}
|
||||
error_log('RESult['.$success.'] '.$result);
|
||||
//error_log('RESult['.$success.'] '.$result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,10 +43,12 @@ class Personal implements ISettings {
|
|||
public function getForm() {
|
||||
$token = $this->config->getUserValue($this->userId, Application::APP_ID, 'token', '');
|
||||
$url = $this->config->getUserValue($this->userId, Application::APP_ID, 'url', '');
|
||||
$searchEnabled = $this->config->getUserValue($this->userId, Application::APP_ID, 'search_enabled', '0');
|
||||
|
||||
$userConfig = [
|
||||
'token' => $token,
|
||||
'url' => $url
|
||||
'url' => $url,
|
||||
'search_enabled' => ($searchEnabled === '1')
|
||||
];
|
||||
$this->initialStateService->provideInitialState($this->appName, 'user-config', $userConfig);
|
||||
return new TemplateResponse(Application::APP_ID, 'personalSettings');
|
||||
|
|
|
|||
|
|
@ -52,6 +52,15 @@
|
|||
:placeholder="t('integration_moodle', 'Authenticate with OAuth')"
|
||||
@input="onInput">
|
||||
</div>
|
||||
<div id="moodle-search-block">
|
||||
<input
|
||||
id="search-moodle"
|
||||
type="checkbox"
|
||||
class="checkbox"
|
||||
:checked="state.search_enabled"
|
||||
@input="onSearchChange">
|
||||
<label for="search-moodle">{{ t('integration_moodle', 'Enable unified search for courses.') }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -85,6 +94,10 @@ export default {
|
|||
},
|
||||
|
||||
methods: {
|
||||
onSearchChange(e) {
|
||||
this.state.search_enabled = e.target.checked
|
||||
this.saveOptions()
|
||||
},
|
||||
onInput() {
|
||||
const that = this
|
||||
delay(function() {
|
||||
|
|
@ -103,6 +116,7 @@ export default {
|
|||
values: {
|
||||
token: this.state.token,
|
||||
url: this.state.url,
|
||||
search_enabled: this.state.search_enabled ? '1' : '0',
|
||||
},
|
||||
}
|
||||
const url = generateUrl('/apps/integration_moodle/config')
|
||||
|
|
@ -150,6 +164,10 @@ export default {
|
|||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
#moodle-search-block {
|
||||
margin-left: 30px;
|
||||
margin-top: 30px;
|
||||
}
|
||||
.moodle-grid-form label {
|
||||
line-height: 38px;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue