From 395add404275b5be68afbe325c0b6c0a8bb005c7 Mon Sep 17 00:00:00 2001
From: pbarroca <pbarroca@afi-sa.fr>
Date: Wed, 11 Mar 2015 17:56:07 +0100
Subject: [PATCH] rel #16499 : SIGB services can provide pickup locations

---
 .../opac/controllers/RechercheController.php  |  78 +++++++++---
 .../Class/WebService/SIGB/AbstractService.php |  12 +-
 .../Carthame/ReserveInfoResponseReader.php    |   7 +-
 .../WebService/SIGB/Carthame/Service.php      |  35 ++++-
 .../Class/WebService/SIGB/CarthameTest.php    | 120 ++++++++++++++++--
 5 files changed, 220 insertions(+), 32 deletions(-)

diff --git a/application/modules/opac/controllers/RechercheController.php b/application/modules/opac/controllers/RechercheController.php
index ac0dfc2a363..837b4dcee2e 100644
--- a/application/modules/opac/controllers/RechercheController.php
+++ b/application/modules/opac/controllers/RechercheController.php
@@ -541,14 +541,14 @@ class RechercheController extends ZendAfi_Controller_Action {
 		$viewRenderer = $this->getHelper('ViewRenderer');
 		$viewRenderer->setNoRender();
 
-		if (!$user = Class_Users::getLoader()->getIdentity()) {
+		if (!$user = Class_Users::getIdentity()) {
 		  $this->_forward('popup-login', 'auth', 'opac', ['redirect' => $this->view->url()]);
 			return;
 		}
 
-		$id_bib = (int)$this->_request->getParam('id_bib');
-		$id_origine = $this->_request->getParam('id_origine');
-		$code_annexe = $this->_request->getParam('code_annexe');
+		$id_bib = (int)$this->_getParam('id_bib');
+		$id_origine = $this->_getParam('id_origine');
+		$code_annexe = $this->_getParam('code_annexe');
 
 		$comm = new Class_CommSigb();
 		$ret = $comm->reserverExemplaire($id_bib, $id_origine, $code_annexe);
@@ -598,40 +598,78 @@ class RechercheController extends ZendAfi_Controller_Action {
 
 
 	public function reservationPickupAjaxAction() {
-		if (!Class_CosmoVar::isSiteRetraitResaEnabled()) {
-			$this->_forward('reservationajax');
+		if (!$user = Class_Users::getIdentity()) {
+		  $this->_forward('popup-login', 'auth', 'opac', ['redirect' => $this->view->url()]);
 			return;
 		}
 
 
-		if ($this->_request->isPost()) {
-			$this->renderPopup($this->view->url(['action' => 'reservationajax',
-																					 'code_annexe' => $this->_request->getPost('code_annexe')]));
+		if (!Class_CosmoVar::isSiteRetraitResaEnabled()
+				&& !$this->arePickupLocationsProvidedByComm()) {
+			$this->_forward('reservationajax');
 			return;
 		}
 
 
-		$annexes = Class_CodifAnnexe::findAllByPickup();
+		$form = $this->view
+			->newForm(['id' => 'pickup',
+								 'class' => 'zend_form reservation_pickup',
+								 'action' => $this->view->url(['controller' => 'recherche',
+																							 'action' => 'reservation-pickup-ajax'])])
+			->addElement('Radio', 'code_annexe', ['required' => true,
+																						'allowEmpty' => false])
+
+			->addDisplayGroup(['code_annexe'], 'group', ['legend' => 'Site de retrait'])
 
-		$form = $this->view->newForm(['id' => 'pickup',
-																	'class' => 'zend_form reservation_pickup',
-																	'action' => $this->view->url(['controller' => 'recherche', 'action' => 'reservation-pickup-ajax'])])
-			->addElement('Radio', 'code_annexe', array('required' => true,
-																								 'allowEmpty' => false))
-			->addDisplayGroup(array('code_annexe'), 'group', array('legend' => 'Site de retrait'))
 			->addElement('Submit', 'Valider')
-			->addElement('Button', 'Annuler', array('onclick' => 'opacDialogClose();return false;'));
+			->addElement('Button', 'Annuler',
+									 ['onclick' => 'opacDialogClose();return false;']);
 
 		$radio = $form->getElement('code_annexe');
-		foreach ($annexes as $annexe)
-			$radio->addMultiOption($annexe->getCode(), $annexe->getLibelle());
-		$radio->setValue($this->_getParam('code_annexe'));
+		$this->arePickupLocationsProvidedByComm() ?
+			$this->_addLocationsFromCommTo($radio) :
+			$this->_addLocationsFromCodifTo($radio);
+
+		if ($this->_request->isPost()
+				&& $form->isValid($this->_request->getPost())) {
+			$this->renderPopup($this->view->url(['action' => 'reservationajax',
+																					 'code_annexe' => $this->_request->getPost('code_annexe')]));
+			return;
+		}
 
 		$this->renderPopupResult($this->view->_('Lieu de mise à disposition demandé'),
 														 $this->view->renderForm($form));
 	}
 
 
+	protected function _addLocationsFromCodifTo($element) {
+		foreach (Class_CodifAnnexe::findAllByPickup() as $annexe)
+			$element->addMultiOption($annexe->getCode(), $annexe->getLibelle());
+		$element->setValue($this->_getParam('code_annexe'));
+	}
+
+
+	protected function _addLocationsFromCommTo($element) {
+		if ((!$user = Class_Users::getIdentity())
+				|| (!$comm = $user->getSIGBComm())
+				|| (!$item = Class_Exemplaire::find($this->_getParam('id_origine'))))
+			return;
+
+		foreach($comm->pickupLocationsFor($user, $item) as $k => $v)
+			$element->addMultiOption($k, $v);
+	}
+
+
+	protected function arePickupLocationsProvidedByComm() {
+		if ((!$user = Class_Users::getIdentity())
+				|| (!Class_Exemplaire::find($this->_getParam('id_origine'))))
+			return false;
+
+		return ($comm = $user->getSIGBComm()) ?
+			$comm->providesPickupLocations() : false;
+	}
+
+
 	public function setMoteurRecherche($moteur) {
 		$this->moteur = $moteur;
 	}
diff --git a/library/Class/WebService/SIGB/AbstractService.php b/library/Class/WebService/SIGB/AbstractService.php
index 1c8bf744c80..3a34374ea0f 100644
--- a/library/Class/WebService/SIGB/AbstractService.php
+++ b/library/Class/WebService/SIGB/AbstractService.php
@@ -105,6 +105,16 @@ abstract class Class_WebService_SIGB_AbstractService {
 	}
 
 
+	public function providesPickupLocations() {
+		return false;
+	}
+
+
+	public function pickupLocationsFor($user, $item) {
+		return [];
+	}
+
+
 	protected function _success() {
     return array('statut' => true, 'erreur' => '');
 	}
@@ -112,7 +122,7 @@ abstract class Class_WebService_SIGB_AbstractService {
 
 	protected function _error($message) {
 		return array('statut' => false,
-								  'erreur' => $message);
+								 'erreur' => $message);
 	}
 
 
diff --git a/library/Class/WebService/SIGB/Carthame/ReserveInfoResponseReader.php b/library/Class/WebService/SIGB/Carthame/ReserveInfoResponseReader.php
index 356ecd3cc8d..9df17205e91 100644
--- a/library/Class/WebService/SIGB/Carthame/ReserveInfoResponseReader.php
+++ b/library/Class/WebService/SIGB/Carthame/ReserveInfoResponseReader.php
@@ -16,7 +16,7 @@
  *
  * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
  * along with BOKEH; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA 
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
 class Class_WebService_SIGB_Carthame_ReserveInfoResponseReader {
 	/** @var Class_WebService_XMLParser */
@@ -39,6 +39,11 @@ class Class_WebService_SIGB_Carthame_ReserveInfoResponseReader {
 	}
 
 
+	public static function read($xml) {
+		return (new self())->readXml($xml);
+	}
+
+
 	/**
 	 * @param string $xml
 	 * @return Class_WebService_SIGB_Emprunteur
diff --git a/library/Class/WebService/SIGB/Carthame/Service.php b/library/Class/WebService/SIGB/Carthame/Service.php
index 7b4dd917817..edd4c2ddfc5 100644
--- a/library/Class/WebService/SIGB/Carthame/Service.php
+++ b/library/Class/WebService/SIGB/Carthame/Service.php
@@ -20,10 +20,13 @@
  */
 
 class Class_WebService_SIGB_Carthame_Service extends Class_WebService_SIGB_AbstractRESTService {
+	const CARTHAME_NAME = 'ktm';
+	const KARVI_NAME = 'karvi';
+
 	protected $_key;
 	protected $_translate;
 	protected $_hold_error_messages;
-	protected $_sigb_field_name = "ktm";
+	protected $_sigb_field_name = self::CARTHAME_NAME;
 
 	/**
 	 * @param string $server_root
@@ -48,6 +51,34 @@ class Class_WebService_SIGB_Carthame_Service extends Class_WebService_SIGB_Abstr
 	}
 
 
+	public function providesPickupLocations() {
+		return $this->isKarvi();
+	}
+
+
+	public function isKarvi() {
+		return self::KARVI_NAME == $this->_sigb_field_name;
+	}
+
+
+	public function pickupLocationsFor($user, $item) {
+		if (!$this->isKarvi() || !$user || !$item)
+			return [];
+
+		$user_id = $this->_authenticate($user);
+		$record_id = $item->getIdOrigine();
+
+		$xml = $this->_callAction('reserveInfo',
+															['userid' => $user_id, 'nn' => $record_id]);
+
+		if (1 <= (int)$this->_getTagData($xml, 'error'))
+			return [];
+
+		return Class_WebService_SIGB_Carthame_ReserveInfoResponseReader::read($xml)
+			->getSites();
+	}
+
+
 	/**
 	 * @param $translate Zend_Translate
 	 * @return self
@@ -57,11 +88,13 @@ class Class_WebService_SIGB_Carthame_Service extends Class_WebService_SIGB_Abstr
 		return $this;
 	}
 
+
 	public function setSigbFieldName($sigb_field_name) {
 		$this->_sigb_field_name=$sigb_field_name;
 		return $this;
 	}
 
+
 	/**
 	 * @param Class_Users $user
 	 * @return Class_WebService_SIGB_Emprunteur
diff --git a/tests/library/Class/WebService/SIGB/CarthameTest.php b/tests/library/Class/WebService/SIGB/CarthameTest.php
index 3f2dc89cac4..71fd97df5eb 100644
--- a/tests/library/Class/WebService/SIGB/CarthameTest.php
+++ b/tests/library/Class/WebService/SIGB/CarthameTest.php
@@ -20,21 +20,28 @@
  */
 
 abstract class CarthameTestCase extends Storm_Test_ModelTestCase {
+	public function setUp() {
+		Storm_Model_Loader::defaultToVolatile();
+		parent::setUp();
+	}
+
+
 	public function tearDown() {
 		Class_WebService_SIGB_Carthame::reset();
+		Storm_Model_Loader::defaultToDb();
 		parent::tearDown();
 	}
-	public function setUp() {
-		parent::setUp();
-	}
 }
 
 
 class CarthameGetServiceTest extends CarthameTestCase {
 	protected $service;
+
 	public function setUp() {
 		parent::setUp();
-		$this->service = Class_WebService_SIGB_Carthame::getService(['url_serveur' => 'http://ifr.ro/webservices/index.php', 'key' => 'bibkey', 'sigb_field_name' => 'karvi']);
+		$this->service = Class_WebService_SIGB_Carthame::getService(['url_serveur' => 'http://ifr.ro/webservices/index.php',
+																																 'key' => 'bibkey',
+																																 'sigb_field_name' => 'karvi']);
 	}
 
 
@@ -46,16 +53,20 @@ class CarthameGetServiceTest extends CarthameTestCase {
 
 	/** @test */
 	public function serverRootShouldBeIfrDotEU() {
-		$this->assertEquals('http://ifr.ro/webservices/index.php', $this->service->getServerRoot());
+		$this->assertEquals('http://ifr.ro/webservices/index.php',
+												$this->service->getServerRoot());
 	}
 
 	/** @test */
 	public function getServiceWithoutSchemeShouldAddHttpScheme() {
 		$this->service = Class_WebService_SIGB_Carthame::getService(['url_serveur' => 'ifr.ro/webservices/index.php']);
-		$this->assertEquals('http://ifr.ro/webservices/index.php', $this->service->getServerRoot());
+		$this->assertEquals('http://ifr.ro/webservices/index.php',
+												$this->service->getServerRoot());
 	}
 }
 
+
+
 abstract class CarthameOperationTestCase extends CarthameTestCase {
 	protected $mock_web_client;
 	protected $service;
@@ -93,14 +104,32 @@ class CarthameKtmNoticeAlbatorTest extends CarthameTestCase {
 			->with('http://ifr.ro/webservices/index.php?sigb=ktm&version=standalone&idclient=bibkey&action=copyDetails&nn=I86355')
 			->answers(CarthameTestFixtures::createAnonymousNoticeXml());
 
-
-
-		$this->service = Class_WebService_SIGB_Carthame::getService(['url_serveur' => 'http://ifr.ro/webservices/index.php', 'key' => 'bibkey'])
+		$this->service = Class_WebService_SIGB_Carthame::getService(['url_serveur' => 'http://ifr.ro/webservices/index.php',
+																																 'key' => 'bibkey'])
 			->setWebClient($this->mock_web_client);
 
 		$this->albator = $this->service->getNotice('I86355');
 	}
 
+
+	/** @test */
+	public function shouldNotProvidePickupLocations() {
+		$this->assertFalse($this->service->providesPickupLocations());
+	}
+
+
+	/** @test */
+	public function pickupLocationsForUserAndItemShouldBeEmpty() {
+		$this->assertEmpty($this->service->pickupLocationsFor());
+	}
+
+
+	/** @test */
+	public function shouldNotBeKarvi() {
+		$this->assertFalse($this->service->isKarvi());
+	}
+
+
 	/** @test */
 	public function shouldAnswerOneNotice() {
 		$this->assertInstanceOf('Class_WebService_SIGB_Notice', $this->albator);
@@ -131,6 +160,7 @@ class CarthameKarviNoticeAlbatorTest extends CarthameOperationTestCase {
 		$this->albator = $this->service->getNotice('I86355');
 	}
 
+
 	/** @test */
 	public function shouldAnswerOneNotice() {
 		$this->assertInstanceOf('Class_WebService_SIGB_Notice', $this->albator);
@@ -146,6 +176,78 @@ class CarthameKarviNoticeAlbatorTest extends CarthameOperationTestCase {
 
 
 
+class CarthameKarviPickupLocationsTest extends CarthameOperationTestCase {
+	public function setUp() {
+		parent::setUp();
+		$this->service->setWebClient($this->mock()
+																 ->whenCalled('open_url')
+																 ->with('http://ifr.ro/webservices/index.php?sigb=karvi&version=standalone&idclient=bibkey&action=login&username=90100000119049&password=pass')
+																 ->answers('<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <login>
+    <sigb>karvi</sigb>
+    <user>90100000119049</user>
+    <id>L0001910</id>
+    <fullname>testing test</fullname>
+    <error>0</error>
+    <code>0</code>
+  </login>
+</root>
+')
+
+																 ->whenCalled('open_url')
+																 ->with('http://ifr.ro/webservices/index.php?sigb=karvi&version=standalone&idclient=bibkey&action=reserveInfo&userid=L0001910&nn=DOC00236387')
+																 ->answers('<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <reservationInfo>
+    <sigb>karvi</sigb>
+    <user>L0001910</user>
+    <nn>DOC00236387</nn>
+    <site id="T-21" coche="1">Tournée 027 (prochain passage 14/03/2015)</site>
+    <site id="1" coche="0">MD68-Colmar</site>
+    <error>0</error>
+    <code>0</code>
+  </reservationInfo>
+</root>')
+
+																 ->beStrict());
+
+		$user = $this->fixture('Class_Users',
+													 ['id' => 34,
+														'login' => '90100000119049',
+														'password' => 'pass']);
+
+		$item = $this->fixture('Class_Exemplaire',
+													 ['id' => 123,
+														'id_origine' => 'DOC00236387']);
+
+		$this->_locations = $this->service->pickupLocationsFor($user, $item);
+
+	}
+
+
+	/** @test */
+	public function shouldBeKarvi() {
+		$this->assertTrue($this->service->isKarvi());
+	}
+
+
+	/** @test */
+	public function shouldProvidePickupLocations() {
+		$this->assertTrue($this->service->providesPickupLocations());
+	}
+
+
+	/** @test */
+	public function shouldProvide2PickupLocations() {
+		$this->assertEquals(['T-21' => 'Tournée 027 (prochain passage 14/03/2015)',
+												 '1' => 'MD68-Colmar'],
+												$this->_locations);
+	}
+}
+
+
+
 class CarthameAnonymousNoticeTest extends CarthameOperationTestCase {
 	/** @var Class_WebService_SIGB_Notice */
 	protected $anonymous;
-- 
GitLab