Differences Between: [Versions 400 and 403] [Versions 401 and 403] [Versions 402 and 403]
1 <?php 2 3 namespace Packback\Lti1p3; 4 5 class LtiAssignmentsGradesService extends LtiAbstractService 6 { 7 public const CONTENTTYPE_SCORE = 'application/vnd.ims.lis.v1.score+json'; 8 public const CONTENTTYPE_LINEITEM = 'application/vnd.ims.lis.v2.lineitem+json'; 9 public const CONTENTTYPE_LINEITEMCONTAINER = 'application/vnd.ims.lis.v2.lineitemcontainer+json'; 10 public const CONTENTTYPE_RESULTCONTAINER = 'application/vnd.ims.lis.v2.resultcontainer+json'; 11 12 public function getScope(): array 13 { 14 return $this->getServiceData()['scope']; 15 } 16 17 // https://www.imsglobal.org/spec/lti-ags/v2p0#assignment-and-grade-service-claim 18 // When an LTI message is launching a resource associated to one and only one lineitem, 19 // the claim must include the endpoint URL for accessing the associated line item; 20 // in all other cases, this property must be either blank or not included in the claim. 21 public function getResourceLaunchLineItem(): ?LtiLineitem 22 { 23 $serviceData = $this->getServiceData(); 24 if (empty($serviceData['lineitem'])) { 25 return null; 26 } 27 28 return LtiLineitem::new()->setId($serviceData['lineitem']); 29 } 30 31 public function putGrade(LtiGrade $grade, LtiLineitem $lineitem = null) 32 { 33 $this->validateScopes([LtiConstants::AGS_SCOPE_SCORE]); 34 35 $lineitem = $this->ensureLineItemExists($lineitem); 36 37 $scoreUrl = $lineitem->getId(); 38 39 // Place '/scores' before url params 40 $pos = strpos($scoreUrl, '?'); 41 $scoreUrl = $pos === false ? $scoreUrl.'/scores' : substr_replace($scoreUrl, '/scores', $pos, 0); 42 43 $request = new ServiceRequest( 44 ServiceRequest::METHOD_POST, 45 $scoreUrl, 46 ServiceRequest::TYPE_SYNC_GRADE 47 ); 48 $request->setBody($grade); 49 $request->setContentType(static::CONTENTTYPE_SCORE); 50 51 return $this->makeServiceRequest($request); 52 } 53 54 public function findLineItem(LtiLineitem $newLineItem): ?LtiLineitem 55 { 56 $lineitems = $this->getLineItems(); 57 58 foreach ($lineitems as $lineitem) { 59 if ($this->isMatchingLineitem($lineitem, $newLineItem)) { 60 return new LtiLineitem($lineitem); 61 } 62 } 63 64 return null; 65 } 66 67 public function updateLineitem(LtiLineItem $lineitemToUpdate): LtiLineitem 68 { 69 $request = new ServiceRequest( 70 ServiceRequest::METHOD_PUT, 71 $this->getServiceData()['lineitem'], 72 ServiceRequest::TYPE_UPDATE_LINEITEM 73 ); 74 75 $request->setBody($lineitemToUpdate) 76 ->setContentType(static::CONTENTTYPE_LINEITEM) 77 ->setAccept(static::CONTENTTYPE_LINEITEM); 78 79 $updatedLineitem = $this->makeServiceRequest($request); 80 81 return new LtiLineitem($updatedLineitem['body']); 82 } 83 84 public function createLineitem(LtiLineitem $newLineItem): LtiLineitem 85 { 86 $request = new ServiceRequest( 87 ServiceRequest::METHOD_POST, 88 $this->getServiceData()['lineitems'], 89 ServiceRequest::TYPE_CREATE_LINEITEM 90 ); 91 $request->setBody($newLineItem) 92 ->setContentType(static::CONTENTTYPE_LINEITEM) 93 ->setAccept(static::CONTENTTYPE_LINEITEM); 94 $createdLineItem = $this->makeServiceRequest($request); 95 96 return new LtiLineitem($createdLineItem['body']); 97 } 98 99 public function deleteLineitem(): array 100 { 101 $request = new ServiceRequest( 102 ServiceRequest::METHOD_DELETE, 103 $this->getServiceData()['lineitem'], 104 ServiceRequest::TYPE_DELETE_LINEITEM 105 ); 106 107 return $this->makeServiceRequest($request); 108 } 109 110 public function findOrCreateLineitem(LtiLineitem $newLineItem): LtiLineitem 111 { 112 return $this->findLineItem($newLineItem) ?? $this->createLineitem($newLineItem); 113 } 114 115 public function getGrades(LtiLineitem $lineitem = null) 116 { 117 $lineitem = $this->ensureLineItemExists($lineitem); 118 $resultsUrl = $lineitem->getId(); 119 120 // Place '/results' before url params 121 $pos = strpos($resultsUrl, '?'); 122 $resultsUrl = $pos === false ? $resultsUrl.'/results' : substr_replace($resultsUrl, '/results', $pos, 0); 123 124 $request = new ServiceRequest( 125 ServiceRequest::METHOD_GET, 126 $resultsUrl, 127 ServiceRequest::TYPE_GET_GRADES 128 ); 129 $request->setAccept(static::CONTENTTYPE_RESULTCONTAINER); 130 131 return $this->getAll($request); 132 } 133 134 public function getLineItems(): array 135 { 136 $this->validateScopes([LtiConstants::AGS_SCOPE_LINEITEM, LtiConstants::AGS_SCOPE_LINEITEM_READONLY]); 137 138 $request = new ServiceRequest( 139 ServiceRequest::METHOD_GET, 140 $this->getServiceData()['lineitems'], 141 ServiceRequest::TYPE_GET_LINEITEMS 142 ); 143 $request->setAccept(static::CONTENTTYPE_LINEITEMCONTAINER); 144 145 $lineitems = $this->getAll($request); 146 147 // If there is only one item, then wrap it in an array so the foreach works 148 if (isset($lineitems['body']['id'])) { 149 $lineitems['body'] = [$lineitems['body']]; 150 } 151 152 return $lineitems; 153 } 154 155 public function getLineItem(string $url): LtiLineitem 156 { 157 $this->validateScopes([LtiConstants::AGS_SCOPE_LINEITEM, LtiConstants::AGS_SCOPE_LINEITEM_READONLY]); 158 159 $request = new ServiceRequest( 160 ServiceRequest::METHOD_GET, 161 $url, 162 ServiceRequest::TYPE_GET_LINEITEM 163 ); 164 $request->setAccept(static::CONTENTTYPE_LINEITEM); 165 166 $response = $this->makeServiceRequest($request)['body']; 167 168 return new LtiLineitem($response); 169 } 170 171 private function ensureLineItemExists(LtiLineitem $lineitem = null): LtiLineitem 172 { 173 // If no line item is passed in, attempt to use the one associated with 174 // this launch. 175 if (!isset($lineitem)) { 176 $lineitem = $this->getResourceLaunchLineItem(); 177 } 178 179 // If none exists still, create a default line item. 180 if (!isset($lineitem)) { 181 $defaultLineitem = LtiLineitem::new() 182 ->setLabel('default') 183 ->setScoreMaximum(100); 184 $lineitem = $this->createLineitem($defaultLineitem); 185 } 186 187 // If the line item does not contain an ID, find or create it. 188 if (empty($lineitem->getId())) { 189 $lineitem = $this->findOrCreateLineitem($lineitem); 190 } 191 192 return $lineitem; 193 } 194 195 private function isMatchingLineitem(array $lineitem, LtiLineitem $newLineItem): bool 196 { 197 return $newLineItem->getTag() == ($lineitem['tag'] ?? null) && 198 $newLineItem->getResourceId() == ($lineitem['resourceId'] ?? null) && 199 $newLineItem->getResourceLinkId() == ($lineitem['resourceLinkId'] ?? null); 200 } 201 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body