Commit a73246dd authored by Laurent's avatar Laurent
Browse files

Merge branch 'dev#92615_integration_periodiques_koha_pmb' into 'master'

dev #92615 Koha : import serial titles and articles. Update PMB serial import

See merge request !3400
parents 476bfc52 8c86afc8
Pipeline #9402 passed with stage
in 43 minutes and 57 seconds
......@@ -122,7 +122,10 @@ class NoticeAjaxController extends ZendAfi_Controller_Action {
public function exemplairesAction() {
if ($this->notice->isFirstItemTypeSerialArticle())
$this->notice = $this->notice->getFirstExemplaire()->getPMBSerialRecord();
$this->notice = $this->notice->getLinkedSerialRecord();
if (!$this->notice)
return $this->_sendResponseWithScripts(sprintf('<p>%s</p>', $this->_('Aucun exemplaire trouvé')));
$nb_notices_oeuvre = Class_Notice::countBy(['clef_oeuvre' => $this->notice->getClefOeuvre(),
'id_notice not' => $this->notice->getId()]);
......@@ -163,11 +166,9 @@ class NoticeAjaxController extends ZendAfi_Controller_Action {
if ($xsl->isEnabled())
return $this->_sendResponseWithScripts($this->view->Notice_Xsl($xsl));
if ($notice->isPeriodique()) {
$periodiques = $this->notice->getArticlesPeriodique($this->id_notice);
return $this->_sendResponseWithScripts($this->notice_html->getArticlesPeriodique($periodiques));
}
if ($notice->isPeriodique())
return $this->_sendResponseWithScripts($this->view->Notice_ArticlesPeriodiques($notice));
$html = $this->view->notice_Entete($notice, ['entete' => Class_Codification::CHAMPS]);
$this->_sendResponseWithScripts($html);
......
......@@ -8,7 +8,7 @@ echo $this->toolbar($this->_("Recherche"),
<h3><?php echo $this->iconeSupport($this->notice->getTypeDoc()) . $this->notice->getTitrePrincipal() ;?></h3>
<p class="serie">
<?php
echo $this->getHelper('Notice_Entete')->addSeries($this->notice);
echo $this->notice_SeriesLink($this->notice);
?>
</p>
<p><?php echo $this->notice->getAuteurPrincipal();?></p>
......
'92615' =>
['Label' => $this->_('Intégration des périodiques issus des SIGB Koha et PMB'),
'Desc' => $this->_('Bokeh gère trois niveaux de notices de périodiques: titre de périodique, fascicule et dépouillement. Pour chaque niveau de notice, Bokeh affichera des liens pour aller au niveau supérieur ou inférieur'),
'Image' => '',
'Video' => 'https://youtu.be/tbdQufZij_k',
'Category' => $this->_('Intégration du catalogue'),
'Right' => function($feature_description, $user) {return true;},
'Wiki' => 'http://wiki.bokeh-library-portal.org/index.php?title=Import_des_p%C3%A9riodiques_Koha_dans_Bokeh',
'Test' => '',
'Date' => '2020-02-06'],
\ No newline at end of file
- ticket #92615 : Intégration des périodiques issus des SIGB Koha et PMB
\ No newline at end of file
......@@ -44,4 +44,9 @@ $front = Zend_Controller_Front::getInstance()
->registerPlugin(new ZendAfi_Controller_Plugin_CosmoAuth())
->registerPlugin(new ZendAfi_Controller_Plugin_CosmoBaseUrl());
$current_profil = Class_Profil::getCurrentProfil();
defineConstant('PATH_SKIN', '.' . $current_profil->getPathTheme());
defineConstant('URL_IMG', BASE_URL . $current_profil->getPathTheme() . 'images/');
$front->dispatch();
\ No newline at end of file
......@@ -126,18 +126,19 @@ class profil_donnees {
$this->attributs[0]["type_doc"][$i]["label"] = [];
$this->attributs[0]["type_doc"][$i]["zone_995"] = [];
for($j=0; $j < count($td); $j++) {
if(!isset($td[$j]["label"]))
foreach($td as $j => $definition) {
if(!isset($definition["label"]))
continue;
if($td[$j]["code"] == $type_doc->getId()) {
$this->attributs[0]["type_doc"][$i]["label"]=explode(";",$td[$j]["label"]);
$this->attributs[0]["type_doc"][$i]["zone_995"]=explode(";",$td[$j]["zone_995"]);
if ($definition["code"] == $type_doc->getId()) {
$this->attributs[0]["type_doc"][$i]["label"]=explode(";",$definition["label"]);
$this->attributs[0]["type_doc"][$i]["zone_995"]=explode(";",$definition["zone_995"]);
break;
}
}
}
// decompacter et consolider champs xml
$champs = getCodifsVariable("champs_abonne");
foreach($champs as $champ) {
......
......@@ -37,6 +37,9 @@ class notice_unimarc extends iso2709_record {
'949', // Libermedia
];
const RECORD_STATUS_OK = 0;
const RECORD_STATUS_DELETED = 1;
private $id_profil; // Id du profil de données pour le fichier chargé
private $profil_unimarc; // Instance du profil unimarc pour optimiser
private $type_doc_force; // Type de document forcé dans maj_auto
......@@ -44,14 +47,13 @@ class notice_unimarc extends iso2709_record {
protected $profil; // Structure des valeurs du profil en cours
private $copyright; // Mots clefs pour les notices non libres de droits (801$b)
private $sigb; // Pour traitements specifiques
private $champs_forces; // Liste des champs forcés
private $ean345; // Reconnaissance des ean par la zone 345$b
private $regles_sections_genres; // Règles de reconnaissance des sections et des genres
private $id_genre_documentaire; // Identifiant pour le genre "documentaire"
private $controle_codes_barres; // Exception de filtrage des codes-barres
protected $_id_bib; // Bibliotheque d'intégration
protected $_fluent; // Class_NoticeUnimarc_Fluent
protected $_type_doc; //type do document
public function __construct($id_bib=null) {
$this->_id_bib = $id_bib;
......@@ -60,8 +62,6 @@ class notice_unimarc extends iso2709_record {
$data = getVariable('non_exportable');
$this->copyright = explode(';', $data);
$this->controle_codes_barres = getVariable('controle_codes_barres');
$data = getVariable('champs_sup');
$this->champs_forces = explode(';', $data);
$this->ean345 = getVariable('ean_345');
// Règles sections, genres, emplacements
......@@ -71,6 +71,7 @@ class notice_unimarc extends iso2709_record {
public function ouvrirNotice($data, $id_profil, $sigb=0, $type_doc_force='', $decode_string = true) {
$this->_type_doc = null;
$this->type_doc_force['label'] = $type_doc_force;
$type_doc_map = ['a' => '1', 'j' => '3', 'g' => '4',
'l' => '5', 'c' => '6', 'f' => '7'];
......@@ -125,27 +126,13 @@ class notice_unimarc extends iso2709_record {
}
public function getNoticeIntegration() {
$type_doc = $this->getTypeDocAsArray();
if ($type_doc['code'] == Class_TypeDoc::SERIAL_ARTICLE)
return $this->getNoticeIntegrationArticlePeriodique();
if ($type_doc['code'] == Class_TypeDoc::PERIODIQUE)
$notice['articles_periodiques'] = $this->getIdArticlesPeriodiques();
// exemplaires
$ex = $this->getExemplaires();
$warnings = $ex['warnings'];
//external url
$this->updateItemsWithUrl($ex['exemplaires']);
// Isbn /ean
protected function _getIdentifiers($type_doc) {
$trav = $this->getIsbn();
if($trav['statut'] == 1)
$warnings[] = ['isbn incorrect', $trav['code_brut']];
$isbn = $trav['isbn'];
$ean = $trav['ean'];
if(!$isbn and !$ean) {
$trav = $this->getEan();
if($trav['statut'] == 1)
......@@ -155,23 +142,55 @@ class notice_unimarc extends iso2709_record {
}
// Virer ISBN si autre que livre
if ((!$type = Class_TypeDoc::find((int)$type_doc['code']))
if ((!$type = Class_TypeDoc::find((int)$type_doc))
|| !$type->isBook()) {
$trav['isbn10'] = $trav['isbn13'] = $isbn = '';
$trav['isbn10'] = $trav['isbn13'] = $trav['isbn'] = '';
}
return $trav;
}
public function getNoticeIntegration() {
$type_doc = $this->getTypeDoc();
if ($type_doc == Class_TypeDoc::SERIAL_ARTICLE)
return $this->getNoticeIntegrationArticlePeriodique();
if ($type_doc == Class_TypeDoc::PERIODIQUE)
$notice['articles_periodiques'] = $this->getIdArticlesPeriodiques();
// exemplaires
$ex = $this->getExemplaires();
$warnings = $ex['warnings'];
//external url
$this->updateItemsWithUrl($ex['exemplaires']);
$record_identifiers = $this->_getIdentifiers($type_doc);
// Structure notice
$notice["statut"] = $this->getStatut();
$notice["isbn"] = $isbn;
$notice["isbn10"] = $trav["isbn10"];
$notice["isbn13"] = $trav["isbn13"];
$notice["ean"] = $ean;
$notice["isbn"] = $record_identifiers['isbn'];
$notice["isbn10"] = $record_identifiers['isbn10'];
$notice["isbn13"] = $record_identifiers['isbn13'];
$notice["ean"] = $record_identifiers['ean'];
$notice["id_origine"] = $this->getIdOrigine();
$notice["clef_alpha"] = $this->getClefAlpha();
$notice["clef_oeuvre"] = $this->getClefAlpha(true);
$notice["tome_alpha"] = $this->indexation->alphaMaj($this->getTome());
$notice["clef_alpha"] = $this->indexation->getClefAlpha(
$this->getTypeDoc(),
$this->getTitrePrincipal(),
$this->getComplementTitre(),
$this->getAuteurClefAlpha(),
$notice['tome_alpha'],
$this->getEditeur(),
$this->getAnnee());
$notice["clef_oeuvre"] = $this->indexation->getClefOeuvre(
$this->getTitrePrincipal(),
$this->getComplementTitre(),
$this->getAuteurClefAlpha(),
$notice['tome_alpha']);
$notice["clef_chapeau"] = $this->getClefChapeau();
$notice["titre_princ"] = $this->getTitrePrincipal();
$notice["tome_alpha"] = $this->indexation->alphaMaj($this->getTome());
$notice["alpha_titre"] = $this->indexation->codeAlphaTitre($notice["titre_princ"]." ".$notice["tome_alpha"]);
$notice["id_commerciale"] = $this->getIdCommerciale($notice["alpha_titre"]);
$notice["titres"] = $this->getTitres();
......@@ -190,8 +209,8 @@ class notice_unimarc extends iso2709_record {
$notice["matieres"] = $this->getMatieresLabels();
$notice["matieres_renvois"] = $this->getMatieresRenvois();
$notice["annee"] = $this->getAnnee();
$notice["type_doc"] = $type_doc["code"];
$notice["infos_type_doc"] = $type_doc;
$notice["type_doc"] = $type_doc;
$notice["exportable"] = $this->getExportable();
$notice["dewey"] = $this->getDewey();
......@@ -216,6 +235,12 @@ class notice_unimarc extends iso2709_record {
if (!empty($ret["genre"]))
$notice["genres"] = $ret["genre"];
if (in_array((string)$notice["type_doc"],
[(string)Class_TypeDoc::PERIODIQUE,
(string)Class_TypeDoc::PERIODIQUE_TITLE,
(string)Class_TypeDoc::PERIODIQUE_ARTICLE]))
$notice = $this->_handleSerials($notice);
if ($notice["statut_exemplaires"]["nb_ex"] > 0) {
for($i=0; $i <count($notice["exemplaires"]); $i++) {
$exemplaire = $notice["exemplaires"][$i];
......@@ -244,6 +269,97 @@ class notice_unimarc extends iso2709_record {
return $notice;
}
protected function _handleSerials($notice) {
if ((int)$this->profil["id_article_periodique"] == Class_IntProfilDonnees::SERIAL_FORMAT_PMB) {
return $this->_handleSerialsPMB($notice);
}
if ((int)$this->profil["id_article_periodique"] == Class_IntProfilDonnees::SERIAL_FORMAT_KOHA) {
return $this->_handleSerialsKoha($notice);
}
return $notice;
}
protected function _handleSerialsKoha($notice) {
if (0 != count($notice['exemplaires']))
return $notice;
if (!$record_001 = $this->get_subfield('461', '9')[0])
return $notice;
$numero = $this->get_subfield('461', 'v')[0];
$id_head_record = $record_001 . '-' . $numero;
return $this->_generateItemForSerialRecordLink($notice, $numero, $id_head_record);
}
protected function _handleSerialsPMB($notice) {
if ($notice['exemplaires']) {
$titre_chapeau = $this->get_subfield('200', 'h')[0];
$notice["clef_chapeau"] = $this->indexation->codeAlphaTitre($titre_chapeau);
$notice["tome_alpha"] = $this->indexation->alphaMaj($this->get_subfield('463', 'v')[0]);
$notice["clef_oeuvre"] = $this->indexation->getClefOeuvre($titre_chapeau,
$this->getComplementTitre(),
$this->getAuteurClefAlpha(),
$notice['tome_alpha']);
$notice["clef_alpha"] = $this->indexation->getClefAlpha(
$this->getTypeDoc(),
$this->getTitrePrincipal(),
$this->getComplementTitre(),
$this->getAuteurClefAlpha(),
$notice['tome_alpha'],
$this->getEditeur(),
$this->getAnnee());
return $notice;
}
if ($notice['type_doc'] == Class_TypeDoc::PERIODIQUE_TITLE) {
$notice['exemplaires'] = [
['code_barres' => sprintf('%s-%s',
$this->_id_bib,
$notice["id_origine"]) ]
];
$notice["statut_exemplaires"]["nb_ex"] = 1;
return $notice;
}
$head_link = $this->get_subfield('463', '9');
if (!$id_bull = end(explode(':', $head_link[0])))
return $notice;
$numero = $this->indexation->alphaMaj($this->get_subfield('463', 'v')[0]);
$id_head_record = $id_bull . '-bull';
return $this->_generateItemForSerialRecordLink($notice, $numero, $id_head_record);
}
protected function _generateItemForSerialRecordLink($notice, $numero, $id_head_record) {
$titre_chapeau = $this->get_subfield('461', 't')[0];
$notice["clef_chapeau"] = $this->indexation->serialCodeAlphaChapeau($titre_chapeau, $numero);
$notice['exemplaires'] = [
['code_barres' => sprintf('%s-%s',
$this->_id_bib,
$notice["id_origine"]),
'type' => Class_Notice::TYPE_SERIAL_ARTICLE,
'zone995' => serialize([ ['code' => '0',
'valeur' => $id_head_record] ])
]
];
$notice["statut_exemplaires"]["nb_ex"] = 1;
return $notice;
}
// ----------------------------------------------------------------
// Notice de periodique
// ----------------------------------------------------------------
......@@ -251,8 +367,6 @@ class notice_unimarc extends iso2709_record {
{
// type de doc
$notice["type_doc"] = Class_TypeDoc::SERIAL_ARTICLE;
$notice["infos_type_doc"] = ["code"=> Class_TypeDoc::SERIAL_ARTICLE, 'libelle'=>"article de périodique"];
// statut
$notice["statut"] = $this->getStatut();
$notice["clef_chapeau"]="";
......@@ -281,7 +395,7 @@ class notice_unimarc extends iso2709_record {
// clef titre de l'article
$titre=$this->getTitrePrincipal();
$notice["titre_princ"]=$titre;
$notice["titre_princ"] = $titre;
$titre=$this->indexation->codeAlphaTitre($titre);
$notice["clef_article"]=substr($titre,0,20);
......@@ -891,6 +1005,12 @@ class notice_unimarc extends iso2709_record {
}
public function getIssn() {
$issn = $this->get_subfield("011", "a");
return trim($issn[0]);
}
protected function _detectIsbn($datas) {
if (!$datas)
return '';
......@@ -928,7 +1048,7 @@ class notice_unimarc extends iso2709_record {
$code=trim($data[0]);
if($code)
{
$oIsbn=new class_isbn($code);
$oIsbn = new Class_Isbn($code);
$ean=$oIsbn->getAll();
}
}
......@@ -994,21 +1114,6 @@ class notice_unimarc extends iso2709_record {
}
public function getClefAlpha($oeuvre=false) {
$type_doc = $this->getTypeDoc();
$titre = $this->getTitrePrincipal();
$complement_titre = $this->getComplementTitre();
$auteur = $this->getAuteurClefAlpha();
$editeur = $this->getEditeur();
$annee = $this->getAnnee();
$tome = $this->getTome();
return ($oeuvre) ?
$this->indexation->getClefOeuvre($titre, $complement_titre, $auteur, $tome) :
$this->indexation->getClefAlpha($type_doc, $titre, $complement_titre, $auteur, $tome, $editeur, $annee);
}
public function getClefChapeau() {
if (!$titre = $this->get_subfield('461', 't'))
$titre = $this->get_subfield('410', 't');
......@@ -1019,7 +1124,10 @@ class notice_unimarc extends iso2709_record {
}
public function getTypeDoc($infos=false) {
public function getTypeDoc() {
if (null !== $this->_type_doc)
return $this->_type_doc;
if($this->type_doc_force['label'])
$this->inner_guide['dt'] = $this->type_doc_force['label'];
......@@ -1045,27 +1153,8 @@ class notice_unimarc extends iso2709_record {
? $this->type_doc_force['code']
: $this->profil_unimarc->getTypeDoc($label, $z995r, $z995p)['code'];
if ($infos) {
$ret["code"] = $typeDoc["code"];
$ret["infos"] = "Label=".$label;
if (isset($z995r[0]))
$ret["infos"] .= " - "."995\$r=".$z995r[0];
if (isset($z995p[0]))
$ret["infos"] .= " - \$p=".$z995p[0];
$ret["libelle"] = ($this->type_doc_force["label"] > "")
? getLibCodifVariable('types_docs', $typeDoc['code'])
: '';
return $ret;
}
return ($typeDoc['code']) ? $typeDoc['code'] : 0;
}
public function getTypeDocAsArray() {
return $this->getTypeDoc(true);
$this->_type_doc = ($typeDoc['code']) ? $typeDoc['code'] : 0;
return $this->_type_doc;
}
......@@ -1430,9 +1519,9 @@ class notice_unimarc extends iso2709_record {
* 0=ok 1=detruire la notice
*/
public function getStatut() {
$statut = 0;
$statut = static::RECORD_STATUS_OK;
if ($this->inner_guide['rs'] == 'd')
$statut = 1;
$statut = static::RECORD_STATUS_DELETED;
$ex = $data = $this->get_subfield('995');
$nb_ex = count($ex);
......@@ -1444,7 +1533,7 @@ class notice_unimarc extends iso2709_record {
$nb_ex_detruit++;
if ($nb_ex_detruit >= $nb_ex and $nb_ex > 0)
$statut = 1;
$statut = static::RECORD_STATUS_DELETED;
return $statut;
}
......@@ -1512,18 +1601,6 @@ class notice_unimarc extends iso2709_record {
}
public function getChampsForces() {
$champ_forces = [];
for($i=0; $i < count($this->champs_forces); $i++) {
$champ = $this->get_subfield($this->champs_forces[$i]);
for($j=0; $j < count($champ); $j++) {
$champ_forces["Z" . $this->champs_forces[$i]][] = $champ[$j];
}
}
return $champ_forces;
}
public function getAll() {
$data = $this->get_subfield(200, 'a');
$notice["titre_princ"] = $data[0];
......
......@@ -100,21 +100,29 @@ class KohaPeriodiquesMarieClaireTest extends KohaPeriodiquesTestCase {
/** @test */
public function shouldHaveInserted21Records() {
$this->assertEquals(21, count(Class_Notice::findAll()));
public function loadNoticeShouldHaveInserted22Records() {
$this->assertEquals(22, count(Class_Notice::findAll()));
}
/** @test */
public function typeDocShouldBeTwo() {
$this->assertEquals(2,
public function typeDocShouldBePerTitle() {
$this->assertEquals('per_title',
$this->notice_integration->noticeToDBEnreg($this->notice_data)['type_doc']);
}
/** @test */
public function shouldHaveInserted51Items() {
$this->assertEquals(51, count(Class_Exemplaire::findAll()));
public function loadNoticeShouldHaveInserted52Items() {
$this->assertEquals(52, count(Class_Exemplaire::findAll()));
}
/** @test */
public function firstRecordItemThatIsPeriodicTitleShouldBeOneDash139179() {
$this->assertEquals('1-139179',
Class_Notice::findFirstBy(['type_doc' => 'per_title'])
->getFirstExemplaire()->getCodeBarres());
}
......@@ -136,7 +144,7 @@ class KohaPeriodiquesMarieClaireTest extends KohaPeriodiquesTestCase {
/** @test */
public function lastTitle411dollarOShouldBeEmpty() {
$this->assertNull($this->getSubfieldAt('461', 'o', 2, $this->marcDumpFor($this->unimarcAt(20))));
$this->assertNull($this->getSubfieldAt('461', 'o', 0, $this->marcDumpFor($this->unimarcAt(20))));
}
......@@ -158,7 +166,7 @@ class KohaPeriodiquesMarieClaireTest extends KohaPeriodiquesTestCase {
public function firstNumberShouldBe725() {
$this->assertEquals(
'725',
$this->getSubfieldAt('461', 'v', 1, $this->marcDumpFor($this->unimarcAt(0))));
$this->getSubfieldAt('461', 'v', 0, $this->marcDumpFor($this->unimarcAt(0))));
}
......@@ -166,7 +174,15 @@ class KohaPeriodiquesMarieClaireTest extends KohaPeriodiquesTestCase {
public function firstSubtitleShouldBeJanvier2013() {
$this->assertEquals(
'Janvier 2013',
$this->getSubfieldAt('461', 'o', 2, $this->marcDumpFor($this->unimarcAt(0))));
$this->getSubfieldAt('461', 'o', 0, $this->marcDumpFor($this->unimarcAt(0))));
}
/** @test */
public function subfield461Dollar9ShouldContains001FromTitleRecord139179() {
$this->assertEquals(
'139179',
$this->getSubfieldAt('461', '9', 0, $this->marcDumpFor($this->unimarcAt(1))));
}
......@@ -174,7 +190,7 @@ class KohaPeriodiquesMarieClaireTest extends KohaPeriodiquesTestCase {
public function firstSetNameShouldBeMarieClaire() {
$this->assertEquals(
'MARIE CLAIRE',
$this->getSubfieldAt('461', 't', 0, $this->marcDumpFor($this->unimarcAt(0))));
$this->getSubfieldAt('461', 't', 0, $this->marcDumpFor($this->unimarcAt(1))));
}
......@@ -244,14 +260,30 @@ class KohaPeriodiquesMarieClaireWithoutDoubleSearchTest extends KohaPeriodiquesT
/** @test */
public function shouldHaveInserted21RecordsToo() {
$this->assertEquals(21, count(Class_Notice::findAll()));
public function shouldHaveInserted22RecordsToo() {
$this->assertEquals(22, count(Class_Notice::findAll()));
}
/** @test */
public function shouldHaveInserted52Items() {
$this->assertCount(52, Class_Exemplaire::findAll());
}
}
class KohaPeriodiquesIdeatTest extends KohaPeriodiquesTestCase {
public function setUp() {