diff --git a/VERSIONS_HOTLINE/88224 b/VERSIONS_HOTLINE/88224 new file mode 100644 index 0000000000000000000000000000000000000000..54b23f4c9568c1bf71d192a9345a3f3d7741831d --- /dev/null +++ b/VERSIONS_HOTLINE/88224 @@ -0,0 +1 @@ + - ticket #88224 : SIGB Nanook : Amélioration de la prise en charge dans Bokeh du dédoublonnage effectué dans le SIGB \ No newline at end of file diff --git a/library/Class/Notice/BarcodeDoubleFinder.php b/library/Class/Notice/BarcodeDoubleFinder.php index 552f5d78f26348cf738ea799d74f50ead572b5bc..cb49786552f7e0eb4463e2983167d081d5da070c 100644 --- a/library/Class/Notice/BarcodeDoubleFinder.php +++ b/library/Class/Notice/BarcodeDoubleFinder.php @@ -21,27 +21,18 @@ class Class_Notice_BarcodeDoubleFinder extends Class_Notice_DoubleFinder { - public function find() { - $this->_on_barcode = null; - $this->_id = null; - - if ($this->_id = $this->findByBarcodes()) { - $this->_found_on = 'code_barres'; - return true; - } - - return false; + protected function _buildStrategy() { + parent::_buildStrategy(); + $this->_strategy->addItemFilter([$this, 'filterSigbLoanable']); } - protected function _getRecordIdByItemFilters() { - $filters = parent::_getRecordIdByItemFilters(); - $filters[] = [$this, '_filterSigbLoanable']; - return $filters; + protected function _strategyName() { + return 'Class_Notice_DoubleFinder_BarcodeStrategy'; } - protected function _filterSigbLoanable($items) { + public function filterSigbLoanable($items) { foreach($items as $item) if ($item->isSigbLoanable()) return $item; diff --git a/library/Class/Notice/DoubleFinder.php b/library/Class/Notice/DoubleFinder.php index dd6642a4620c0576ba9e86c0a7c3670cb7579d78..a50221ac5825ce44ce9ffc09d20f291acdf24ee5 100644 --- a/library/Class/Notice/DoubleFinder.php +++ b/library/Class/Notice/DoubleFinder.php @@ -26,6 +26,7 @@ class Class_Notice_DoubleFinder { VAR_DOUBLE_MODE = 'mode_doublon'; protected + $_strategy, $_barcode_uniq_mode, $_double_mode, $_data, @@ -42,28 +43,78 @@ class Class_Notice_DoubleFinder { if (!$this->_library = Class_IntBib::find($library_id)) $this->_library = Class_IntBib::newInstance(); + + $this->_buildStrategy(); + } + + + protected function _buildStrategy() { + $strategy_name = $this->_strategyName(); + $library_limit = ($this->_barcode_uniq_mode == Class_CosmoVar::UNIQ_BARCODE_WITHIN_LIBRARY) + ? (int) $this->_library->getId() + : null; + + $this->_strategy = new $strategy_name($library_limit); + } + + + protected function _strategyName() { + if ($this->_profil + && ($this->_profil->isFormatDublinCore() || $this->_profil->isBibliondemand())) + return 'Class_Notice_DoubleFinder_BarcodeStrategy'; + + if (($this->_double_mode == Class_CosmoVar::DOUBLE_SEARCH_NONE) + && $this->_library->isPergame()) + return 'Class_Notice_DoubleFinder_NoDedupStrategy'; + + if ($this->_double_mode == Class_CosmoVar::DOUBLE_SEARCH_ALPHA_KEY) + return 'Class_Notice_DoubleFinder_AlphaKeyStrategy'; + + return 'Class_Notice_DoubleFinder_IdsStrategy'; } public function find() { - $this->_on_barcode = null; - $this->_id = null; + return $this->_strategy->find($this->_data); + } - if ($this->_id = $this->findByBarcodes()) { - $this->_found_on = 'code_barres'; - return true; - } - if ($this->_profil && ($this->_profil->isFormatDublinCore() || $this->_profil->isBibliondemand())) - return false; + public function getMatchedCriteria() { + return $this->_strategy->getMatchedCriteria(); + } - if ($this->_id = $this->findByIdOrigine()) { - $this->_found_on = 'id_origine'; - return true; - } - return (bool) ($this->_id = $this->findByIds()); + public function getId() { + return $this->_strategy->getId(); } +} + + + +abstract class Class_Notice_DoubleFinder_Strategy { + const + FOUND_ON_BARCODE = 'code_barres', + FOUND_ON_ID_ORIGINE = 'id_origine'; + + protected + $_data, + $_id, + $_found_on, + $_library_limit, + $_item_filters; + + + public function __construct($library_limit) { + $this->_library_limit = $library_limit; + $this->_item_filters = [ [$this, '_filterSameDoctype'] ]; + } + + + /** + * @param Class_Entity $data + * @return bool true if double has been found + */ + abstract public function find($data); public function getMatchedCriteria() { @@ -76,37 +127,34 @@ class Class_Notice_DoubleFinder { } - protected function findByBarcodes() { + public function addItemFilter($filter) { + $this->_item_filters[] = $filter; + return $this; + } + + + protected function _findByBarcodes() { if (!$this->_hasItems()) return; foreach ($this->_data->getexemplaires() as $item) - if ($id = $this->findByBarcodeOf($item)) + if ($id = $this->_findByBarcodeOf($item)) return $id; } - protected function findByBarcodeOf($item) { + protected function _findByBarcodeOf($item) { if (!$item['code_barres']) return; $conditions = ['code_barres' => $item['code_barres']]; - if ($this->_barcode_uniq_mode == Class_CosmoVar::UNIQ_BARCODE_WITHIN_LIBRARY) - $conditions['id_int_bib'] = (int) $this->_library->getId(); + if ($this->_library_limit) + $conditions['id_int_bib'] = $this->_library_limit; return $this->_getRecordIdByItem($conditions); } - protected function findByIdOrigine() { - if (($this->_double_mode != Class_CosmoVar::DOUBLE_SEARCH_NONE) - || !$this->_library->isPergame()) - return; - - return $this->_getRecordIdByItem(['id_origine' => $this->_data->getid_origine()]); - } - - protected function _getRecordIdByItem($conditions) { $conditions['type'] = Class_Notice::TYPE_BIBLIOGRAPHIC; $founds = Class_Exemplaire::findAllBy($conditions); @@ -120,7 +168,7 @@ class Class_Notice_DoubleFinder { protected function _getRecordIdByItemFilters() { - return [ [$this, '_filterSameDoctype'] ]; + return $this->_item_filters; } @@ -131,8 +179,104 @@ class Class_Notice_DoubleFinder { } + protected function _hasItems() { + return ($statuses = $this->_data->getstatut_exemplaires()) + || $statuses['nb_ex'] > 0; + } +} + + + +class Class_Notice_DoubleFinder_BarcodeStrategy extends Class_Notice_DoubleFinder_Strategy { + public function find($data) { + $this->_id = null; + $this->_data = $data; + + if ($this->_id = $this->_findByBarcodes()) { + $this->_found_on = static::FOUND_ON_BARCODE; + return true; + } + + return false; + } +} + + + +class Class_Notice_DoubleFinder_NoDedupStrategy extends Class_Notice_DoubleFinder_Strategy { + public function find($data) { + $this->_id = null; + $this->_data = $data; + + if ($this->_id = $this->_findByBarcodes()) { + $this->_found_on = static::FOUND_ON_BARCODE; + return true; + } + + if ($this->_id = $this->_findByIdOrigine()) { + $this->_found_on = static::FOUND_ON_ID_ORIGINE; + return true; + } + + return false; + } + + + protected function _findByIdOrigine() { + return $this->_getRecordIdByItem(['id_origine' => $this->_data->getid_origine()]); + } + + + protected function _findByBarcodeOf($item) { + if (!$item['code_barres']) + return; + + $conditions = ['code_barres' => $item['code_barres']]; + if ($this->_library_limit) + $conditions['id_int_bib'] = $this->_library_limit; + + $conditions['type'] = Class_Notice::TYPE_BIBLIOGRAPHIC; + $founds = Class_Exemplaire::findAllBy($conditions); + if (empty($founds)) + return; + + foreach($founds as $found) + if ($this->_isValidItem($found)) + return $found->getIdNotice(); + } + + + protected function _isValidItem($item) { + if ($this->_data->gettype_doc() != $item->getTypeDoc()) + return false; + + if ($this->_data->getid_origine() != $item->getIdOrigine()) { + $item->delete(); + return false; + } + + return true; + } +} + + + +abstract class Class_Notice_DoubleFinder_KeysStrategy extends Class_Notice_DoubleFinder_Strategy { + public function find($data) { + $this->_id = null; + $this->_data = $data; + + if ($this->_id = $this->_findByBarcodes()) { + $this->_found_on = static::FOUND_ON_BARCODE; + return true; + } + + return (bool) ($this->_id = $this->findByIds()); + } + + protected function findByIds() { - foreach ($this->recordAttributes() as $attr) + foreach ($this->_recordAttributes() as $attr) if ($id = $this->findById($attr)) return $id; } @@ -148,18 +292,7 @@ class Class_Notice_DoubleFinder { } - protected function recordAttributes() { - if ($this->_double_mode == Class_CosmoVar::DOUBLE_SEARCH_IDS) - return [['isbn', $this->_data->getisbn13()], - ['isbn', $this->_data->getisbn10()], - ['ean', $this->_data->getean()], - ['id_commerciale', $this->_data->getid_commerciale()]]; - - if ($this->_double_mode == Class_CosmoVar::DOUBLE_SEARCH_ALPHA_KEY) - return [ ['clef_alpha', $this->_data->getclef_alpha()] ]; - - return []; - } + abstract protected function _recordAttributes(); protected function findRecordBy($key, $value) { @@ -175,10 +308,23 @@ class Class_Notice_DoubleFinder { if($this->_data->gettype_doc() == $found->getTypeDoc()) return $found->getId(); } +} - protected function _hasItems() { - return ($statuses = $this->_data->getstatut_exemplaires()) - || $statuses['nb_ex'] > 0; + +class Class_Notice_DoubleFinder_IdsStrategy extends Class_Notice_DoubleFinder_KeysStrategy { + protected function _recordAttributes() { + return [['isbn', $this->_data->getisbn13()], + ['isbn', $this->_data->getisbn10()], + ['ean', $this->_data->getean()], + ['id_commerciale', $this->_data->getid_commerciale()]]; + } +} + + + +class Class_Notice_DoubleFinder_AlphaKeyStrategy extends Class_Notice_DoubleFinder_KeysStrategy { + protected function _recordAttributes() { + return [ ['clef_alpha', $this->_data->getclef_alpha()] ]; } } \ No newline at end of file diff --git a/tests/library/Class/Notice/DoubleFinderTest.php b/tests/library/Class/Notice/DoubleFinderTest.php index a33c63e59d18b1875de341cdbacd814421adc5f6..ffde3b95af5998af371e8676ef9dbc66cb3ec2c6 100644 --- a/tests/library/Class/Notice/DoubleFinderTest.php +++ b/tests/library/Class/Notice/DoubleFinderTest.php @@ -22,7 +22,6 @@ abstract class DoubleFinderTestCase extends ModelTestCase { protected - $_storm_default_to_volatile = true, $_data = ['type_doc' => Class_TypeDoc::LIVRE], $_library_id = 1, $_finder, @@ -39,45 +38,38 @@ abstract class DoubleFinderTestCase extends ModelTestCase { protected function _prepareFixtures() { - $item = $this->fixture('Class_Exemplaire', - ['id' => 1, - 'code_barres' => '159', - 'id_origine' => '88903', - 'id_int_bib' => 1]); - $this->fixture('Class_Notice', ['id' => 1, 'type_doc' => Class_TypeDoc::LIVRE, 'isbn' => '2-85868-161-9', 'clef_alpha' => 'JESUISNEBONHOMME--SARA--EDTHIERRYMAGNIER-2010-1', - 'exemplaires' => [$item]]); - - $dilicom_item = $this->fixture('Class_Exemplaire', - ['id' => 2, - 'code_barres' => '0001-2', - 'id_origine' => '88903', - 'id_int_bib' => 1]); + 'exemplaires' => [ $this->fixture('Class_Exemplaire', + ['id' => 1, + 'code_barres' => '159', + 'id_origine' => '88903', + 'id_int_bib' => 1])]]); $this->fixture('Class_Notice', ['id' => 2, 'type_doc' => Class_TypeDoc::DILICOM, 'isbn' => '2-85868-161-9', 'clef_alpha' => 'JESUISNEBONHOMME--SARA--EDTHIERRYMAGNIER-2010-1', - 'exemplaires' => [$dilicom_item]]); - - $rss_item = $this->fixture('Class_Exemplaire', - ['id' => 3, - 'code_barres' => '159', - 'id_origine' => '789', - 'id_int_bib' => 1]); + 'exemplaires' => [ $this->fixture('Class_Exemplaire', + ['id' => 2, + 'code_barres' => '0001-2', + 'id_origine' => '88903', + 'id_int_bib' => 1])]]); $this->fixture('Class_Notice', ['id' => 3, 'type_doc' => Class_TypeDoc::RSS, 'isbn' => '2-85868-161-9', 'clef_alpha' => 'JESUISNEBONHOMME--SARA--EDTHIERRYMAGNIER-2010-1', - 'exemplaires' => [$rss_item]]); - + 'exemplaires' => [ $this->fixture('Class_Exemplaire', + ['id' => 3, + 'code_barres' => '159', + 'id_origine' => '789', + 'id_int_bib' => 1])]]); } @@ -93,8 +85,16 @@ abstract class DoubleFinderTestCase extends ModelTestCase { -class DoubleFinderWithNoNoticeTest extends DoubleFinderTestCase { +class DoubleFinderWithoutAnyRecordTest extends DoubleFinderTestCase { + /** @test */ + public function shouldNotFindDouble() { + $this->assertNotFound(); + } +} + + +class DoubleFinderWithNoNoticeTest extends DoubleFinderTestCase { protected $_data = ['type_doc' => Class_TypeDoc::DILICOM, 'statut_exemplaires' => ['nb_ex' => 1], 'exemplaires' => [ ['code_barres' => '302'] ]]; @@ -111,16 +111,7 @@ class DoubleFinderWithNoNoticeTest extends DoubleFinderTestCase { /** @test */ - public function WithExemplaireWithoutNoticeShouldNotFound() { - $this->assertFalse($this->_found); - } -} - - - -class DoubleFinderWithoutAnyRecordTest extends DoubleFinderTestCase { - /** @test */ - public function shouldNotFindDouble() { + public function WithExemplaireWithoutNoticeShouldNotFindDouble() { $this->assertNotFound(); } } @@ -128,7 +119,6 @@ class DoubleFinderWithoutAnyRecordTest extends DoubleFinderTestCase { abstract class DoubleFinderWithRecordMatchingTestCase extends DoubleFinderTestCase { - /** @test */ public function shouldFindRecord() { $this->assertFound(); @@ -200,9 +190,8 @@ class DoubleFinderWithExistingAlphaKeyTest extends DoubleFinderWithRecordMatchin protected function _prepareFixtures() { parent::_prepareFixtures(); - $this->fixture('Class_CosmoVar', - ['id' => Class_Notice_DoubleFinder::VAR_DOUBLE_MODE, - 'valeur' => Class_CosmoVar::DOUBLE_SEARCH_ALPHA_KEY]); + Class_CosmoVar::set(Class_Notice_DoubleFinder::VAR_DOUBLE_MODE, + Class_CosmoVar::DOUBLE_SEARCH_ALPHA_KEY); } @@ -219,15 +208,17 @@ class DoubleFinderWithExistingItemInAnotherLibraryTest extends DoubleFinderTestC $_data = ['type_doc' => Class_TypeDoc::LIVRE, 'statut_exemplaires' => ['nb_ex' => 1], 'exemplaires' => [ ['code_barres' => '159'] ]], + $_library_id = 42; protected function _prepareFixtures() { parent::_prepareFixtures(); - $this->fixture('Class_CosmoVar', - ['id' => Class_Notice_DoubleFinder::VAR_BARCODE_UNIQ_MODE, - 'valeur' => '1']); + Class_CosmoVar::set(Class_Notice_DoubleFinder::VAR_BARCODE_UNIQ_MODE, + Class_CosmoVar::UNIQ_BARCODE_WITHIN_LIBRARY); + + $this->fixture('Class_IntBib', ['id' => 42]); } @@ -248,9 +239,8 @@ class DoubleFinderWithExistingItemAndNoDedupModeTest extends DoubleFinderWithRec protected function _prepareFixtures() { parent::_prepareFixtures(); - $this->fixture('Class_CosmoVar', - ['id' => Class_Notice_DoubleFinder::VAR_DOUBLE_MODE, - 'valeur' => Class_CosmoVar::DOUBLE_SEARCH_NONE]); + Class_CosmoVar::set(Class_Notice_DoubleFinder::VAR_DOUBLE_MODE, + Class_CosmoVar::DOUBLE_SEARCH_NONE); } @@ -269,9 +259,8 @@ class DoubleFinderWithExistingIdOrigneNoDedupModeDefaultTest extends DoubleFinde protected function _prepareFixtures() { parent::_prepareFixtures(); - $this->fixture('Class_CosmoVar', - ['id' => Class_Notice_DoubleFinder::VAR_DOUBLE_MODE, - 'valeur' => Class_CosmoVar::DOUBLE_SEARCH_NONE]); + Class_CosmoVar::set(Class_Notice_DoubleFinder::VAR_DOUBLE_MODE, + Class_CosmoVar::DOUBLE_SEARCH_NONE); } @@ -294,9 +283,8 @@ class DoubleFinderWithExistingIdOrigneNoDedupModeForNanookTestTest extends Doubl ['id' => 1, 'sigb' => Class_IntBib::SIGB_NANOOK]); - $this->fixture('Class_CosmoVar', - ['id' => Class_Notice_DoubleFinder::VAR_DOUBLE_MODE, - 'valeur' => Class_CosmoVar::DOUBLE_SEARCH_NONE]); + Class_CosmoVar::set(Class_Notice_DoubleFinder::VAR_DOUBLE_MODE, + Class_CosmoVar::DOUBLE_SEARCH_NONE); } @@ -304,4 +292,119 @@ class DoubleFinderWithExistingIdOrigneNoDedupModeForNanookTestTest extends Doubl public function shouldHaveMatchedIdOrigine() { $this->assertEquals('id_origine', $this->_finder->getMatchedCriteria()); } +} + + + +/** @see #88224 */ +class DoubleFinderWithExistingCodeBarreInRemotelyDeletedRecordNoDedupModeForNanookTest + extends DoubleFinderWithRecordMatchingTestCase { + protected $_data = ['type_doc' => Class_TypeDoc::LIVRE, + 'id_origine' => '88903', + 'statut_exemplaires' => ['nb_ex' => 1], + 'exemplaires' => [ [ 'code_barres' => 'CLJ0003D82' ] ]]; + + protected function _prepareFixtures() { + parent::_prepareFixtures(); + + $this->fixture('Class_IntBib', + ['id' => 1, + 'sigb' => Class_IntBib::SIGB_NANOOK]); + + Class_CosmoVar::set(Class_Notice_DoubleFinder::VAR_DOUBLE_MODE, + Class_CosmoVar::DOUBLE_SEARCH_NONE); + + $this->fixture('Class_Notice', + ['id' => 55, + 'type_doc' => Class_TypeDoc::LIVRE, + 'isbn' => '2-85868-161-9', + 'clef_alpha' => 'JESUISNEBONHOMME--SARA--EDTHIERRYMAGNIER-2010-1', + 'exemplaires' => [ $this->fixture('Class_Exemplaire', + ['id' => 4, + 'id_origine' => '99283087', + 'code_barres' => 'CLJ0003D82', + 'id_int_bib' => 1, + ])]]); + } + + + /** @test */ + public function shouldHaveMatchedIdOrigine() { + $this->assertEquals('id_origine', $this->_finder->getMatchedCriteria()); + } + + + /** @test */ + public function itemInPreviousRecordShouldBeDeleted() { + $this->assertNull(Class_Exemplaire::find(4)); + } +} + + + +class DoubleFinderWithDublinCoreProfileTest extends ModelTestCase { + public function setUp() { + parent::setUp(); + + Class_CosmoVar::set(Class_Notice_DoubleFinder::VAR_BARCODE_UNIQ_MODE, + Class_CosmoVar::UNIQ_BARCODE_WITHIN_LIBRARY); + + Class_CosmoVar::set(Class_Notice_DoubleFinder::VAR_DOUBLE_MODE, + Class_CosmoVar::DOUBLE_SEARCH_ALPHA_KEY); + + $this->fixture('Class_IntBib', ['id' => 1]); + $this->fixture('Class_IntProfilDonnees', + ['id' => 99, + 'format' => Class_IntProfilDonnees::FORMAT_DUBLIN_CORE]); + } + + + /** @test */ + public function shouldFindExistingBarCodeOfSameDoctypeInSameLibrary() { + $id_origine = 'any:oai:server:883987228'; + $bar_code = md5($id_origine); + + $this->fixture('Class_Notice', + ['id' => 99, + 'type_doc' => Class_TypeDoc::LIVRE, + 'exemplaires' => [ $this->fixture('Class_Exemplaire', + ['id' => 839, + 'code_barres' => $bar_code, + 'id_origine' => $id_origine, + 'id_int_bib' => 1])]]); + + $datas = ['type_doc' => Class_TypeDoc::LIVRE, + 'id_origine' => $id_origine, + 'statut_exemplaires' => ['nb_ex' => 1], + 'exemplaires' => [ [ 'code_barres' => $bar_code ] ]]; + + $finder = new Class_Notice_DoubleFinder($datas, 1, 99); + + $this->assertTrue($finder->find()); + $this->assertEquals(99, $finder->getId()); + $this->assertEquals(Class_Notice_DoubleFinder_Strategy::FOUND_ON_BARCODE, + $finder->getMatchedCriteria()); + } + + + /** @test */ + public function shouldNotFindExistingAlphaKeyOfSameDoctypeInSameLibrary() { + $alpha_key = 'UNEFAMILLEANGLAISE--WALSHH--FLAMMARION-2011-1'; + + $this->fixture('Class_Notice', + ['id' => 99, + 'type_doc' => Class_TypeDoc::LIVRE, + 'clef_alpha' => $alpha_key]); + + $id_origine = 'any:oai:server:883987228'; + $bar_code = md5($id_origine); + $datas = ['type_doc' => Class_TypeDoc::LIVRE, + 'id_origine' => $id_origine, + 'statut_exemplaires' => ['nb_ex' => 1], + 'exemplaires' => [ [ 'code_barres' => $bar_code ] ]]; + + $finder = new Class_Notice_DoubleFinder($datas, 1, 99); + + $this->assertFalse($finder->find()); + } } \ No newline at end of file