Skip to content

Commit c48f466

Browse files
committed
Plugin: ExerciseMonitoring: Show snapshot logs in ExerciseFocused plugin report - refs BT#21074
1 parent e04802b commit c48f466

File tree

4 files changed

+217
-5
lines changed

4 files changed

+217
-5
lines changed

plugin/exercisefocused/src/Traits/ReportingFilterTrait.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Display;
1313
use Doctrine\ORM\Query\Expr\Join;
1414
use Exception;
15+
use ExerciseMonitoringPlugin;
1516
use ExtraField;
1617
use ExtraFieldValue;
1718
use FormValidator;
@@ -192,9 +193,13 @@ protected function formatResults(array $queryResults): array
192193

193194
protected function createTable(array $tableData): HTML_Table
194195
{
196+
$monitoringPluginEnabled = ExerciseMonitoringPlugin::create()->isEnabled(true);
197+
195198
$detailIcon = Display::return_icon('forum_listview.png', get_lang('Detail'));
199+
$webcamIcon = Display::return_icon('webcam.png', $this->plugin->get_lang('MonitoringDetail'));
196200

197201
$urlDetail = api_get_path(WEB_PLUGIN_PATH).'exercisefocused/pages/detail.php?'.api_get_cidreq().'&';
202+
$monitoringDetail = api_get_path(WEB_PLUGIN_PATH).'exercisemonitoring/pages/detail.php?'.api_get_cidreq().'&';
198203

199204
$table = new HTML_Table(['class' => 'table table-hover table-striped data_table']);
200205
$table->setHeaderContents(0, 0, get_lang('Username'));
@@ -219,6 +224,18 @@ protected function createTable(array $tableData): HTML_Table
219224
]
220225
);
221226

227+
if ($monitoringPluginEnabled) {
228+
$url .= Display::url(
229+
$webcamIcon,
230+
$monitoringDetail.http_build_query(['id' => $result['id']]),
231+
[
232+
'class' => 'ajax',
233+
'data-title' => get_lang('MonitoringDetail'),
234+
'data-size' => 'lg',
235+
]
236+
);
237+
}
238+
222239
$table->setCellContents($row, 0, $result['username']);
223240
$table->setCellContents($row, 1, $result['user_fullname']);
224241
$table->setCellContents($row, 2, $result['quiz_title']);
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
/* For licensing terms, see /license.txt */
4+
5+
use Chamilo\PluginBundle\ExerciseMonitoring\Controller\DetailController;
6+
use Chamilo\PluginBundle\ExerciseMonitoring\Entity\Log;
7+
use Symfony\Component\HttpFoundation\Request as HttpRequest;
8+
use Symfony\Component\HttpFoundation\Response as HttpResponse;
9+
10+
require_once __DIR__.'/../../../main/inc/global.inc.php';
11+
12+
if (!api_is_allowed_to_edit()) {
13+
api_not_allowed(true);
14+
}
15+
16+
$em = Database::getManager();
17+
$logRepository = $em->getRepository(Log::class);
18+
19+
$detailController = new DetailController(
20+
ExerciseMonitoringPlugin::create(),
21+
HttpRequest::createFromGlobals(),
22+
$em,
23+
$logRepository
24+
);
25+
26+
try {
27+
$response = $detailController();
28+
} catch (Exception $e) {
29+
$response = HttpResponse::create('', HttpResponse::HTTP_FORBIDDEN);
30+
}
31+
32+
$response->send();
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
<?php
2+
3+
/* For license terms, see /license.txt */
4+
5+
namespace Chamilo\PluginBundle\ExerciseMonitoring\Controller;
6+
7+
use Chamilo\CoreBundle\Entity\TrackEAttempt;
8+
use Chamilo\CoreBundle\Entity\TrackEExercises;
9+
use Chamilo\CourseBundle\Entity\CQuiz;
10+
use Chamilo\CourseBundle\Entity\CQuizQuestion;
11+
use Chamilo\PluginBundle\ExerciseMonitoring\Entity\Log;
12+
use Chamilo\UserBundle\Entity\User;
13+
use Display;
14+
use Doctrine\ORM\EntityManager;
15+
use Doctrine\ORM\EntityRepository;
16+
use Doctrine\ORM\Query\Expr\Join;
17+
use Exception;
18+
use Exercise;
19+
use ExerciseMonitoringPlugin;
20+
use HTML_Table;
21+
use Symfony\Component\Filesystem\Filesystem;
22+
use Symfony\Component\HttpFoundation\File\UploadedFile;
23+
use Symfony\Component\HttpFoundation\Request as HttpRequest;
24+
use Symfony\Component\HttpFoundation\Response as HttpResponse;
25+
26+
class DetailController
27+
{
28+
/**
29+
* @var ExerciseMonitoringPlugin
30+
*/
31+
private $plugin;
32+
33+
/**
34+
* @var HttpRequest
35+
*/
36+
private $request;
37+
38+
/**
39+
* @var EntityManager
40+
*/
41+
private $em;
42+
43+
/**
44+
* @var EntityRepository
45+
*/
46+
private $logRepository;
47+
48+
public function __construct(
49+
ExerciseMonitoringPlugin $plugin,
50+
HttpRequest $request,
51+
EntityManager $em,
52+
EntityRepository $logRepository
53+
) {
54+
$this->plugin = $plugin;
55+
$this->request = $request;
56+
$this->em = $em;
57+
$this->logRepository = $logRepository;
58+
}
59+
60+
/**
61+
* @throws Exception
62+
*/
63+
public function __invoke(): HttpResponse
64+
{
65+
if (!$this->plugin->isEnabled(true)) {
66+
throw new Exception();
67+
}
68+
69+
$trackExe = $this->em->find(
70+
TrackEExercises::class,
71+
$this->request->query->getInt('id')
72+
);
73+
74+
if (!$trackExe) {
75+
throw new Exception();
76+
}
77+
78+
$exercise = $this->em->find(CQuiz::class, $trackExe->getExeExoId());
79+
$user = api_get_user_entity($trackExe->getExeUserId());
80+
81+
$objExercise = new Exercise();
82+
$objExercise->read($trackExe->getExeExoId());
83+
84+
$qb = $this->logRepository->createQueryBuilder('l');
85+
$qb
86+
->select(['l.imageFilename', 'l.createdAt']);
87+
88+
if (ONE_PER_PAGE == $objExercise->selectType()) {
89+
$qb
90+
->addSelect(['qq.question'])
91+
->innerJoin(CQuizQuestion::class, 'qq', Join::WITH, 'l.level = qq.iid');
92+
}
93+
94+
$logs = $qb
95+
->andWhere(
96+
$qb->expr()->eq('l.exe', $trackExe->getExeId())
97+
)
98+
->addOrderBy('l.createdAt')
99+
->getQuery()
100+
->getResult();
101+
102+
$content = $this->generateHeader($objExercise, $user, $trackExe)
103+
.'<hr>'
104+
.$this->generateSnapshotList($logs, $trackExe->getExeUserId());
105+
106+
return HttpResponse::create($content);
107+
}
108+
109+
private function generateHeader(Exercise $objExercise, User $student, TrackEExercises $trackExe): string
110+
{
111+
$startDate = api_get_local_time($trackExe->getStartDate(), null, null, true, true, true);
112+
$endDate = api_get_local_time($trackExe->getExeDate(), null, null, true, true, true);
113+
114+
return Display::page_subheader2($objExercise->selectTitle())
115+
.Display::tag('p', $student->getCompleteNameWithUsername(), ['class' => 'lead'])
116+
.Display::tag(
117+
'p',
118+
sprintf(get_lang('QuizRemindStartDate'), $startDate)
119+
.sprintf(get_lang('QuizRemindEndDate'), $endDate)
120+
.sprintf(get_lang('QuizRemindDuration'), api_format_time($trackExe->getExeDuration()))
121+
);
122+
}
123+
124+
/**
125+
* @param array $logs
126+
* @param int $userId
127+
*
128+
* @return string
129+
*/
130+
private function generateSnapshotList(array $logs, int $userId): string
131+
{
132+
$pluginDirName = api_get_path(WEB_UPLOAD_PATH).'plugins/exercisemonitoring';
133+
134+
$html = '';
135+
136+
foreach ($logs as $log) {
137+
$userDirName = $pluginDirName.'/'.$userId;
138+
139+
$date = api_get_local_time($log['createdAt'], null, null, true, true, true);
140+
141+
$html .= '<div class="col-xs-12 col-sm-6 col-md-3">';
142+
$html .= '<div class="thumbnail">';
143+
$html .= Display::img(
144+
$userDirName.'/'.$log['imageFilename'],
145+
$date
146+
);
147+
$html .= '<div class="caption">';
148+
$html .= Display::tag('p', $date, ['class' => 'text-center']);
149+
150+
if (!empty($log['question'])) {
151+
$html .= Display::tag('div', $log['question'], ['class' => 'text-center']);
152+
}
153+
154+
$html .= '</div>';
155+
$html .= '</div>';
156+
$html .= '</div>';
157+
}
158+
159+
return '<div class="row">'.$html.'</div>';
160+
}
161+
}

plugin/exercisemonitoring/src/Controller/ExerciseSubmitController.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,12 @@ public function __invoke(): HttpResponse
3737
$existingExeId = (int) ChamiloSession::read('exe_id');
3838

3939
$levelId = $this->request->request->getInt('level_id');
40-
$exercise = $this->em->find(
41-
CQuiz::class,
42-
$this->request->request->getInt('exercise_id')
43-
);
40+
$exerciseId = $this->request->request->getInt('exercise_id');
41+
42+
$exercise = $this->em->find(CQuiz::class, $exerciseId);
43+
44+
$objExercise = new Exercise();
45+
$objExercise->read($exerciseId);
4446

4547
$trackingExercise = $this->em->find(TrackEExercises::class, $existingExeId);
4648

@@ -54,7 +56,7 @@ public function __invoke(): HttpResponse
5456
$imgSubmit->move($userDirName, $newFilename);
5557
}
5658

57-
if (ONE_PER_PAGE === $exercise->getType()) {
59+
if (ONE_PER_PAGE == $objExercise->selectType()) {
5860
$question = $this->em->find(CQuizQuestion::class, $levelId);
5961
$level = $question->getIid();
6062
}

0 commit comments

Comments
 (0)