diff --git a/.gitattributes b/.gitattributes index 2ce318721fb163b54aad36a037e6c0ae93070027..452a19c604e49efdbb6966a16b3c9d80584687bb 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1762,6 +1762,7 @@ library/Class/WebService/Lastfm.php -text library/Class/WebService/LibraryThing.php -text library/Class/WebService/MappedSoapClient.php -text library/Class/WebService/OAI.php -text +library/Class/WebService/OAI/CatalogueVisitor.php -text library/Class/WebService/OAI/Response/Identify.php -text library/Class/WebService/OAI/Response/ListSets.php -text library/Class/WebService/OAI/Response/Null.php -text @@ -1821,6 +1822,7 @@ library/Class/WebService/Vignette.php -text library/Class/WebService/XMLParser.php -text library/Class/Xml.php -text library/Class/Xml/Builder.php -text +library/Class/Xml/Oai/DublinCoreBuilder.php -text library/Class/Zone.php -text library/Thumbs/GdThumb.inc.php -text library/Thumbs/PhpThumb.inc.php -text @@ -3369,6 +3371,7 @@ scripts/insert_licence.sh -text scripts/opac2.sql -text /startup.php -text tests/.htaccess -text +tests/TestXPathFactory.php -text tests/application/modules/AbstractControllerTestCase.php -text tests/application/modules/admin/controllers/AccueilControllerTest.php -text tests/application/modules/admin/controllers/AdminAbstractControllerTestCase.php -text @@ -3486,6 +3489,7 @@ tests/library/Class/UsersTest.php -text tests/library/Class/VodeclicLinkTest.php -text tests/library/Class/WebService/BabelioTest.php -text tests/library/Class/WebService/OAI/Response/IdentifyTest.php -text +tests/library/Class/WebService/OAI/Response/ListSetsTest.php -text tests/library/Class/WebService/OAIIdentify.xml -text tests/library/Class/WebService/OAIListIdentifiers.xml -text tests/library/Class/WebService/OAIListRecords.xml -text diff --git a/library/Class/Catalogue.php b/library/Class/Catalogue.php index 933b9568f0e28e3914b8c2ac0e99874d5d6e5c87..c3d3a01f642d4ee46736c5ffae9a70311bbcfbc4 100644 --- a/library/Class/Catalogue.php +++ b/library/Class/Catalogue.php @@ -22,8 +22,27 @@ // OPAC3 - Catalogues de notices //////////////////////////////////////////////////////////////////////////////// -class Class_Catalogue +class Class_Catalogue extends Storm_Model_Abstract { + protected $_table_name = 'catalogue'; + protected $_table_primary = 'ID_CATALOGUE'; + + protected $_default_attribute_values = array('oai_spec' => '', + 'description' => ''); + + public static function getLoader() { + return self::getLoaderFor(__CLASS__); + } + + + public function acceptVisitor($visitor) { + $visitor->visitOaiSpec($this->getOaiSpec()); + $visitor->visitLibelle($this->getLibelle()); + if ($this->hasDescription()) + $visitor->visitDescription($this->getDescription()); + } + + //------------------------------------------------------------------------------ // Rend les notices et les stats (test d'un catalogue) //------------------------------------------------------------------------------ diff --git a/library/Class/Notice/DublinCoreVisitor.php b/library/Class/Notice/DublinCoreVisitor.php index bf5fb6be97acad158c0299d1a9b1f7b5e3039636..deeb9a02610fbeca84c9607b5f1d3123318ed5ba 100644 --- a/library/Class/Notice/DublinCoreVisitor.php +++ b/library/Class/Notice/DublinCoreVisitor.php @@ -21,38 +21,33 @@ class Class_Notice_DublinCoreVisitor { protected $_xml; + protected $_builder; - public function visit($notice) { - $this->_xml = '<oai_dc:dc xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:oai_dc="http://www.openarchives.org/OAI/2.0/oai_dc/">'; + public function __construct() { + $this->_builder = new Class_Xml_Oai_DublinCoreBuilder(); + } + + public function visit($notice) { $notice->acceptVisitor($this); - $this->_xml .= '</oai_dc:dc>'; - } public function xml() { - return $this->_xml; + return $this->_builder->oai_dc($this->_xml); } public function visitClefAlpha($clef) { - $this->addTag('identifier', sprintf('http://%s%s/recherche/notice/%s', - $_SERVER['SERVER_NAME'], - BASE_URL, - $clef)); + $this->_xml .= $this->_builder->identifier(sprintf('http://%s%s/recherche/notice/%s', + $_SERVER['SERVER_NAME'], + BASE_URL, + $clef)); } public function visitTitre($titre) { - $this->addTag('title', $titre); - } - - - public function addTag($tag, $content) { - $this->_xml .= sprintf('<dc:%1$s>%2$s</dc:%1$s>', - $tag, $content); + $this->_xml .= $this->_builder->title($titre); } } diff --git a/library/Class/WebService/OAI/CatalogueVisitor.php b/library/Class/WebService/OAI/CatalogueVisitor.php new file mode 100644 index 0000000000000000000000000000000000000000..65b772ddb5c360c8516906d62bd250e5ee1cc3e6 --- /dev/null +++ b/library/Class/WebService/OAI/CatalogueVisitor.php @@ -0,0 +1,60 @@ +<?php +/** + * Copyright (c) 2012, Agence Française Informatique (AFI). All rights reserved. + * + * AFI-OPAC 2.0 is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * AFI-OPAC 2.0 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with AFI-OPAC 2.0; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +class Class_WebService_OAI_CatalogueVisitor { + protected $_xml; + protected $_xmlBuilder; + + public function __construct($builder) { + $this->_xmlBuilder = $builder; + } + + + public function xml() { + return $this->_xml; + } + + + public function visitCatalogue($catalogue) { + $this->_xml = ''; + $catalogue->acceptVisitor($this); + return $this; + } + + + public function visitOaiSpec($oai_spec) { + $this->_xml .= $this->_xmlBuilder->setSpec($oai_spec); + } + + + public function visitLibelle($libelle) { + $this->_xml .= $this->_xmlBuilder->setName($libelle); + } + + + public function visitDescription($description) { + $dcBuilder = new Class_Xml_Oai_DublinCoreBuilder(); + $dcDescription = $dcBuilder->oai_dc($dcBuilder->description($description)); + $this->_xml .= $this->_xmlBuilder->setDescription($dcDescription); + } +} + +?> \ No newline at end of file diff --git a/library/Class/WebService/OAI/Response/ListSets.php b/library/Class/WebService/OAI/Response/ListSets.php index 59b66ce041d7a56614af97ee8636bd40eb9b26ce..76bc58f5b7da9db02715c8a1a5fa1859a5a1eb6d 100644 --- a/library/Class/WebService/OAI/Response/ListSets.php +++ b/library/Class/WebService/OAI/Response/ListSets.php @@ -21,10 +21,38 @@ class Class_WebService_OAI_Response_ListSets extends Class_WebService_OAI_Response_Null { + protected $_xmlBuilder; + protected $_catalogue_visitor; + public function buildXmlOn($builder) { + $this->_xmlBuilder = $builder; + $this->_catalog_visitor = new Class_WebService_OAI_CatalogueVisitor($this->_xmlBuilder); + return - $builder->request(array('verb' => 'ListSets'), - $this->_baseUrl); + $this->_xmlBuilder->request(array('verb' => 'ListSets'), + $this->_baseUrl) + . $this->_buildSets(); + } + + + protected function _buildSets() { + $catalogs = Class_Catalogue::getLoader() + ->findAllBy(array('where' => 'oai_spec is not null', + 'where' => 'oai_spec !=\'\'', + 'order' => 'oai_spec')); + + + $sets = ''; + foreach ($catalogs as $catalog) + $sets .= $this->xmlForCatalogue($catalog); + + return $this->_xmlBuilder->ListSets($sets); + } + + + protected function xmlForCatalogue($catalog) { + $this->_catalog_visitor->visitCatalogue($catalog); + return $this->_xmlBuilder->set($this->_catalog_visitor->xml()); } } diff --git a/library/Class/WebService/OAI/Response/Null.php b/library/Class/WebService/OAI/Response/Null.php index e02ee83b29a979d49b58552ff90aafcc64983467..fff17ca425e0b5058070a7fe6bb732251ce43ed8 100644 --- a/library/Class/WebService/OAI/Response/Null.php +++ b/library/Class/WebService/OAI/Response/Null.php @@ -38,6 +38,7 @@ class Class_WebService_OAI_Response_Null { $this->buildXmlOn($builder)); } + public function buildXmlOn($builder) { return $builder->error(array('code' => 'badVerb'), 'Illegal OAI verb'); } diff --git a/library/Class/Xml/Builder.php b/library/Class/Xml/Builder.php index 850911822b59d264d43bebea6c38497753ea21d7..b8919dd3bb979a463007d6312d1bd2c842405248 100644 --- a/library/Class/Xml/Builder.php +++ b/library/Class/Xml/Builder.php @@ -30,11 +30,7 @@ class Class_Xml_Builder { public function _tag($tag, $content) { if (!is_array($tag)) return $this->_xmlString((string)$tag, $content); - - $attributes = ''; - foreach (current($tag) as $k => $v) - $attributes .= ' ' . $k . '="' . $v . '"'; - + $attributes = $this->attributesToString(current($tag)); return $this->_xmlString(key($tag), $content, $attributes); } @@ -42,6 +38,14 @@ class Class_Xml_Builder { public function _xmlString($name, $content, $attributes = '') { return '<'.$name.$attributes.'>'.$content.'</'.$name.'>'; } + + + public function attributesToString($attributes) { + $attribs = ''; + foreach ($attributes as $k => $v) + $attribs .= ' ' . $k . '="' . $v . '"'; + return $attribs; + } } ?> \ No newline at end of file diff --git a/library/Class/Xml/Oai/DublinCoreBuilder.php b/library/Class/Xml/Oai/DublinCoreBuilder.php new file mode 100644 index 0000000000000000000000000000000000000000..0665eacba5b57c5b5605bc6dc4ae9ff5eed20bc4 --- /dev/null +++ b/library/Class/Xml/Oai/DublinCoreBuilder.php @@ -0,0 +1,35 @@ +<?php +/** + * Copyright (c) 2012, Agence Française Informatique (AFI). All rights reserved. + * + * AFI-OPAC 2.0 is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * AFI-OPAC 2.0 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with AFI-OPAC 2.0; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +class Class_Xml_Oai_DublinCoreBuilder extends Class_Xml_Builder { + public function oai_dc($content) { + return parent::_xmlString('oai_dc:dc', + $content, + $this->attributesToString(array('xmlns:oai_dc' => 'http://www.openarchives.org/OAI/2.0/oai_dc/', + 'xmlns:dc' => 'http://purl.org/dc/elements/1.1'))); + } + + + public function _xmlString($name, $content, $attributes = '') { + return parent::_xmlString('dc:' . $name, $content, $attributes); + } +} +?> \ No newline at end of file diff --git a/tests/TestXPathFactory.php b/tests/TestXPathFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..eed8061d6cc76bc887e39c9d9be8728ce0a05712 --- /dev/null +++ b/tests/TestXPathFactory.php @@ -0,0 +1,30 @@ +<?php +/** + * Copyright (c) 2012, Agence Française Informatique (AFI). All rights reserved. + * + * AFI-OPAC 2.0 is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * AFI-OPAC 2.0 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with AFI-OPAC 2.0; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +class TestXPathFactory { + public static function newOai() { + $xpath = new Storm_Test_XPathXML(); + $xpath->registerNameSpace('oai', 'http://www.openarchives.org/OAI/2.0/'); + return $xpath; + } + +} +?> \ No newline at end of file diff --git a/tests/application/modules/opac/controllers/OaiControllerTest.php b/tests/application/modules/opac/controllers/OaiControllerTest.php index fe4d83be6820263550f07a4608b9681b74510562..5407c1449a6b51cc639568181c4744ac7ca1b988 100644 --- a/tests/application/modules/opac/controllers/OaiControllerTest.php +++ b/tests/application/modules/opac/controllers/OaiControllerTest.php @@ -82,6 +82,13 @@ class OaiControllerListSetsRequestTest extends OaiControllerRequestTestCase { public function setUp() { parent::setUp(); + Storm_Test_ObjectWrapper::onLoaderOfModel('Class_Catalogue') + ->whenCalled('findAllBy') + ->with(array('where' => 'oai_spec is not null', + 'where' => 'oai_spec !=\'\'', + 'order' => 'oai_spec')) + ->answers(array()); + $this->dispatch('/opac/oai/request?verb=ListSets'); } diff --git a/tests/library/Class/WebService/OAI/Response/ListSetsTest.php b/tests/library/Class/WebService/OAI/Response/ListSetsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..00f4cc5f904904a195ffd1ecb7a4669e85602b38 --- /dev/null +++ b/tests/library/Class/WebService/OAI/Response/ListSetsTest.php @@ -0,0 +1,99 @@ +<?php +/** + * Copyright (c) 2012, Agence Française Informatique (AFI). All rights reserved. + * + * AFI-OPAC 2.0 is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * AFI-OPAC 2.0 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with AFI-OPAC 2.0; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +class ListSetsTest extends Storm_Test_ModelTestCase { + protected $_response; + protected $_xpath; + + public function setUp() { + parent::setUp(); + + $this->_xpath = TestXPathFactory::newOai(); + + $catalogue_bd = Class_Catalogue::getLoader()->newInstanceWithId(1) + ->setLibelle('BDs') + ->setOaiSpec('livres:bd'); + $catalogue_musique = Class_Catalogue::getLoader()->newInstanceWithId(2) + ->setLibelle('Musique') + ->setDescription('La musique qui balance') + ->setOaiSpec('music'); + + Storm_Test_ObjectWrapper::onLoaderOfModel('Class_Catalogue') + ->whenCalled('findAllBy') + ->with(array('where' => 'oai_spec is not null', + 'where' => 'oai_spec !=\'\'', + 'order' => 'oai_spec')) + ->answers(array($catalogue_bd, $catalogue_musique)); + + + $this->_response = new Class_WebService_OAI_Response_ListSets('http://afi.fr/oai'); + } + + + /** @test */ + public function setMusiqueShouldContainSpecMusic() { + $this->_xpath->assertXpathContentContains($this->_response->xml(), + '//oai:ListSets/oai:set/oai:setSpec', + 'music'); + } + + + /** @test */ + public function setMusiqueShouldContainNameMusique() { + $this->_xpath->assertXpathContentContains($this->_response->xml(), + '//oai:ListSets/oai:set/oai:setName', + 'Musique'); + } + + + /** @test */ + public function setMusiqueShouldContainDescriptionLaMusiqueQuiBalance() { + $this->_xpath->assertXpathContentContains($this->_response->xml(), + '//oai:ListSets/oai:set/oai:setDescription', + 'La musique qui balance'); + } + + + + /** @test */ + public function setBdsShouldContainsSpecLivresColonBds() { + $this->_xpath->assertXpathContentContains($this->_response->xml(), + '//oai:ListSets/oai:set/oai:setSpec', + 'livres:bd'); + } + + + /** @test */ + public function setBdsShouldContainsNameBds() { + $this->_xpath->assertXpathContentContains($this->_response->xml(), + '//oai:ListSets/oai:set/oai:setName', + 'BDs'); + } + + + /** @test */ + public function setBdsShouldNotContainDescription() { + $this->_xpath->assertNotXpath($this->_response->xml(), + '//oai:ListSets/oai:set/oai:setSpec[text()="livres:bd"][following-sibling::oai:setDescription]'); + } + +} +?> \ No newline at end of file