Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 57
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
SendLtiOutcomeTask
0.00% covered (danger)
0.00%
0 / 57
0.00% covered (danger)
0.00%
0 / 3
90
0.00% covered (danger)
0.00%
0 / 1
 __invoke
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 1
30
 sendLtiOutcome
0.00% covered (danger)
0.00%
0 / 30
0.00% covered (danger)
0.00%
0 / 1
12
 getLtiOutcomeXmlFactory
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3/**
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; under version 2
7 * of the License (non-upgradable).
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 *
18 * Copyright (c) 2014-2020 (original work) Open Assessment Technologies SA;
19 *
20 */
21
22declare(strict_types=1);
23
24namespace oat\ltiDeliveryProvider\model\tasks;
25
26use common_report_Report;
27use oat\oatbox\extension\AbstractAction;
28use oat\oatbox\log\LoggerAwareTrait;
29use oat\taoDelivery\model\execution\ServiceProxy;
30use oat\taoLti\models\classes\LtiOutcome\LtiOutcomeXmlFactory;
31use oat\taoLti\models\classes\LtiService;
32use oat\taoOutcomeUi\model\ResultsService;
33use oat\taoResultServer\models\classes\ResultAliasServiceInterface;
34use taoResultServer_models_classes_OutcomeVariable;
35
36class SendLtiOutcomeTask extends AbstractAction
37{
38    use LoggerAwareTrait;
39
40    public const VARIABLE_IDENTIFIER = 'LtiOutcome';
41
42    public function __invoke($params)
43    {
44        $report = new common_report_Report(common_report_Report::TYPE_ERROR);
45        $deliveryResultIdentifier = $params['deliveryResultIdentifier'];
46        $consumerKey = $params['consumerKey'];
47        $serviceUrl = $params['serviceUrl'];
48
49        try {
50            $deliveryExecution = ServiceProxy::singleton()->getDeliveryExecution($deliveryResultIdentifier);
51            $resultsService = ResultsService::singleton();
52            $implementation = $resultsService->getReadableImplementation($deliveryExecution->getDelivery());
53            $resultsService->setImplementation($implementation);
54
55            $variables = $resultsService->getVariableDataFromDeliveryResult(
56                $deliveryResultIdentifier,
57                [taoResultServer_models_classes_OutcomeVariable::class]
58            );
59
60            $submitted = 0;
61            /** @var taoResultServer_models_classes_OutcomeVariable $variable */
62            foreach ($variables as $variable) {
63                if (self::VARIABLE_IDENTIFIER == $variable->getIdentifier()) {
64                    $this->sendLtiOutcome($variable, $deliveryResultIdentifier, $consumerKey, $serviceUrl);
65                    $submitted++;
66                    break;
67                }
68            }
69            if (0 === $submitted) {
70                throw new \common_Exception(
71                    'No LTI Outcome has been submitter for execution' . $deliveryResultIdentifier
72                );
73            }
74        } catch (\Exception $exception) {
75            $report->setMessage($exception->getMessage());
76        }
77
78        $report->setType(common_report_Report::TYPE_SUCCESS);
79        return $report;
80    }
81
82    /**
83     * @param taoResultServer_models_classes_OutcomeVariable $testVariable
84     * @param $deliveryResultIdentifier
85     * @param $consumerKey
86     * @param $serviceUrl
87     * @return bool
88     * @throws \common_exception_Error
89     * @throws \oat\taoLti\models\classes\LtiException
90     */
91    private function sendLtiOutcome(
92        taoResultServer_models_classes_OutcomeVariable $testVariable,
93        $deliveryResultIdentifier,
94        $consumerKey,
95        $serviceUrl
96    ) {
97        $grade = (string)$testVariable->getValue();
98
99        /** @var ResultAliasServiceInterface $resultAliasService */
100        $resultAliasService = $this->getServiceLocator()->get(ResultAliasServiceInterface::SERVICE_ID);
101        $deliveryResultAlias = $resultAliasService->getResultAlias($deliveryResultIdentifier);
102        $deliveryResultIdentifier = empty($deliveryResultAlias)
103            ? $deliveryResultIdentifier
104            : current($deliveryResultAlias);
105
106        $message = $this->getLtiOutcomeXmlFactory()->buildReplaceResultRequest(
107            $deliveryResultIdentifier,
108            $grade,
109            uniqid('', true)
110        );
111
112        $credentialResource = LtiService::singleton()->getCredential($consumerKey);
113        $credentials = new \tao_models_classes_oauth_Credentials($credentialResource);
114        //Building POX raw http message
115        $unSignedOutComeRequest = new \common_http_Request($serviceUrl, 'POST', []);
116        $unSignedOutComeRequest->setBody($message);
117        $signingService = new \tao_models_classes_oauth_Service();
118        $signedRequest = $signingService->sign($unSignedOutComeRequest, $credentials, true);
119        //Hack for moodle compatibility, the header is ignored for the signature computation
120        $signedRequest->setHeader("Content-Type", "application/xml");
121
122        $response = $signedRequest->send(true);
123
124        if ('200' != $response->httpCode) {
125            $this->logWarning("Request sent (Body)\n" . $signedRequest->getBody() . "\n");
126            $this->logWarning("Request sent (Headers)\n" . serialize($signedRequest->getHeaders()) . "\n");
127            $this->logWarning("\nHTTP Code received: " . $response->httpCode . "\n");
128
129            $this->logWarning("\nHTTP From: " . $response->effectiveUrl . "\n");
130            $this->logWarning("\nHTTP Content received: " . $response->responseData . "\n");
131
132            throw new \common_exception_Error(
133                'An HTTP level problem occurred when sending the outcome to the service url'
134            );
135        } else {
136            $this->logInfo('Submited LTI score with id "' . $deliveryResultIdentifier . '"');
137        }
138        return true;
139    }
140
141    private function getLtiOutcomeXmlFactory(): LtiOutcomeXmlFactory
142    {
143        return $this->getServiceLocator()->get(LtiOutcomeXmlFactory::class);
144    }
145}