Skip to content

Commit ac6c720

Browse files
authored
Merge pull request #160 from packbackbooks/mgmt-191-user-id-filter
Add user ID filter to grades
2 parents 9f4ad55 + ead0780 commit ac6c720

File tree

4 files changed

+90
-10
lines changed

4 files changed

+90
-10
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,5 @@ vendor
1717
# ignore the coverage folders
1818
**/.phpunit.cache
1919
**/coverage
20+
21+
**/.claude/settings.local.json

CLAUDE.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Build/Test/Lint Commands
6+
- Run all tests: `composer test`
7+
- Run a single test: `vendor/bin/phpunit tests/path/to/TestFile.php --filter testMethodName`
8+
- Run static analysis: `vendor/bin/phpstan analyse`
9+
- Check code style: `composer lint`
10+
- Fix code style issues: `composer lint-fix`
11+
12+
## Code Style Guidelines
13+
- Follow PSR-1/PSR-2 coding standards (Laravel preset)
14+
- Use PHP 8.1+ features and type hints
15+
- Classes organized in the namespace `Packback\Lti1p3`
16+
- Tests in the namespace `Tests`
17+
- Document public methods with PHPDoc blocks
18+
- Constants for error messages (use const ERR_* pattern)
19+
- Use interfaces for dependency injection
20+
- Error handling: Throw exceptions with descriptive messages
21+
- Import all classes with use statements
22+
- Use strict type checking (avoid loose comparisons)
23+
- Use camelCase for method names and variables
24+
- Line length: 80-120 characters

src/LtiAssignmentsGradesService.php

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public function putGrade(LtiGrade $grade, ?LtiLineitem $lineitem = null)
3333
$this->validateScopes([LtiConstants::AGS_SCOPE_SCORE]);
3434

3535
$lineitem = $this->ensureLineItemExists($lineitem);
36-
$scoreUrl = $this->appendLineItemPath($lineitem, '/scores');
36+
$scoreUrl = static::appendLineItemPath($lineitem, '/scores');
3737

3838
$request = new ServiceRequest(
3939
ServiceRequest::METHOD_POST,
@@ -107,10 +107,16 @@ public function findOrCreateLineitem(LtiLineitem $newLineItem): LtiLineitem
107107
return $this->findLineItem($newLineItem) ?? $this->createLineitem($newLineItem);
108108
}
109109

110-
public function getGrades(?LtiLineitem $lineitem = null)
110+
public function getGrades(?LtiLineitem $lineitem = null, ?string $userId = null)
111111
{
112112
$lineitem = $this->ensureLineItemExists($lineitem);
113-
$resultsUrl = $this->appendLineItemPath($lineitem, '/results');
113+
$resultsUrl = static::appendLineItemPath($lineitem, '/results');
114+
115+
if (isset($userId)) {
116+
$resultsUrl = static::appendQueryParams($resultsUrl, [
117+
'user_id' => $userId,
118+
]);
119+
}
114120

115121
$request = new ServiceRequest(
116122
ServiceRequest::METHOD_GET,
@@ -190,17 +196,31 @@ private function isMatchingLineitem(array $lineitem, LtiLineitem $newLineItem):
190196
$newLineItem->getResourceLinkId() == ($lineitem['resourceLinkId'] ?? null);
191197
}
192198

193-
private function appendLineItemPath(LtiLineitem $lineItem, string $suffix): string
199+
public static function appendLineItemPath(LtiLineitem $lineItem, string $suffix): string
194200
{
195201
$url = $lineItem->getId();
196-
$pos = strpos($url, '?');
197202

198-
if ($pos === false) {
199-
$url = $url.$suffix;
203+
$path = implode('', [
204+
parse_url($url, PHP_URL_HOST),
205+
parse_url($url, PHP_URL_PORT) ? ':'.parse_url($url, PHP_URL_PORT) : '',
206+
parse_url($url, PHP_URL_PATH),
207+
]);
208+
209+
return str_replace($path, $path.$suffix, $url);
210+
}
211+
212+
public static function appendQueryParams(string $url, array $params): string
213+
{
214+
$existingQueryString = parse_url($url, PHP_URL_QUERY);
215+
if ($existingQueryString) {
216+
parse_str($existingQueryString, $existingQueryParams);
217+
$queryString = http_build_query(array_merge($existingQueryParams, $params));
218+
219+
return str_replace($existingQueryString, $queryString, $url);
200220
} else {
201-
$url = substr_replace($url, $suffix, $pos, 0);
202-
}
221+
$queryString = http_build_query($params);
203222

204-
return $url;
223+
return $url.'?'.$queryString;
224+
}
205225
}
206226
}

tests/LtiAssignmentsGradesServiceTest.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,4 +480,38 @@ public function test_it_gets_a_line_item()
480480

481481
$this->assertEquals($expected, $result);
482482
}
483+
484+
public function test_it_appends_path()
485+
{
486+
// A simple example
487+
$lineItem = new LtiLineitem(['id' => 'https://example.com']);
488+
489+
$result = LtiAssignmentsGradesService::appendLineItemPath($lineItem, '/bat');
490+
491+
$this->assertEquals('https://example.com/bat', $result);
492+
493+
// A complicated example
494+
$lineItem = new LtiLineitem(['id' => 'https://example.com:443/foo?bar=baz']);
495+
496+
$result = LtiAssignmentsGradesService::appendLineItemPath($lineItem, '/bat');
497+
498+
$this->assertEquals('https://example.com:443/foo/bat?bar=baz', $result);
499+
}
500+
501+
public function test_it_query_params()
502+
{
503+
// A simple example
504+
$url = 'https://example.com';
505+
506+
$result = LtiAssignmentsGradesService::appendQueryParams($url, ['user_id' => 'foo']);
507+
508+
$this->assertEquals('https://example.com?user_id=foo', $result);
509+
510+
// A complicated example
511+
$url = 'https://example.com:443/foo?bar=baz';
512+
513+
$result = LtiAssignmentsGradesService::appendQueryParams($url, ['user_id' => 'foo']);
514+
515+
$this->assertEquals('https://example.com:443/foo?bar=baz&user_id=foo', $result);
516+
}
483517
}

0 commit comments

Comments
 (0)