diff --git a/src/Adapters/Groups/MockGroupAdapter.php b/src/Adapters/Groups/MockGroupAdapter.php index e3c195e..b6c76fc 100644 --- a/src/Adapters/Groups/MockGroupAdapter.php +++ b/src/Adapters/Groups/MockGroupAdapter.php @@ -31,7 +31,9 @@ class MockGroupAdapter extends AbstractAdapter $coreGroupMembers = []; foreach ($mockGroup->getMembers() as $mockGroupMember) { $coreGroupMember = new MultiValuedAttribute(); - $coreGroupMember->setValue($mockGroupMember); + $coreGroupMember->setValue($mockGroupMember->getValue()); + $coreGroupMember->setDisplay($mockGroupMember->getDisplay()); + $coreGroupMember->setRef($mockGroupMember->getRef()); $coreGroupMembers[] = $coreGroupMember; } @@ -60,12 +62,15 @@ class MockGroupAdapter extends AbstractAdapter if ($coreGroup->getMembers() !== null && !empty($coreGroup->getMembers())) { $mockGroupMembers = []; foreach ($coreGroup->getMembers() as $coreGroupMember) { - $mockGroupMembers[] = $coreGroupMember->getValue(); + $mockGroupMember = new MultiValuedAttribute(); + $mockGroupMember->setValue($coreGroupMember->getValue()); + $mockGroupMember->setDisplay($coreGroupMember->getDisplay()); + $mockGroupMember->setRef($coreGroupMember->getRef()); + $mockGroupMembers[] = $mockGroupMember; } $mockGroup->setMembers($mockGroupMembers); } - return $mockGroup; } } diff --git a/src/DataAccess/Groups/MockGroupDataAccess.php b/src/DataAccess/Groups/MockGroupDataAccess.php index 67d6b3d..de4a2d4 100644 --- a/src/DataAccess/Groups/MockGroupDataAccess.php +++ b/src/DataAccess/Groups/MockGroupDataAccess.php @@ -109,8 +109,10 @@ class MockGroupDataAccess $insertRes = $insertStatement->execute([ $groupToCreate->getId(), $groupToCreate->getDisplayName(), + // we serialize the whole members array and store it as is in the database + // this is relatively dirty, but fine enough for a mock group implementation $groupToCreate->getMembers() !== null && !empty($groupToCreate->getMembers()) - ? $groupToCreate->getMembers() : "", + ? serialize($groupToCreate->getMembers()) : "", $dateNow, $dateNow ]); @@ -149,7 +151,7 @@ class MockGroupDataAccess $query = $query . "members = ?, "; // We need to transform the string array of user IDs to a single string - $values[] = implode(",", $groupToUpdate->getMembers()); + $values[] = serialize($groupToUpdate->getMembers()); } if (empty($query)) { diff --git a/src/Models/Mock/MockGroup.php b/src/Models/Mock/MockGroup.php index 5e5c6ec..2838ba9 100644 --- a/src/Models/Mock/MockGroup.php +++ b/src/Models/Mock/MockGroup.php @@ -7,7 +7,7 @@ class MockGroup extends MockCommonEntity /** @var string|null $displayName */ private $displayName; - /** @var array|null $members */ + /** @var \Opf\Models\SCIM\MultiValuedAttribute|null $members */ private $members; public function mapFromArray($properties = null): bool @@ -36,7 +36,8 @@ class MockGroup extends MockCommonEntity } if (strcasecmp($key, 'members') === 0) { - $this->members = $value; + // the members array is stored as a serialized array in the DB + $this->members = unserialize($value); continue; } $result = false; diff --git a/src/Models/SCIM/Standard/Groups/CoreGroup.php b/src/Models/SCIM/Standard/Groups/CoreGroup.php index 8127b47..758730a 100644 --- a/src/Models/SCIM/Standard/Groups/CoreGroup.php +++ b/src/Models/SCIM/Standard/Groups/CoreGroup.php @@ -62,7 +62,9 @@ class CoreGroup extends CommonEntity $members = []; foreach ($data['members'] as $member) { $scimMember = new MultiValuedAttribute(); - $scimMember->setValue($member); + $scimMember->setValue($member['value']); + $scimMember->setDisplay($member['display']); + $scimMember->setRef($member['$ref']); $members[] = $scimMember; } $this->setMembers($members); diff --git a/src/Util/Filters/FilterParser.php b/src/Util/Filters/FilterParser.php index fb9aa92..5650772 100644 --- a/src/Util/Filters/FilterParser.php +++ b/src/Util/Filters/FilterParser.php @@ -2,6 +2,7 @@ namespace Opf\Util\Filters; +use Attribute; use Opf\Models\SCIM\Standard\Filters\AttributeExpression; use Opf\Models\SCIM\Standard\Filters\FilterException; use Opf\Models\SCIM\Standard\Filters\FilterExpression; @@ -24,16 +25,35 @@ class FilterParser ); } - $splitFilterExpression = explode(" ", $filterExpression); - if (count($splitFilterExpression) < 2 || count($splitFilterExpression) > 3) { + $splitAttributePathFromFilterExpression = explode(" ", $filterExpression, 2); + + if (!isset($splitAttributePathFromFilterExpression[1]) || empty($splitAttributePathFromFilterExpression[1])) { throw new FilterException("Incorrectly formatted AttributeExpression"); + } else if (strcmp($splitAttributePathFromFilterExpression[1], "pr") === 0) { + $attributeExpression = new AttributeExpression( + $splitAttributePathFromFilterExpression[0], // The attribute path + "pr", // The comparison operator (which must be "pr" in this case) + null // The comparison value (must be null due to "pr") + ); + } else { + $splitFilterExpressionWithoutAttributePath = explode(" ", $splitAttributePathFromFilterExpression[1], 2); + $attributeExpression = new AttributeExpression( + $splitAttributePathFromFilterExpression[0], // The attribute path + $splitFilterExpressionWithoutAttributePath[0], // The comparison operator (which is different from "pr") + $splitFilterExpressionWithoutAttributePath[1] // The comparison value (can contain spaces) + ); } - $attributeExpression = new AttributeExpression( - $splitFilterExpression[0], - $splitFilterExpression[1], - $splitFilterExpression[2] - ); + + // if (count($splitFilterExpression) < 2 || count($splitFilterExpression) > 3) { + // throw new FilterException("Incorrectly formatted AttributeExpression"); + // } + + // $attributeExpression = new AttributeExpression( + // $splitFilterExpression[0], + // $splitFilterExpression[1], + // $splitFilterExpression[2] + // ); return $attributeExpression; } diff --git a/test/resources/filterTestUsers.json b/test/resources/filterTestUsers.json index 659df83..16b2eff 100644 --- a/test/resources/filterTestUsers.json +++ b/test/resources/filterTestUsers.json @@ -15,5 +15,10 @@ "userName": "testuser3", "externalId": "testuser3external", "profileUrl": "http://example.com/testuser3" + }, + { + "userName": "some user", + "externalId": "testsome_userexternal", + "profileUrl": "http://example.com/some_user" } ] \ No newline at end of file diff --git a/test/unit/FilterParserTest.php b/test/unit/FilterParserTest.php index 27b2d00..48a0567 100644 --- a/test/unit/FilterParserTest.php +++ b/test/unit/FilterParserTest.php @@ -46,12 +46,25 @@ final class FilterParserTest extends TestCase $parsedFilterExpression = FilterParser::parseFilterExpression($filterString); } - public function testParseTooLongFilterExpression() + public function testFilterExpressionWithSpacesInValue() + { + $filterString = "userName eq \"some value\""; + $parsedFilterExpression = FilterParser::parseFilterExpression($filterString); + + $this->assertInstanceOf(FilterExpression::class, $parsedFilterExpression); + $this->assertInstanceOf(AttributeExpression::class, $parsedFilterExpression); + + $this->assertEquals("userName", $parsedFilterExpression->getAttributePath()); + $this->assertEquals(AttributeOperator::OP_EQ, $parsedFilterExpression->getCompareOperator()); + $this->assertEquals("\"some value\"", $parsedFilterExpression->getComparisonValue()); + } + + public function testParseIncorrectExpression() { $this->expectException(FilterException::class); - $this->expectExceptionMessage("Incorrectly formatted AttributeExpression"); + $this->expectExceptionMessage("Invalid AttributeOperation passed to AttributeExpression"); - $filterString = "userName eq some value"; + $filterString = "userName blabla \"some moreblabla\""; $parsedFilterExpression = FilterParser::parseFilterExpression($filterString); } } diff --git a/test/unit/FilterUtilTest.php b/test/unit/FilterUtilTest.php index 7b084b1..c304f59 100644 --- a/test/unit/FilterUtilTest.php +++ b/test/unit/FilterUtilTest.php @@ -42,15 +42,32 @@ final class FilterUtilTest extends TestCase $filterString = "userName sw testuser"; $filteredScimUsers = FilterUtil::performFiltering($filterString, $this->scimUsers); - $this->assertEquals($this->scimUsers, $filteredScimUsers); + $this->assertEquals(array_splice($this->scimUsers, 0, 3), $filteredScimUsers); } public function testInvalidFiltering() { $this->expectException(FilterException::class); - $this->expectExceptionMessage("Incorrectly formatted AttributeExpression"); + $this->expectExceptionMessage("Invalid AttributeOperation passed to AttributeExpression"); - $filterString = "externalId eq some value"; + $filterString = "externalId bla some value"; $filteredScimUsers = FilterUtil::performFiltering($filterString, $this->scimUsers); } + + public function testFilteringWithSpaces() + { + $filterString = "userName eq some user"; + $filteredScimUsers = FilterUtil::performFiltering($filterString, $this->scimUsers); + + $this->assertEquals(array($this->scimUsers[3]), $filteredScimUsers); + } + + public function testIncorrectPRFilterExpression() + { + $this->expectException(FilterException::class); + $this->expectExceptionMessage("\"pr\" filter operator must be used without a comparison value"); + + $filterString = "userName pr \"some blabla\""; + $parsedFilterExpression = FilterUtil::performFiltering($filterString, $this->scimUsers); + } }