diff --git a/src/Mods/Reader/AbstractReader.php b/src/Mods/Reader/AbstractReader.php index db4a034..bbdd053 100644 --- a/src/Mods/Reader/AbstractReader.php +++ b/src/Mods/Reader/AbstractReader.php @@ -14,6 +14,7 @@ use Slub\Mods\Element\AbstractElement; use Slub\Mods\Element\Xml\Element; +use Slub\Mods\Utility\Query; /** * Trait for reading Abstract element @@ -40,4 +41,26 @@ public function getAbstract(string $query = ''): ?AbstractElement } return null; } + + /** + * Get the value of the element by given parameters. + * @see https://www.loc.gov/standards/mods/userguide/abstract.html + * + * @access public + * + * @param string $query The XPath query for metadata search + * @param array $attributes The array of attributes ['attribute' => 'value'] + * @param string $value The value for metadata search + * + * @return ?AbstractElement + */ + public function getAbstractByParameters(string $query = '', array $attributes = [], string $value = ''): ?AbstractElement + { + $query = new Query('./mods:abstract', $query, $attributes, $value); + $element = new Element($this->xml, $query->getXPath()); + if ($element->exists()) { + return new AbstractElement($element->getValues()[0]); + } + return null; + } } diff --git a/src/Mods/Reader/AccessConditionReader.php b/src/Mods/Reader/AccessConditionReader.php index df74a57..f55db54 100644 --- a/src/Mods/Reader/AccessConditionReader.php +++ b/src/Mods/Reader/AccessConditionReader.php @@ -13,6 +13,7 @@ namespace Slub\Mods\Reader; use Slub\Mods\Element\AccessCondition; +use Slub\Mods\Utility\Query; /** * Trait for reading AccessCondition element @@ -40,6 +41,29 @@ public function getAccessConditions(string $query = ''): array return $accessConditions; } + /** + * Get the the array of the elements by given parameters. + * @see https://www.loc.gov/standards/mods/userguide/accesscondition.html + * + * @access public + * + * @param string $query The XPath query for metadata search + * @param array $attributes The array of attributes ['attribute' => 'value'] + * @param string $value The value for metadata search + * + * @return AccessCondition[] + */ + public function getAccessConditionsByParameters(string $query = '', array $attributes = [], string $value = ''): array + { + $accessConditions = []; + $query = new Query('./mods:accessCondition', $query, $attributes, $value); + $values = $this->getValues($query->getXPath()); + foreach ($values as $value) { + $accessConditions[] = new AccessCondition($value); + } + return $accessConditions; + } + /** * Get the matching element. * @see https://www.loc.gov/standards/mods/userguide/accesscondition.html diff --git a/src/Mods/Reader/PhysicalDescriptionReader.php b/src/Mods/Reader/PhysicalDescriptionReader.php index 978526b..5120fa2 100644 --- a/src/Mods/Reader/PhysicalDescriptionReader.php +++ b/src/Mods/Reader/PhysicalDescriptionReader.php @@ -13,6 +13,7 @@ namespace Slub\Mods\Reader; use Slub\Mods\Element\PhysicalDescription; +use Slub\Mods\Utility\Query; /** * Trait for reading PhysicalDescription element @@ -40,6 +41,29 @@ public function getPhysicalDescriptions(string $query = ''): array return $physicalDescriptions; } + /** + * Get the the array of the elements by given parameters. + * @see https://www.loc.gov/standards/mods/userguide/physicaldescription.html + * + * @access public + * + * @param string $query The XPath query for metadata search + * @param array $attributes The array of attributes ['attribute' => 'value'] + * @param string $value The value for metadata search + * + * @return PhysicalDescription[] + */ + public function getPhysicalDescriptionsByParameters(string $query = '', array $attributes = [], string $value = ''): array + { + $physicalDescriptions = []; + $query = new Query('./mods:physicalDescription', $query, $attributes, $value); + $values = $this->getValues($query->getXPath()); + foreach ($values as $value) { + $physicalDescriptions[] = new PhysicalDescription($value); + } + return $physicalDescriptions; + } + /** * Get the matching element. * @see https://www.loc.gov/standards/mods/userguide/physicaldescription.html diff --git a/src/Mods/Utility/Query.php b/src/Mods/Utility/Query.php new file mode 100644 index 0000000..fe186ca --- /dev/null +++ b/src/Mods/Utility/Query.php @@ -0,0 +1,88 @@ + 'value'] + * @param string $value The value for metadata search + * + * @return void + */ + public function __construct(string $xpath, string $query = '', array $attributes = [], string $value = '') + { + $parsedAttributes = !empty($attributes) ? $this->getParsedAttributes($attributes) : ''; + + if (!empty($query) && !empty($parsedAttributes)) { + $xpath .= !empty($value) ? '[' . $query . '[' . $parsedAttributes . ']="' . $value . '"]' : '[' . $query . '[' . $parsedAttributes . ']]'; + } else if (!empty($query) || !empty($parsedAttributes)) { + $inner = !empty($query) ? $query : $parsedAttributes; + $xpath .= !empty($value) ? '[' . $inner . ']="' . $value . '"' : '[' . $inner . ']'; + } else if (!empty($value)) { + $xpath .= '="' . $value . '"'; + } + + $this->xPath = $xpath; + } + + public function getXPath(): string + { + return $this->xPath; + } + + private function getParsedAttributes(array $attributes): string + { + $parsedAttributes = ''; + + $amountAttributes = count($attributes); + + if ($amountAttributes == 1) { + foreach ($attributes as $key => $value) { + $parsedAttributes .= '@' . $key . '="' . $value . '"'; + } + + return $parsedAttributes; + } + + $index = 0; + $lastIndex = $amountAttributes - 1; + + foreach ($attributes as $key => $value) { + $parsedAttributes .= '@' . $key . '="' . $value . '"'; + if ($index < $lastIndex) { + $parsedAttributes .= ' AND '; + } + $index++; + } + + return $parsedAttributes; + } +} diff --git a/tests/Mods/Reader/PhysicalDescriptionReaderTest.php b/tests/Mods/Reader/PhysicalDescriptionReaderTest.php index 03ccc31..8828825 100644 --- a/tests/Mods/Reader/PhysicalDescriptionReaderTest.php +++ b/tests/Mods/Reader/PhysicalDescriptionReaderTest.php @@ -59,6 +59,17 @@ public function getLastPhysicalDescriptionForBookDocument() self::assertPhysicalDescriptionForBookDocument($physicalDescription); } + /** + * @test + */ + public function gtPhysicalDescriptionsByParametersForBookDocument() + { + $physicalDescriptions = $this->bookReader->getPhysicalDescriptionsByParameters('./mods:form', ['authority' => 'marcform'], 'print'); + self::assertNotEmpty($physicalDescriptions); + self::assertEquals(1, count($physicalDescriptions)); + self::assertPhysicalDescriptionForBookDocument($physicalDescriptions[0]); + } + /** * @test */ diff --git a/tests/Mods/Utility/QueryTest.php b/tests/Mods/Utility/QueryTest.php new file mode 100644 index 0000000..19f928c --- /dev/null +++ b/tests/Mods/Utility/QueryTest.php @@ -0,0 +1,91 @@ + [ + 'query' => 'div', + 'attributes' => ['class' => 'test'], + 'value' => 'active', + 'expectedSuffix' => '[div[@class="test"]="active"]' + ], + 'No query, attributes and value present' => [ + 'query' => '', + 'attributes' => ['class' => 'test'], + 'value' => 'active', + 'expectedSuffix' => '[@class="test"]="active"' + ], + 'Only value present' => [ + 'query' => '', + 'attributes' => [], + 'value' => 'active', + 'expectedSuffix' => '="active"' + ], + 'Only attributes present' => [ + 'query' => '', + 'attributes' => ['class' => 'test'], + 'value' => '', + 'expectedSuffix' => '[@class="test"]' + ], + 'Only query present' => [ + 'query' => 'div', + 'attributes' => [], + 'value' => '', + 'expectedSuffix' => '[div]' + ], + 'Query and value present, no attributes' => [ + 'query' => 'div', + 'attributes' => [], + 'value' => 'active', + 'expectedSuffix' => '[div]="active"' + ], + 'Query and attributes present, no value' => [ + 'query' => 'div', + 'attributes' => ['class' => 'test'], + 'value' => '', + 'expectedSuffix' => '[div[@class="test"]]' + ], + 'All optional parameters empty' => [ + 'query' => '', + 'attributes' => [], + 'value' => '', + 'expectedSuffix' => '' + ], + 'Multiple attributes present with query and value' => [ + 'query' => 'div', + 'attributes' => ['class' => 'test', 'id' => 'main'], + 'value' => 'visible', + 'expectedSuffix' => '[div[@class="test" AND @id="main"]="visible"]' + ] + ]; + + /** + * @test + */ + public function testConstructorAppendsCorrectXpath() + { + $initialXPath = '/initial/xpath'; + + foreach (self::$testData as $testMessage => $testData) { + $resultQuery = new Query($initialXPath, $testData['query'], $testData['attributes'], $testData['value']); + self::assertSame($initialXPath . $testData['expectedSuffix'], $resultQuery->getXpath(), $testMessage); + } + } +}