-
Laurent authored367f3acd
classe_notice_integration.php 47.01 KiB
<?php
/**
* Copyright (c) 2012, Agence Française Informatique (AFI). All rights reserved.
*
* BOKEH 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).
*
* BOKEH 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 BOKEH; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
require_once 'Class/Isbn.php';
require_once 'classe_indexation.php';
require_once 'classe_unimarc.php';
require_once 'classe_codif_matiere.php';
require_once 'classe_codif_langue.php';
require_once 'classe_profil_donnees.php';
require_once 'classe_communication.php';
class notice_integration {
const
RECORD_REJECT = 0,
RECORD_INSERT = 1,
RECORD_DELETE = 2,
RECORD_FULLUPDATE = 3,
RECORD_UPDATE = 4,
RECORD_RENEW = 5,
RECORD_UPGRADE = 6,
RECORD_SUCCINCT = 7,
STATUS_NOTFOUND = 'non trouvée';
private $id_profil; // Id du profil de données initialisé
private $format; // Format de fichier 0=unimarc
private $id_article_periodique; // Mode d'indentification des articles de periodiques
private $type_doc_force; // Type de document forcé dans maj_auto
private $analyseur; // Instance de la classe qui découpe la notice
private $indexation; // Instance de la classe d'indexation
private $id_bib; // Bibliotheque pour qui on integre @deprecated, see below setParamsIntegration
private $id_int_bib; // Intégration programmée pour qui on integre
private $type_operation; // Maj ou suppression
private $notice; // Structure notice en cours de traitement
private $qualite_bib; // Code qualite de la bib
private $sigb; // Sigb de la bib
private $statut; // Statut de la notice traitee
public $libStatut = [self::RECORD_REJECT => "Rejetées",
self::RECORD_INSERT => "Créée",
self::RECORD_DELETE => "Supprimée",
self::RECORD_FULLUPDATE => "Mise à jour notice et exemplaires",
self::RECORD_UPDATE => "Mise à jour exemplaires",
self::RECORD_RENEW => "Remplacées",
self::RECORD_UPGRADE => "Homogénéisées",
self::RECORD_SUCCINCT =>"Mises en notices succintes"];
private $erreur; // Message d'erreur notice traitee
private $filtrer_fulltext; // Vient de la variable filtrer_fulltext.
private $identification; // Mode d'identification de la notice
private $notice_sgbd; // Instance unimarc pour notices de la base
private $mode_doublon; // Mode de dédoublonnage (tous identifiants ou clef alpha prioritaire)
private $url_site; // Url d'origine du site opac
private $flag_koha=false; // flag pour réentrance des notices de periodiques koha
/** @category testing */
protected $_service_runner;
protected $_codif_provider;
public function __construct() {
$this->indexation = indexation::getInstance();
$this->filtrer_fulltext = Class_CosmoVar::get("filtrer_fulltext");
$this->mode_doublon = Class_CosmoVar::get("mode_doublon");
$this->notice_sgbd = new notice_unimarc();
}
public function setParamsIntegration($id_bib, $type_operation, $id_profil, $type_doc_force='') {
/**
* $this->id_bib is deprecated, use $this->id_int_bib instead.
* @see http://forge.afi-sa.fr/issues/14279
*/
$this->id_bib = $this->id_int_bib = $id_bib;
$this->type_operation = $type_operation;
$this->type_doc_force = $type_doc_force;
$bib = Class_IntBib::getOrCreate($id_bib);
$this->qualite_bib = $bib->getQualite();
$this->sigb = $bib->getSigb();
$this->id_profil = $id_profil;
$profil = Class_IntProfilDonnees::getOrCreate($id_profil);
$this->id_article_periodique = $profil->getIdArticlePeriodique();
$this->format = $profil->isCustomFileType()
? $profil->getTypeFichier()
: $profil->getFormat();
unset($this->analyseur);
switch($this->format) {
case Class_IntProfilDonnees::FORMAT_UNIMARC:
case Class_IntProfilDonnees::FORMAT_UNIMARC_XML:
$this->analyseur = new notice_unimarc();
break;
case Class_IntProfilDonnees::FORMAT_CG68_ARCHIVES:
require_once("classe_notice_archive_calice.php");
$this->analyseur = new notice_archive_calice();
break;
case Class_IntProfilDonnees::FORMAT_AVENIO:
require_once("classe_notice_avenio.php");
$this->analyseur = new notice_avenio($id_bib);
break;
case Class_IntProfilDonnees::FORMAT_MARC21:
require_once("classe_notice_marc21.php");
$this->analyseur = new notice_marc21();
break;
case Class_IntProfilDonnees::FORMAT_DUBLIN_CORE:
$this->analyseur = new Class_Cosmogramme_Integration_Record_DublinCore();
break;
case Class_IntProfilDonnees::FORMAT_BIBLIONDEMAND:
$this->analyseur = new Class_Cosmogramme_Integration_Record_Bibliondemand();
break;
default:
require_once("classe_notice_ascii.php");
$this->analyseur = new notice_ascii();
break;
}
}
public function traiteNotice($data) {
global $sql;
$id_bib = $this->id_bib;
if(!$this->analyseur)
return false;
$this->statut = static::RECORD_REJECT;
$this->erreur = '';
unset($this->notice);
if(!$this->analyseur->ouvrirNotice($data,$this->id_profil,$this->sigb,$this->type_doc_force)) {
$this->erreur=$this->analyseur->getLastError();
return 0;
}
$this->notice=$this->analyseur->getNoticeIntegration();
if($this->notice['type_doc'] == Class_TypeDoc::LIVRE_NUM) {
$this->ecrireArticlePeriodique();
return;
}
$id_notice = $this->chercheNotice();
if($this->type_operation == 1) {
$this->statut = static::RECORD_DELETE;
if($this->format == Class_IntProfilDonnees::FORMAT_UNIMARC )
$this->supprimerNotice($id_notice,$this->notice["id_origine"]);
else
$this->supprimerExemplaire($id_notice,$this->notice["exemplaires"][0]);
return;
}
if($this->notice["statut"] == 1) {
$this->statut = static::RECORD_DELETE;
$this->supprimerNotice($id_notice,$this->notice["id_origine"]);
return;
}
if($this->notice["type_doc"] == Class_TypeDoc::PERIODIQUE) {
// Periodiques Koha et orphee (1 exemplaire pour chaque numéro)
if(($this->id_article_periodique == Class_IntProfilDonnees::SERIAL_FORMAT_KOHA
or $this->id_article_periodique == Class_IntProfilDonnees::SERIAL_FORMAT_ORPHEE)
and $this->flag_koha == false) {
$this->flag_koha = true;
$ret = $this->traitePeriodiquesKoha();
$this->flag_koha = false;
return $ret;
}
// pergame : on efface tous les articles
if($this->id_article_periodique == Class_IntProfilDonnees::SERIAL_FORMAT_PERGAME) {
$clef_chapeau = $this->notice['clef_chapeau'];
$clef_numero = addslashes($this->notice['tome_alpha']);
$date = dateDuJour(0);
Class_Notice_SerialArticles::deleteBy(['clef_chapeau' => $clef_chapeau,
'clef_numero' => $clef_numero,
'date_maj not' => $date]);
}
// opsys indexpresse : on cree les articles manquants
if($this->id_article_periodique == Class_IntProfilDonnees::SERIAL_FORMAT_ALOES_INDEXPRESS
and $this->notice['articles_periodiques']) {
$enreg = ["clef_chapeau"=>$this->notice["articles_periodiques"]["clef_chapeau"],
"clef_numero"=>$this->notice["articles_periodiques"]["clef_numero"],
"date_maj"=>date("Y-m-d")];
foreach($this->notice["articles_periodiques"]["articles"] as $id_unimarc) {
$clef_unimarc = intval($id_unimarc);
if(!$clef_unimarc) {
$this->notice["warnings"][] = ["Identifiant article de périodique incorrect",
$id_unimarc];
continue;
}
$existe = $sql->fetchOne("select count(*) from notices_articles where clef_unimarc='$clef_unimarc'");
if($existe){
unset($enreg["clef_unimarc"]);
$sql->update("update notices_articles set @SET@ where clef_unimarc='$clef_unimarc'",$enreg);
}
else {
$enreg["clef_unimarc"]=$clef_unimarc;
$sql->insert("notices_articles",$enreg);
}
}
}
}
if(!$id_notice) {
$this->notice["qualite"] = $this->qualite_bib;
$id_notice = $this->insertNotice();
if(!$id_notice)
return ;
else
$this->statut = static::RECORD_INSERT;
} else {
$this->updateNoticeWithId($id_notice);
}
$this->ecrireExemplaires($id_notice);
return $this->notice;
}
protected function updateNoticeWithId($id_notice) {
if(($this->identification["statut"] == "clef_alpha") && $this->flag_koha)
return $id_notice;
return $this->updateNotice($id_notice,$this->qualite_bib);
}
public function traiteHomogene($id_notice, $isbn, $ean, $id_commerciale, $no_request) {
global $sql;
// Appel du service
$args["isbn"]=$isbn;
$args["ean"]= $ean;
$args["id_commerciale"]=$id_commerciale;
$args["no_request"]=$no_request;
$ret=communication::runService(4,$args);
// Formatter la reponse
$ret["timeout"]=10;
// Statut not found : Mise a jour nombre de retries
if ($ret["statut_z3950"] == '1') {
$notice = Class_Notice::find($id_notice);
$retry = $notice->getZ3950Retry() + 1;
$notice->setZ3950Retry($retry)->save();
}
// Statut ok : on remplace la notice
if(!$this->analyseur) $this->analyseur=new notice_unimarc();
if($ret["statut_z3950"] > "1")
{
$this->analyseur->ouvrirNotice($ret["unimarc"],
$args['isbn']
? profil_donnees::HOMOGENIZATION_ISBN
: profil_donnees::HOMOGENIZATION_EAN);
$this->notice=$this->analyseur->getNoticeIntegration();
$qualite=getVariable("homogene_code_qualite");
$this->updateNotice($id_notice,$qualite);
}
return $ret;
}
public function traiteSuccinte($enreg) {
global $sql;
extract($enreg);
/**
* $this->id_bib is deprecated, use $this->id_int_bib instead.
* @see http://forge.afi-sa.fr/issues/14279
*/
$this->id_bib = $this->id_int_bib = $id_bib;
$notice = unserialize($data);
$this->notice = $notice;
// On la cherche dans la base
if ($id_notice = $this->chercheNotice()) {
$this->handleSuccinteLocaly($notice, $id_notice, $sql);
$ret["statut"]=4;
}
// On cherche sur les serveurs z3950
else {
$args["isbn"]=$notice["isbn"];
$args["ean"]= $notice["ean"];
$args["id_commerciale"]=$notice["id_commerciale"];
$args["no_request"]=getVariable("Z3950_cache_only");
$ret = $this->getServiceRunner()->run(4, $args);
// Statut ok : on remplace la notice
if (!$this->analyseur)
$this->analyseur = new notice_unimarc();
if ($ret["statut_z3950"] > "1") {
$this->analyseur->ouvrirNotice($ret["unimarc"],1);
$this->notice=$this->analyseur->getNoticeIntegration();
$this->notice["id_origine"]=$notice["id_origine"];
$this->notice["statut_exemplaires"] = $notice["statut_exemplaires"];
$this->notice["exemplaires"] = $notice["exemplaires"];
$this->notice["qualite"]=getVariable("homogene_code_qualite");
if ($this->notice["titre_princ"]
&& $id_notice = $this->insertNotice()) {
$this->ecrireExemplaires($id_notice);
$ret["statut"] = 1;
}
$ret["statut"] = 0;
} else {
$ret["statut"] = 0;
}
}
// Mise a jour
$ret["id_notice"]=$id_notice;
$ret["id_bib"]=$id_bib;
$ret["isbn"]=$notice["isbn"];
$ret["ean"]= $notice["ean"];
$ret["id_commerciale"] = $notice["id_commerciale"];
$query = ($id_notice)
? "delete from notices_succintes where id=$id"
: "Update notices_succintes set z3950_retry = z3950_retry +1 Where id=$id";
$sql->execute($query);
return $ret;
}
protected function handleSuccinteLocaly($succinte, $id_notice, $sql) {
$unimarc=$sql->fetchOne("select unimarc from notices where id_notice=$id_notice");
$this->notice_sgbd->ouvrirNotice($unimarc,0);
$this->notice=$this->notice_sgbd->getNoticeIntegration();
$this->notice["id_origine"]=$succinte["id_origine"];
$this->notice["statut_exemplaires"] = $succinte["statut_exemplaires"];
$this->notice["exemplaires"] = $succinte["exemplaires"];
$this->updateNotice($id_notice, $this->notice["qualite"]);
$this->ecrireExemplaires($id_notice);
}
/**
* 1 item by number
*/
private function traitePeriodiquesKoha() {
if (0 == count($this->notice['exemplaires']))
return [];
$number_map = [3 => 'v', 4 => '6'];
if (!array_key_exists($this->id_article_periodique, $number_map))
return [];
$champ_numero = $number_map[$this->id_article_periodique];
$unimarc = $this->notice['unimarc'];
foreach($this->notice['exemplaires'] as $exemplaire) {
$this->notice_sgbd->ouvrirNotice($unimarc,
$this->id_profil,
$this->sigb,
$this->type_doc_force);
$champs = unserialize($exemplaire['zone995']);
$table_champs = [];
$numero = '';
foreach($champs as $champ) {
$table_champs[] = [$champ['code'], $champ['valeur']];
if ($champ['code'] != $champ_numero)
continue;
if (preg_match('/(\d+)/', $champ['valeur'], $numbers)) {
$numero = $numbers[0];
$complement_titre = trim(substr($champ['valeur'], strpos($champ['valeur'], $numero) + strlen($numero)));
} else {
$numero = $champ['valeur'];
}
}
$this->notice_sgbd->add_field('461', '11', 't' . $this->notice['titre_princ']);
$this->notice_sgbd->add_field('461', '11', 'v' . $numero);
if ($complement_titre)
$this->notice_sgbd->add_field('461', '11', 'o' . $complement_titre);
$this->notice_sgbd->add_field('995', ' ', $table_champs);
$this->notice_sgbd->update();
$data = $this->notice_sgbd->getFullRecord();
$this->traiteNotice($data);
}
}
// ----------------------------------------------------------------
// Retourne l'url d'origine du site (ex: http://opac3.pergame.net/)
// ----------------------------------------------------------------
private function getUrlSite() {
if (isset($this->url_site))
return $this->url_site;
$adresse=getVariable("url_site");
if(strtolower(substr($adresse,0,7)) !="http://") $adresse="http://".$adresse;
if(substr($adresse,-1,1)!="/") $adresse.="/";
return $this->url_site = $adresse;
}
private function chercheNotice() {
$this->identification = ['statut' => static::STATUS_NOTFOUND];
$double = new Class_Notice_DoubleFinder($this->notice,
$this->id_int_bib,
$this->id_profil);
if (!$double->find())
return '';
$matched_on = $double->getMatchedCriteria();
$this->identification['statut'] = $matched_on;
$this->identification[$matched_on] = $double->getId();
return $double->getId();
}
private function insertNotice() {
if(!$this->notice["statut_exemplaires"]["nb_ex"]) {
$this->erreur = "notice sans exemplaire";
$this->statut = static::RECORD_REJECT;
return false;
}
if(!$this->notice["titre_princ"]) {
if($this->notice["isbn"] or $this->notice["ean"] or $this->notice["id_commerciale"]) {
$id_bib=$this->id_bib;
$data=serialize($this->notice);
Class_NoticeSuccincte::newInstance(['id_bib' => $this->id_bib,
'data' => serialize($this->notice)])
->save();
$this->statut = static::RECORD_SUCCINCT;
return false;
}
if($this->format == Class_IntProfilDonnees::FORMAT_UNIMARC or $this->format == Class_IntProfilDonnees::FORMAT_CG68_ARCHIVES)
$this->erreur = "pas de titre principal";
else
$this->erreur = "Aucun identifiant valide";
$this->statut = static::RECORD_REJECT;
return false;
}
$this->traiteFacettes();
$notice = Class_Notice::newInstance($this->noticeToDBEnreg());
$notice->save();
$this->statut = static::RECORD_INSERT;
return $notice->getId();
}
public function noticeToDBEnreg() {
return ["type_doc" => $this->notice["type_doc"],
"alpha_titre" => $this->notice["alpha_titre"],
"alpha_auteur" => $this->notice["alpha_auteur"],
"titres" => $this->indexation->getfullText(array_merge($this->notice["titres"],
[$this->notice["clef_chapeau"],
$this->notice["tome_alpha"]])),
"auteurs" => $this->indexation->getfullText($this->_getFulltextAuthors()),
"editeur" => $this->indexation->getfullText($this->notice["editeur"]),
"collection" => $this->indexation->getfullText($this->notice["collection"]),
"matieres" => $this->indexation->getfullText($this->_getFulltextTopics()),
"dewey" => $this->indexation->getfullText($this->notice["full_dewey"]),
"facettes" => $this->notice["facettes"],
"isbn" => $this->notice["isbn"],
"ean" => $this->notice["ean"],
"id_commerciale" => $this->notice["id_commerciale"],
"clef_alpha" => $this->notice["clef_alpha"],
"clef_chapeau" => $this->notice["clef_chapeau"],
"clef_oeuvre" => $this->notice["clef_oeuvre"],
"tome_alpha" => $this->notice["tome_alpha"],
"annee" => $this->notice["annee"],
"qualite" => $this->notice["qualite"],
"exportable" => $this->notice["exportable"],
"cote" => $this->notice["cote"],
"unimarc" => $this->notice['unimarc'],
"date_maj" => dateDuJour(2)];
}
protected function _getFulltextAuthors() {
if (!$this->notice['auteurs'])
return $this->notice["200_f"];
return array_merge($this->notice["auteurs"],
$this->notice["auteurs_renvois"],
$this->_getCodifAuteurRenvois());
}
protected function _getCodifAuteurRenvois() {
$see_also = [];
foreach($this->notice['auteurs'] as $author) {
if (($codif = $this->_getCodifAuteur($author))
&& $codif->hasMotsRenvois())
$see_also[] = $codif->getMotsRenvois();
}
return $see_also;
}
protected function _getFulltextTopics() {
if (!$this->notice['matieres'])
return ;
return array_merge($this->notice["matieres"],
$this->notice["matieres_renvois"],
$this->_getCodifTopicsRenvois());
}
protected function _getCodifTopicsRenvois() {
$see_also = [];
foreach($this->notice['matieres'] as $topic) {
if (($codif = $this->_getCodifTopic($topic))
&& $codif->hasMotsRenvois())
$see_also[] = $codif->getMotsRenvois();
}
return $see_also;
}
public function updateNotice($id_notice, $qualite) {
if (!$existing_notice = Class_Notice::find($id_notice))
return $id_notice;
$this->notice["qualite"] = $existing_notice->getQualite();
$this->notice["facette"] = $existing_notice->getFacettes();
// Test qualite
if ($qualite >= $this->notice["qualite"]) {
$this->notice["qualite"] = $qualite;
$this->statut = static::RECORD_RENEW;
} else {
$this->statut = static::RECORD_UPDATE;
}
// Si la notice n'a pas de titre on substitue par celle de la base en forcant a une qualite inferieure
if (!$this->notice['titre_princ'])
$this->statut = static::RECORD_UPDATE;
if (in_array($this->format,
[ Class_IntProfilDonnees::FORMAT_DUBLIN_CORE,
Class_IntProfilDonnees::FORMAT_BIBLIONDEMAND]))
return $this->_realUpdate($existing_notice);
// Zones forcees
$this->notice_sgbd
->ouvrirNotice($existing_notice->getUnimarc(),
$this->id_profil,
0,
'',
false);
$champs_forces = $this->notice_sgbd->getChampsForces();
$id_origine = $this->notice["id_origine"];
$qualite = $this->notice["qualite"];
$statut_exemplaires = $this->notice["statut_exemplaires"];
$exemplaires = $this->notice["exemplaires"];
$warnings = $this->notice["warnings"];
// Si la notice de la base est de meilleure qualite on la prend
if ($this->statut == static::RECORD_RENEW) {
$full_unimarc = array_key_exists('unimarc_with_items', $this->notice)
? $this->notice['unimarc_with_items']
: $this->notice['unimarc'];
$this->notice_sgbd
->ouvrirNotice($full_unimarc, $this->id_profil, 0, '', false);
}
$this->updateForcedZones($champs_forces, $this->notice["champs_forces"]);
$this->notice = $this->notice_sgbd->getNoticeIntegration();
$this->notice["statut_exemplaires"] = $statut_exemplaires;
$this->notice["exemplaires"] = $exemplaires;
$this->notice["warnings"] = $warnings;
$this->notice["qualite"] = $qualite;
$this->notice["id_origine"] = $id_origine;
if ($this->statut == static::RECORD_UPDATE)
return $id_notice;
return $this->_realUpdate($existing_notice);
}
protected function _realUpdate($record) {
$this->traiteFacettes($record->getId());
$record
->updateAttributes($this->noticeToDBEnreg())
->save();
return $record->getId();
}
protected function updateForcedZones($existing, $current) {
if (!$existing || $existing == $current)
return;
$new = ($current) ?
array_merge_recursive($existing, $current) :
$existing;
// Fusion des champs forces
$champs_forces = [];
foreach ($new as $zone => $valeurs) {
$zone = substr($zone, 1); // on retire le Z qui sert au array_merge_recursive
$this->notice_sgbd->delete_field($zone); // On supprime l'ancienne zone
// si champ matiere on dedoublonne directement
if ('6' == substr($zone, 0, 1)) {
$champs = array_unique($valeurs);
$champs_forces[$zone] = $champs;
continue;
}
// sinon on decoupe les elements on les dedoublonne et on les remet dans 1 seule zone
$champs=array();
foreach($valeurs as $valeur)
$champs = array_merge($champs, $this->notice_sgbd->getValeursBloc($valeur));
$champs = array_unique($champs);
$champs_forces[$zone][] = $this->notice_sgbd->makeZoneByValeurs(substr($valeurs[0],0,2),"a",$champs);
}
// On remet les nouvelles zones
foreach($champs_forces as $zone => $valeurs)
foreach($valeurs as $valeur)
$this->notice_sgbd->add_zone($zone,$valeur);
$this->statut = static::RECORD_FULLUPDATE;
}
// --------------------------------------------------------------------------------
// Suppression de notice (ne supprime pas l'enreg notice)
// --------------------------------------------------------------------------------
private function supprimerNotice($id_notice,$id_origine) {
foreach (['id_notice' => $id_notice,
'id_origine' => $id_origine] as $key => $value) {
if ($exemplaires = Class_Exemplaire::findAllBy([$key => $value,
'id_bib' => $this->id_bib])) {
foreach ($exemplaires as $exemplaire)
$exemplaire->delete();
return;
}
}
$this->statut = static::RECORD_REJECT;
$this->erreur="notice à supprimer non reconnue";
return false;
}
public function ecrireExemplaires($id_notice) {
$code_barres = [];
$exemplaires = [];
foreach ($this->notice['exemplaires'] as $ex) {
$code_barres []= $ex['code_barres'];
if ($ex["activite"]=="d")
continue;
$exemplaire = Class_Exemplaire::newInstance($ex)
->setIdNotice($id_notice)
->setIdOrigine($this->notice['id_origine'])
->setIdBib($this->id_bib)
->setIdIntBib($this->id_int_bib);
/**
* @see http://forge.afi-sa.fr/issues/14279
* we can have one file with items for different libraries. We use "annexe" codification to find
* to put each item in the library it belongs to.
**/
if ($exemplaire->hasAnnexe() && ($annexe = CodifAnnexeCache::getInstance()->find($ex['annexe']))) {
$exemplaire->setIdBib($annexe->getIdBib());
}
$exemplaires []= $exemplaire;
}
if (!empty($code_barres)) {
$unicite_codes_barres = getVariable('unicite_code_barres');
$delete_duplicates_args = ($unicite_codes_barres == '1') ? [] : ['id_int_bib' => $this->id_int_bib];
$delete_duplicates_args['id_notice'] = $id_notice;
$delete_duplicates_args['code_barres'] = $code_barres;
Class_Exemplaire::deleteBy($delete_duplicates_args);
}
foreach($exemplaires as $exemplaire)
$exemplaire->save();
if($record = Class_Notice::find($id_notice))
$record->setDateMaj(dateDuJour(2))->save();
Class_Exemplaire::clearCache();
Class_Notice::clearCache();
}
public function supprimerExemplaire($id_notice,$ex) {
if(!$id_notice) {
$this->statut = static::RECORD_REJECT;
$this->erreur="notice de l'exemplaire à supprimer non trouvée";
return false;
}
$exemplaires = Class_Exemplaire::findAllBy(['id_notice' => $id_notice,
'id_int_bib' => $this->id_int_bib,
'code_barres' => $ex['code_barres']]);
if(!$exemplaires) {
$this->statut = static::RECORD_REJECT;
$this->erreur="code-barres à supprimer non trouvé";
return false;
}
$notice = Class_Notice::find($id_notice);
foreach($exemplaires as $exemplaire) {
$notice->removeExemplaire($exemplaire);
}
$notice->setDateMaj(dateDuJour(2))
->save();
}
public function traiteFacettes($id_notice=null) {
$facettes = [];
// Tags
if ($id_notice)
foreach (Class_CodifTags::findForRecord($id_notice) as $tag)
$facettes[] = $tag->asFacet();
// Doc type
if($type_doc = $this->notice['infos_type_doc']) {
if($code_type_doc = $type_doc['code']){
$facettes[] = 'T'.$code_type_doc;
}
}
// Dewey
$this->notice["full_dewey"] = '';
if($this->notice["dewey"])
{
foreach($this->notice["dewey"] as $indice)
{
if (!$dewey = Class_CodifDewey::find($indice)) {
$dewey = Class_CodifDewey::newInstance(['id_dewey' => $indice,
'libelle' => '']);
$dewey->save();
}
$this->notice["full_dewey"] .= $dewey->getLibelle()." ";
$facettes[]="D".$indice;
}
}
// Pcdm4
if($this->notice["pcdm4"]) {
$indice = $this->notice["pcdm4"];
if (!$pcdm4 = Class_CodifPcdm4::find($indice)) {
$pcdm4 = Class_CodifPcdm4::newInstance(['id_pcdm4' => $indice,
'libelle' => '']);
$pcdm4->save();
}
$this->notice["full_dewey"] .= $pcdm4->getLibelle()." ";
$facettes[]="P".$indice;
}
// Thesaurus
if($thesauri=$this->notice["thesauri"])
{
foreach ($thesauri as $thesaurus) {
if (empty($thesaurus))
continue;
if ($thesaurus->getLibelle())
$this->notice["full_dewey"] .= $thesaurus->getLibelle().' ';
$facettes[]="H".$thesaurus->getIdThesaurus();
}
}
// Auteurs
if($this->notice["auteurs"])
{
foreach($this->notice["auteurs"] as $auteur) {
if ($facette_auteur= $this->getFacetteAuteur($auteur))
$facettes []= $facette_auteur;
}
}
// Matieres
if($this->notice["matieres"]) {
foreach($this->notice["matieres"] as $matiere) {
if (!$codif_matiere = $this->_getCodifTopic($matiere)) continue;
$facettes[]="M".$codif_matiere->getId();
}
}
// Centres d'interet
if ($this->notice["interet"]) {
foreach($this->notice["interet"] as $interet) {
if (!$code_alpha = $this->indexation->alphaMaj($interet))
continue;
if (!$centre_interet = Class_CodifCentreInteret::findFirstBy(['code_alpha' => $code_alpha])) {
$centre_interet = Class_CodifCentreInteret::newInstance(['libelle' => $interet,
'code_alpha' => $code_alpha]);
$centre_interet->save();
}
$facettes[] = "F" . $centre_interet->getId();
$this->notice["full_dewey"] .= $interet." ";
}
}
// Langues
if($this->notice["langues"])
{
foreach($this->notice["langues"] as $langue)
{
if (Class_CodifLangue::find($langue))
$facettes[]="L".$langue;
else
$this->notice["warnings"][]=array("Code langue non reconnu",$langue);
}
}
// genres
if(isset($this->notice["genres"]) && count($this->notice["genres"]))
{
foreach(array_filter($this->notice["genres"]) as $genre)
{
$facettes[]="G".$genre." ";
if ($codif_genre = Class_CodifGenre::find($genre))
$this->notice["full_dewey"].=$codif_genre->getLibelle();
}
}
// emplacements
if (isset($this->notice["emplacements"]) && count($this->notice['emplacements']))
$facettes = array_merge($facettes, array_map(function($e) { return "E$e";}, $this->notice['emplacements']));
// Maj enreg facette
$this->notice["facettes"] = trim(implode(' ', array_unique($facettes)));
}
public function getFacetteAuteur($auteur) {
return ($codif = $this->_getCodifAuteur($auteur))
? 'A' . $codif->getId() : '';
}
protected function _getCodifAuteur($auteur) {
return $this->getCodifProvider()->getAuthor($auteur);
}
protected function _getCodifTopic($topic) {
return $this->getCodifProvider()->getTopic($topic);
}
// --------------------------------------------------------------------------------
// Ecrit une notice : article de périodique
// --------------------------------------------------------------------------------
private function ecrireArticlePeriodique() {
if( 1 == $this->notice["statut"])
return $this->deleteRecordArticles();
$title_key = hash('crc32b', $this->notice['titre_princ']);
$unimarc_key = $this->notice["clef_unimarc"]
? $this->notice["clef_unimarc"]
: $title_key;
$article_from_record = Class_Notice_SerialArticles::newInstance(['clef_chapeau' => $this->notice["clef_chapeau"],
'clef_numero' => $this->notice["clef_numero"],
'clef_unimarc' => $unimarc_key,
'unimarc' => $this->notice['unimarc'],
'date_maj' => dateDuJour(0),
'qualite' => $this->qualite_bib,
'clef_article' => $this->notice['clef_article']]);
if(!$this->notice['clef_unimarc']) {
$common_attribs = ['clef_chapeau' => $this->notice['clef_chapeau'],
'clef_numero' => $this->notice['clef_numero']];
if(!$article = Class_Notice_SerialArticles::findFirstBy(array_merge($common_attribs, ['clef_unimarc' => $title_key])))
$article = Class_Notice_SerialArticles::findFirstBy(array_merge($common_attribs, ['clef_article' => $this->notice['clef_article'],
'clef_unimarc' => '']));
return $this->updateOrInsertArticle($article, $article_from_record);
}
if ($article = Class_Notice_SerialArticles::findFirstBy(['clef_unimarc' => $this->notice['clef_unimarc']])) {
$article_from_record->setClefChapeau($article->getClefChapeau());
$article_from_record->setClefNumero($article->getClefNumero());
return $this->updateOrInsertArticle($article, $article_from_record);
}
}
protected function updateOrInsertArticle($article, $article_from_record) {
return $article
? $this->updateArticleWith($article, $article_from_record)
: $this->insertArticleWith($article_from_record);
}
protected function insertArticleWith($article_from_record) {
Class_Notice_SerialArticles::newInstance($article_from_record->toArray())->save();
Class_Notice_SerialArticles::clearCache();
$this->statut = self::RECORD_INSERT;
return;
}
protected function updateArticleWith($article, $article_from_record) {
if($enreg["qualite"] >= $article->getQualite()) {
$article->updateAttributes($article_from_record->toArray())->save();
$this->statut = self::RECORD_RENEW;
}
}
protected function deleteRecordArticles() {
global $sql;
$this->statut = self::RECORD_DELETE;
if($this->notice["clef_unimarc"])
$controle = $sql->execute("delete from notices_articles where clef_unimarc='$clef_unimarc'");
else
$controle = $sql->execute("delete from notices_articles where clef_chapeau='$clef_chapeau' and clef_numero='$clef_numero' and clef_article='$clef_article'" );
if(!$controle) {
$this->statut = static::RECORD_REJECT;
$this->erreur = "notice à supprimer non reconnue";
}
}
// --------------------------------------------------------------------------------
// Recupere titre, auteurs, matieres pour 1 article de périodique
// --------------------------------------------------------------------------------
public function getDataArticlePeriodique($unimarc)
{
if(!$unimarc) { $this->erreur="notice sans unimarc"; return false; }
if(!$this->analyseur->ouvrirNotice($unimarc,$this->id_profil,0,"")) { $this->erreur=$this->analyseur->getLastError(); return false; }
$ret["titres"]=$this->analyseur->getTitres();
$ret["auteurs"]=$this->analyseur->getAuteurs();
$ret["matieres"]=$this->analyseur->getMatieres();
return $ret;
}
// --------------------------------------------------------------------------------
// Rend la derniere erreur et les derniers warnings
// --------------------------------------------------------------------------------
public function getLastStatut()
{
$ret["statut"]=$this->statut;
$ret["erreur"]=$this->erreur;
$ret["warnings"]=$this->notice["warnings"];
$ret["identification"]=$this->identification["statut"];
return $ret;
}
// --------------------------------------------------------------------------------
// Rend tout le contenu de la notice
// --------------------------------------------------------------------------------
public function getNotice()
{
if(!$this->notice) $this->notice=array();
return $this->notice;
}
// ----------------------------------------------------------------
// Test d'une notice unimarc
// ----------------------------------------------------------------
public function testNotice($data,$piege_numero="",$piege_titre="",$piege_code_barres="",$piege_isbn="",$piege_type_doc="")
{
global $sql;
// lire la notice
$this->analyseur->ouvrirNotice($data,$this->id_profil,$this->sigb);
$notice=$this->analyseur->getNoticeIntegration();
// tracedebug($notice,true); //++++++++++++++++++++++++++++++++++++++++++++++++++++
// Titre principal
$ret["titre"]=$notice["titre_princ"];
// Gestion des pieges
if($piege_numero){$ret["statut"]=0; return $ret;}
if($piege_titre >"" and $this->indexation->codeAlphaTitre($ret["titre"]) == $this->indexation->codeAlphaTitre($piege_titre)) {$ret["statut"]=1; return $ret;}
if($piege_code_barres > "" and $notice["statut_exemplaires"]["nb_ex"]>0)
{
foreach($notice["exemplaires"] as $ex)
{
if($ex["code_barres"]==$piege_code_barres) {$ret["statut"]=1; return $ret;}
}
}
if($piege_isbn > "" and ($notice["isbn10"] == $piege_isbn or $notice["isbn13"] == $piege_isbn)) {$ret["statut"]=1; return $ret;}
if($piege_type_doc >"" and $notice["infos_type_doc"]["code"]==$piege_type_doc) {$ret["statut"]=1; return $ret; }
if($piege_titre > "" or $piege_code_barres > "" or $piege_isbn > "" or $piege_type_doc >""){$ret["statut"]=0; return $ret;}
// Type de document
$td=$notice["infos_type_doc"];
if(!$td["code"]){ $statut=1; $libelle=" code non reconnu"; $ret["type_doc"] = Class_TypeDoc::UNKNOWN; }
else {$statut=0; $libelle=$td["code"]." - ".$td["libelle"]; $ret["type_doc"]=$td["code"]; }
$ret["lig"][]=array($statut,"Type de document", $libelle,$td["infos"]);
// Statut : 0=notice vivante 1=à détruire
$lig[0]=0;
$lig[1]="Statut";
$lig[2]="ok";
if($notice["statut"]==1)
{
$lig[0]=3;
$lig[2]='<font color="purple">Notice à supprimer</font>';
}
else if($td["code"]!="100")
{
if($ret["titre"] == "") {$lig[0]=2; $lig[2]="pas de titre principal";$ret["lig"][]=$lig;}
if($notice["statut_exemplaires"]["nb_ex"]==0)
{
$lig[0]=2;
$lig[2]="pas de zone 995";
}
else
{
if($notice["statut_exemplaires"]["codes_barres"]==0) {$lig[0]=1; $lig[2]="code-barres non trouvé";}
if($notice["statut_exemplaires"]["cotes"]==0) {$lig[0]=1; $lig[2] ="cote non trouvée";}
if($notice["exportable"]==false)$lig[3]='<font color="purple">notice non libre de droits</font>'; else $lig[3]="notice libre de droits";
}
}
$ret["lig"][]=$lig;
// articles de periodiques
if($td["code"]== "100")
{
$lig[0]=0;
$lig[1]="titre du numéro";
$lig[2]=$notice["titre_numero"];
$ret["lig"][]=$lig;
$lig[0]=0;
$lig[1]="identifiant 001";
$lig[2]=$notice["info_id"];
$ret["lig"][]=$lig;
}
// tout sauf articles de periodiques
else
{
// exemplaires
$ret["nb_ex"]=$notice["statut_exemplaires"]["nb_ex"];
$lig[0]=0;
$lig[1]="Exemplaires";
$lig[2]=$notice["statut_exemplaires"]["nb_ex"]." ex. actif(s)";
$lig[3]="";
if($notice["statut_exemplaires"]["nb_ex_detruits"] > 0 ) $lig[3]=$notice["statut_exemplaires"]["nb_ex_detruits"]." ex. à supprimer";
$ret["lig"][]=$lig;
// Identifiants (isbn / ean)
$isbn=$this->analyseur->getIsbn();
if(!$isbn) $isbn=$this->analyseur->getEan();
$lig[0]=0;
$lig[1]="Identifiant";
$lig[2]="";
$lig[3]="";
if($isbn["multiple"]==true)
{
$lig[0]=1;
$lig[2]="Isbn multiple";
$lig[3]=$isbn["isbn"];
}
if($isbn["statut"] == 1)
{
$lig[0]=1;
$lig[2]=$isbn["erreur"];
$lig[3]=$isbn["code_brut"];
}
else
{
if($isbn["isbn"]) {$lig[2]="isbn"; $lig[3]=$isbn["isbn"];}
if($isbn["ean"]) {$lig[2]="ean"; $lig[3]=$isbn["ean"];}
}
$ret["lig"][]=$lig;
// Identifiants ID_COMMERCIALE
$lig[0]=0;
$lig[1]="No commercial";
$lig[2]=$notice["id_commerciale"];
$lig[3]="";
$ret["lig"][]=$lig;
}
// Donnes principales
$titre=$this->analyseur->getTitres();
$auteur=$this->analyseur->getAuteurs();
$lig[0]=0;
$lig[1]="Données principales";
$lig[2]="titre(s) : ".count($titre);
$lig[3]="auteur(s) : ".count($auteur);
$ret["lig"][]=$lig;
if($td["code"]!= "100") // tout sauf articles de periodiques
{
// section
$lig[1]="Section";
if(!$notice["sections"]) {$lig[0]=1; $lig[2]="non reconnue";}
else
{
$lig[0]=0;
$lig[2]="";
foreach($notice["sections"] as $section) $lig[2].=$sql->fetchOne("select libelle from codif_section where id_section=".$section).BR;
}
$lig[3]="";
$ret["lig"][]=$lig;
// genre
$lig[1]="Genre";
if(!$notice["genres"]) {$lig[0]=1; $lig[2]="non reconnu";}
else
{
$lig[0]=0;
$lig[2]="";
foreach($notice["genres"] as $genre) $lig[2].=$sql->fetchOne("select libelle from codif_genre where id_genre=".$genre).BR;
}
$lig[3]="";
$ret["lig"][]=$lig;
// emplacement
$lig[1]="Emplacement";
if(!$notice["emplacements"]) {$lig[0]=1; $lig[2]="non reconnu";}
else
{
$lig[0]=0;
$lig[2]="";
foreach($notice["emplacements"] as $emplacement) $lig[2].=$sql->fetchOne("select libelle from codif_emplacement where id_emplacement=".$emplacement).BR;
}
$lig[3]="";
$ret["lig"][]=$lig;
// Champs forcés
$lig[0]=0;
$lig[1]="Champs à conserver";
$lig[2]="";
$lig[3]="";
if(count($notice["champs_forces"]) > 0)
{
foreach($notice["champs_forces"] as $zone => $champ) $lig[2].= substr($zone,1)." ";
}
else $lig[2]="aucun";
$ret["lig"][]=$lig;
}
// Statut general du retour
$ret["statut"]=0;
for($i=0; $i < count($ret["lig"]); $i++)
{
if($ret["lig"][$i][0]==2)
{
$ret["statut"]=2;
break;
}
if($ret["lig"][$i][0]==1) $ret["statut"]=1;
if($ret["lig"][$i][0]==3 and $ret["statut"] <2) $ret["statut"]=3;
}
return $ret;
}
// ----------------------------------------------------------------
// Analyse de synthese d'une notice unimarc
// ----------------------------------------------------------------
public function syntheseNotice($data)
{
global $sql;
$this->analyseur->ouvrirNotice($data,$this->id_profil,$this->sigb);
$notice=$this->analyseur->getNoticeIntegration();
// Notice à supprimer
if($notice["statut"]==1) {$ret["statut"]="suppr"; return $ret;}
// Notice rejetee
$ret["statut"]="rejet";
if(!$notice["titre_princ"]) {$ret["rejet"]="notice sans titre"; return $ret;}
if($notice["type_doc"] != Class_TypeDoc::LIVRE_NUM and !$notice["statut_exemplaires"]["nb_ex"]) {$ret["rejet"]="notice sans exemplaire"; return $ret;}
// Warnings
$ret["statut"]="warning";
if($notice["type_doc"] != Class_TypeDoc::LIVRE_NUM)
{
if(!$notice["statut_exemplaires"]["codes_barres"]) $ret["warnings"][]="code-barres non trouvé";
if(!$notice["statut_exemplaires"]["cotes"]) $ret["warnings"][]="cote non trouvée";
}
if(!$notice["type_doc"])$ret["warnings"][]="Type de document non reconnu";
// Type de doc
if($notice["type_doc"]) $ret["type_doc"]=$notice["infos_type_doc"]["libelle"];
// Identifiants (isbn / ean)
if($notice["type_doc"] != Class_TypeDoc::LIVRE_NUM)
{
$isbn=$this->analyseur->getIsbn();
if(!$isbn) $isbn=$this->analyseur->getEan();
if($isbn["multiple"]==true) $ret["warnings"][]="Isbn multiple";
if($isbn["statut"] == 1) $ret["warnings"][]="ISBN ou EAN incorrect";
if($isbn["isbn"]) $ret["identifiant"]="ISBN identifié";
elseif($isbn["ean"]) $ret["identifiant"]="EAN identifié";
else $ret["identifiant"]="Aucun identifiant";
// Genres
if($notice["genres"])
{
foreach($notice["genres"] as $genre) $ret["genres"][]=$sql->fetchOne("Select libelle from codif_genre where id_genre='$genre'");
}
else $ret["warnings"][]="Code genre non reconnu";
// Sections
if($notice["sections"])
{
foreach($notice["sections"] as $section) $ret["sections"][]=$sql->fetchOne("Select libelle from codif_section where id_section='$section'");
}
else $ret["warnings"][]="Code section non reconnu";
// Emplacements
if($notice["emplacements"])
{
foreach($notice["emplacements"] as $emplacement) $ret["emplacements"][]=$sql->fetchOne("Select libelle from codif_emplacement where id_emplacement='$emplacement'");
}
else $ret["warnings"][]="Code emplacement non reconnu";
// Langues
if($notice["langues"])
{
foreach($notice["langues"] as $langue)
{
$controle=$sql->fetchOne("Select libelle from codif_langue where id_langue='$langue'");
if($controle) $ret["langues"][]=$controle;
else $ret["warnings"][]="Code langue non reconnu";
}
}
// Champs forcés
if(count($notice["champs_forces"]) > 0)
{
foreach($notice["champs_forces"] as $zone => $champ) $ret["zones_forcees"][]= substr($zone,1);
}
}
// Notice sans anomalie
if(!$ret["warnings"]) $ret["statut"]="ok";
// Nombre d'exemplaires
$ret["nb_ex"]=$notice["statut_exemplaires"]["nb_ex"];
if($ret["nb_ex"] > 100) $ret["warnings"][]="trop d'exemplaires";
return $ret;
}
// ----------------------------------------------------------------
// Analyse des valeurs distinctes
// ----------------------------------------------------------------
public function valeursDistinctes($champs,$data)
{
$this->analyseur->ouvrirNotice($data,$this->id_profil,$this->sigb);
foreach($champs as $champ)
{
$zone=substr($champ,0,3);
$sous_champ=substr($champ,-1);
$valeur=$this->analyseur->get_subfield($zone,$sous_champ);
if(!$valeur) $valeur[0] = "non renseigné";
foreach($valeur as $code)
{
$ret[$champ][$code]++;
}
}
return $ret;
}
public function analyseurUpdate() {
$this->analyseur->update();
}
public function get_subfield() {
return call_user_func_array([$this->analyseur, 'get_subfield'], func_get_args());
}
protected function getServiceRunner() {
return null != $this->_service_runner
? $this->_service_runner : new Service_Runner();
}
/** @category testing */
public function setServiceRunner($runner) {
$this->_service_runner = $runner;
return $this;
}
public function getStatut() {
return $this->statut;
}
protected function getCodifProvider() {
if (null == $this->_codif_provider)
$this->_codif_provider = (new Class_Cosmogramme_Integration_CodifProvider)
->setIndexation($this->indexation);
return $this->_codif_provider;
}
protected function _isIncremental() {
return Class_Cosmogramme_Integration::TYPE_OPERATION_INCREMENT == $this->type_operation;
}
/** @category testing */
public function setCodifProvider($provider) {
$this->_codif_provider = $provider;
return $this;
}
}
class Service_Runner {
public function run($type, $args) {
return communication::runService($type, $args);
}
}