Skip to content

Commit

Permalink
Allow other bag-info tag options
Browse files Browse the repository at this point in the history
  • Loading branch information
whikloj committed Apr 24, 2024
1 parent 25243f8 commit e6906c5
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 10 deletions.
5 changes: 0 additions & 5 deletions src/Profiles/BagItProfile.php
Original file line number Diff line number Diff line change
Expand Up @@ -337,16 +337,11 @@ public function getBagInfoTags(): array
/**
* @param array $bagInfoTags Parsed profile Bag-Info sections
* @return BagItProfile The profile object.
* @throws ProfileException If invalid options are specified for a tag.
*/
private function setBagInfoTags(array $bagInfoTags): BagItProfile
{
$expectedKeys = ['required' => 0, 'values' => 0, 'repeatable' => 0, 'description' => 0];
$this->profileBagInfoTags = [];
foreach ($bagInfoTags as $tagName => $tagOpts) {
if (count(array_diff_key($tagOpts, $expectedKeys)) > 0) {
throw new ProfileException("Invalid tag options for $tagName");
}
if (self::matchStrings('BagIt-Profile-Identifier', $tagName)) {
$this->profileWarnings[] = "The tag BagIt-Profile-Identifier is always required, but SHOULD NOT be " .
"listed under Bag-Info in the Profile.";
Expand Down
41 changes: 40 additions & 1 deletion src/Profiles/ProfileTags.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
*/
class ProfileTags
{
/**
* Array with keys matching optional keys from specification, all other keys are system specific.
*/
private const SPEC_TAGS = ['required' => 0, 'values' => 0, 'repeatable' => 0, 'description' => 0];

/**
* @var string
*/
Expand All @@ -38,6 +43,11 @@ class ProfileTags
*/
private string $description = "";

/**
* @var array<string, mixed>
*/
private array $otherOptions = [];

/**
* ProfileTags constructor.
* @param string $tag
Expand Down Expand Up @@ -95,14 +105,43 @@ public function getDescription(): string
return $this->description;
}

/**
* Return any tags defined in the BagItProfile but not in the specification.
* @return array<string, string> Array of tagName => tagValue
*/
public function getOtherTagOptions(): array
{
return $this->otherOptions;
}

/**
* Set the other tag options.
* @param array $tagOptions Array of optionName => optionValue
*/
protected function setOtherTagOptions(array $tagOptions): void
{
$this->otherOptions = $tagOptions;
}

/**
* Create a ProfileTags object from a JSON array.
* @param string $tag Tag name
* @param array<string, string> $tagOpts Tag options
* @return ProfileTags The created object.
*/
public static function fromJson(string $tag, array $tagOpts): ProfileTags
{
return new ProfileTags(
$profileTag = new ProfileTags(
$tag,
$tagOpts['required'] ?? false,
$tagOpts['values'] ?? [],
$tagOpts['repeatable'] ?? true,
$tagOpts['description'] ?? ""
);
$otherTags = array_diff_key($tagOpts, self::SPEC_TAGS);
if (count($otherTags) > 0) {
$profileTag->setOtherTagOptions($otherTags);
}
return $profileTag;
}
}
100 changes: 96 additions & 4 deletions tests/Profiles/BagProfileTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public function testValidateBag1(): void
* @group Profiles
* @covers ::setBagInfoTags
*/
public function testInvalidBagInfoTags(): void
public function testOptionalBagInfoTags(): void
{
$profileJson = <<< JSON
{
Expand Down Expand Up @@ -65,9 +65,21 @@ public function testInvalidBagInfoTags(): void
]
}
JSON;
$this->expectException(ProfileException::class);
$this->expectExceptionMessage("Invalid tag options for Source-Organization");
BagItProfile::fromJson($profileJson);
$profile = BagItProfile::fromJson($profileJson);
$this->assertTrue($profile->isValid());
$this->assertArrayEquals(["source-organization"], array_keys($profile->getBagInfoTags()));
$tag = $profile->getBagInfoTags()["source-organization"];
$this->assertEquals("Source-Organization", $tag->getTag());
$this->assertTrue($tag->isRequired());
$this->assertArrayEquals(["Simon Fraser University", "York University"], $tag->getValues());
$this->assertEquals("", $tag->getDescription());
$this->assertTrue($tag->isRepeatable());
$this->assertArrayEquals(
[
"help" => "This is the organization that originally created the bag."
],
$tag->getOtherTagOptions()
);
}

/**
Expand Down Expand Up @@ -486,4 +498,84 @@ public function testAddSameProfileTwice(): void
$bag->removeBagProfile("http://www.library.yale.edu/mssa/bagitprofiles/disk_images.json");
$this->assertCount(0, $bag->getBagProfiles());
}

/**
* @group Profiles
* @covers \whikloj\BagItTools\Bag::addBagProfileByJson
* @covers \whikloj\BagItTools\Bag::addBagProfileInternal
* @covers \whikloj\BagItTools\Bag::removeBagProfile
*/
public function testAddDifferentProfiles(): void
{
$profile1 = file_get_contents(self::$profiles . "/bagProfileFoo.json");
$profile2 = file_get_contents(self::$profiles . "/bagProfileBar.json");
$profile3 = file_get_contents(self::$profiles . "/btrProfile.json");
$bag = Bag::create($this->tmpdir);
$this->assertCount(0, $bag->getBagProfiles());
$bag->addBagProfileByJson($profile1);
$this->assertCount(1, $bag->getBagProfiles());
$bag->addBagProfileByJson($profile2);
$this->assertCount(2, $bag->getBagProfiles());
$bag->addBagProfileByJson($profile3);
$this->assertCount(3, $bag->getBagProfiles());
// Add profile a second time has no effect.
$bag->addBagProfileByJson($profile2);
$this->assertCount(3, $bag->getBagProfiles());
$this->assertArrayEquals(
[
"http://canadiana.org/standards/bagit/tdr_ingest.json",
"https://github.com/dpscollaborative/btr_bagit_profile/releases/download/1.0/btr-bagit-profile.json",
"http://www.library.yale.edu/mssa/bagitprofiles/disk_images.json",
],
array_keys($bag->getBagProfiles())
);
// Remove profiles.
$bag->removeBagProfile("http://canadiana.org/standards/bagit/tdr_ingest.json");
$this->assertCount(2, $bag->getBagProfiles());
$bag->removeBagProfile(
"https://github.com/dpscollaborative/btr_bagit_profile/releases/download/1.0/btr-bagit-profile.json"
);
$this->assertCount(1, $bag->getBagProfiles());
// Remove profile that doesn't exist in bag has no effect
$bag->removeBagProfile("http://canadiana.org/standards/bagit/tdr_ingest.json");
$this->assertCount(1, $bag->getBagProfiles());
$bag->removeBagProfile("http://www.library.yale.edu/mssa/bagitprofiles/disk_images.json");
$this->assertCount(0, $bag->getBagProfiles());
}

/**
* @group Profiles
* @covers \whikloj\BagItTools\Bag::clearAllProfiles
*/
public function testClearAllProfiles(): void
{
$profile1 = file_get_contents(self::$profiles . "/bagProfileFoo.json");
$profile2 = file_get_contents(self::$profiles . "/bagProfileBar.json");
$profile3 = file_get_contents(self::$profiles . "/btrProfile.json");
$bag = Bag::create($this->tmpdir);
$this->assertCount(0, $bag->getBagProfiles());
$bag->addBagProfileByJson($profile1);
$bag->addBagProfileByJson($profile2);
$bag->addBagProfileByJson($profile3);
$this->assertCount(3, $bag->getBagProfiles());
$bag->clearAllProfiles();
$this->assertCount(0, $bag->getBagProfiles());
}

/**
* @group Profiles
* @covers \whikloj\BagItTools\Bag::getBagProfiles
*/
public function testGetBagProfile(): void
{
$profile = file_get_contents(self::$profiles . "/bagProfileBar.json");
$bag = Bag::create($this->tmpdir);
$bag->addBagProfileByJson($profile);
$testProfiles = $bag->getBagProfiles();
$this->assertCount(1, $testProfiles);
$key = key($testProfiles);
$val = current($testProfiles);
$this->assertEquals("http://canadiana.org/standards/bagit/tdr_ingest.json", $key);
$this->assertInstanceOf(BagItProfile::class, $val);
}
}

0 comments on commit e6906c5

Please sign in to comment.