CToolIntro - add checks for course/session creation + add test

@todo loading states
pull/4004/head
Julio 5 years ago
parent e41b70d628
commit da60ad6385
  1. 83
      assets/vue/views/course/Home.vue
  2. 103
      src/CoreBundle/DataProvider/Extension/CToolIntroExtension.php
  3. 93
      tests/CourseBundle/Repository/CToolIntroRepositoryTest.php

@ -58,13 +58,28 @@
<div v-if="intro" class="p-10 text-center">
<span v-html="intro.introText" />
<button
class="mt-2 btn btn-info"
@click="updateIntro(intro)"
>
<v-icon>mdi-pencil</v-icon>
{{ $t('Update') }}
</button>
<div v-if="createInSession">
<button
class="mt-2 btn btn-info"
v-if="introTool"
@click="addIntro(course, introTool)"
>
<v-icon>mdi-plus</v-icon>
{{ $t('Course introduction in a session') }}
</button>
</div>
<div v-else>
<button
class="mt-2 btn btn-info"
@click="updateIntro(intro)"
>
<v-icon>mdi-pencil</v-icon>
{{ $t('Update') }}
</button>
</div>
</div>
<div v-else>
<div>
@ -78,27 +93,19 @@
<div class="mt-2 font-bold">
{{ $t("You don't have course content") }}
</div>
<div>
{{ $t('Add a course introduction to display to your students') }}
{{ $t('Add a course introduction to display to your students') }}
</div>
<!-- <router-link-->
<!-- v-if="introTool"-->
<!-- :to="{ name: 'ToolIntroCreate', params: {'courseTool': introTool.iid, cid: course.id, sid: route.query.sid} }"-->
<!-- tag="button"-->
<!-- class="mt-2 btn btn-info">-->
<!-- <v-icon>mdi-plus</v-icon>-->
<!-- {{ $t('Course introduction') }}-->
<!-- </router-link>-->
<button
class="mt-2 btn btn-info"
v-if="introTool"
@click="addIntro(course, introTool)"
>
<v-icon>mdi-plus</v-icon>
{{ $t('Course introduction') }}
</button>
<button
class="mt-2 btn btn-info"
v-if="introTool"
@click="addIntro(course, introTool)"
>
<v-icon>mdi-plus</v-icon>
{{ $t('Course introduction') }}
</button>
</div>
</div>
<div v-else>
@ -189,12 +196,13 @@ export default {
dropdownOpen: false,
intro: null,
introTool: null,
createInSession: false,
goToCourseTool,
changeVisibility,
goToSettingCourseTool,
goToShortCut,
addIntro,
updateIntro,
updateIntro
});
const route = useRoute()
const store = useStore();
@ -213,21 +221,38 @@ export default {
});
async function getIntro() {
// Searching for the CTool called 'course_homepage'.
const introTool = state.course.tools.find(element => element.name === 'course_homepage');
state.introTool = introTool;
// Search CToolIntro for this
const filter = {
courseTool : introTool.iid,
cid : courseId,
sid : sessionId,
};
state.introTool = introTool;
store.dispatch('ctoolintro/findAll', filter).then(response => {
if (!isEmpty(response)) {
// first item
state.intro = response[0];
}
});
if (!isEmpty(sessionId)) {
state.createInSession = true;
const filter = {
courseTool : introTool.iid,
cid : courseId,
sid : sessionId,
};
store.dispatch('ctoolintro/findAll', filter).then(response => {
if (!isEmpty(response)) {
state.createInSession = false;
state.intro = response[0];
}
});
}
}
function addIntro(course, introTool) {

@ -0,0 +1,103 @@
<?php
/* For licensing terms, see /license.txt */
declare(strict_types=1);
namespace Chamilo\CoreBundle\DataProvider\Extension;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryCollectionExtensionInterface;
//use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryItemExtensionInterface;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use Chamilo\CoreBundle\Entity\ResourceLink;
use Chamilo\CourseBundle\Entity\CToolIntro;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Security;
final class CToolIntroExtension implements QueryCollectionExtensionInterface
{
private Security $security;
private RequestStack $requestStack;
public function __construct(Security $security, RequestStack $request)
{
$this->security = $security;
$this->requestStack = $request;
}
public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null): void
{
$this->addWhere($queryBuilder, $resourceClass);
}
private function addWhere(QueryBuilder $queryBuilder, string $resourceClass): void
{
if (CToolIntro::class !== $resourceClass) {
return;
}
/*if ($this->security->isGranted('ROLE_ADMIN')) {
return;
}*/
if (null === $user = $this->security->getUser()) {
throw new AccessDeniedException('Access Denied.');
}
$request = $this->requestStack->getCurrentRequest();
$courseId = $request->query->get('cid');
$sessionId = $request->query->get('sid');
$groupId = $request->query->get('gid');
$rootAlias = $queryBuilder->getRootAliases()[0];
$queryBuilder
->innerJoin("$rootAlias.resourceNode", 'node')
->innerJoin('node.resourceLinks', 'links')
;
// Do not show deleted resources.
$queryBuilder
->andWhere('links.visibility != :visibilityDeleted')
->setParameter('visibilityDeleted', ResourceLink::VISIBILITY_DELETED)
;
$allowDraft =
$this->security->isGranted('ROLE_ADMIN') ||
$this->security->isGranted('ROLE_CURRENT_COURSE_TEACHER')
;
if (!$allowDraft) {
$queryBuilder
->andWhere('links.visibility != :visibilityDraft')
->setParameter('visibilityDraft', ResourceLink::VISIBILITY_DRAFT)
;
}
$queryBuilder
->andWhere('links.course = :course')
->setParameter('course', $courseId)
;
if (empty($sessionId)) {
$queryBuilder->andWhere('links.session IS NULL');
} else {
$queryBuilder
->andWhere('links.session = :session')
->setParameter('session', $sessionId)
;
}
if (empty($groupId)) {
$queryBuilder->andWhere('links.group IS NULL');
} else {
$queryBuilder
->andWhere('links.group = :group')
->setParameter('group', $groupId)
;
}
}
}

@ -44,12 +44,101 @@ class CToolIntroRepositoryTest extends AbstractApiTest
$em->flush();
$this->assertNotEmpty($intro->getIntroText());
$this->assertSame(1, $repo->count([]));
$repo->delete($intro);
$this->assertSame(0, $repo->count([]));
}
public function testCreateInSession(): void
{
self::bootKernel();
$em = $this->getEntityManager();
$repo = self::getContainer()->get(CToolIntroRepository::class);
$course = $this->createCourse('new');
$teacher = $this->createUser('teacher');
$session = $this->createSession('my session');
$session->addCourse($course);
$em->persist($session);
$em->flush();
/** @var CTool $courseTool */
$courseTool = $course->getTools()->first();
// Create Intro for the base course.
$intro = (new CToolIntro())
->setIntroText('test')
->setCourseTool($courseTool)
->setParent($course)
->setCreator($teacher)
->addCourseLink($course)
;
$em->persist($intro);
$em->flush();
$this->assertSame(1, $repo->count([]));
$repo->delete($intro);
// Create intro in session.
$this->assertSame(0, $repo->count([]));
$intro2 = (new CToolIntro())
->setIntroText('test in session')
->setCourseTool($courseTool)
->setParent($course)
->setCreator($teacher)
->addCourseLink($course, $session)
;
$this->assertHasNoEntityViolations($intro2);
$em->persist($intro2);
$em->flush();
$this->assertSame(2, $repo->count([]));
$token = $this->getUserToken([]);
$this->createClientWithCredentials($token)->request(
'GET',
'/api/c_tool_intros',
[
'query' => [
'cid' => $course->getId(),
],
]
);
$this->assertResponseIsSuccessful();
// Asserts that the returned JSON is a superset of this one
$this->assertJsonContains([
'@context' => '/api/contexts/CToolIntro',
'@id' => '/api/c_tool_intros',
'@type' => 'hydra:Collection',
'hydra:totalItems' => 1,
]);
$this->createClientWithCredentials($token)->request(
'GET',
'/api/c_tool_intros',
[
'query' => [
'cid' => $course->getId(),
'sid' => $session->getId(),
],
]
);
$this->assertResponseIsSuccessful();
// Asserts that the returned JSON is a superset of this one
$this->assertJsonContains([
'@context' => '/api/contexts/CToolIntro',
'@id' => '/api/c_tool_intros',
'@type' => 'hydra:Collection',
'hydra:totalItems' => 1,
'hydra:member' => [
[
'@type' => 'CToolIntro',
'introText' => 'test in session',
],
],
]);
}
public function testGetToolIntros(): void

Loading…
Cancel
Save