From 89c6138f3b74a01f3dd1f5ee5b47cc702959a514 Mon Sep 17 00:00:00 2001
From: Laurent Laffont <llaffont@afi-sa.fr>
Date: Fri, 4 May 2018 16:46:51 +0200
Subject: [PATCH] dev #74958 data profile: remove limitations for items zones.
 Better marc21 import

---
 VERSIONS_WIP/74958                            |  1 +
 .../controllers/DataProfileControllerTest.php |  9 +++-
 .../php/classes/classe_notice_marc21.php      |  2 +
 cosmogramme/php/classes/classe_unimarc.php    | 16 +++---
 .../php/classes/NoticeIntegrationTest.php     | 53 +++++++++++++++++++
 library/Class/IntProfilDonnees.php            | 31 +++++------
 library/Class/ProfilePrefs.php                |  7 +++
 .../Class/ProfileSerializer/UnimarcRecord.php |  1 +
 library/ZendAfi/Form/Cosmo/DataProfile.php    | 53 +++++++++++--------
 9 files changed, 128 insertions(+), 45 deletions(-)
 create mode 100644 VERSIONS_WIP/74958

diff --git a/VERSIONS_WIP/74958 b/VERSIONS_WIP/74958
new file mode 100644
index 00000000000..5174864b15a
--- /dev/null
+++ b/VERSIONS_WIP/74958
@@ -0,0 +1 @@
+ - ticket #74958 : Amélioration de l'intégration de fichiers MARC21
\ No newline at end of file
diff --git a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DataProfileControllerTest.php b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DataProfileControllerTest.php
index 5229a877d6a..814143a8fd7 100644
--- a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DataProfileControllerTest.php
+++ b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/DataProfileControllerTest.php
@@ -223,7 +223,8 @@ class Cosmo_DataProfileControllerEditUnimarcKohaTest extends Cosmo_DataProfileCo
 
   /** @test */
   public function selectTypeFichierShouldContainsRecordsSelected() {
-    $this->assertXPathContentContains('//form//select[@name="type_fichier"]/option[@value="0"][@selected]', 'Notices');
+    $this->assertXPathContentContains('//form//select[@name="type_fichier"]/option[@value="0"][@selected]',
+                                      'Notices');
   }
 
 
@@ -275,6 +276,12 @@ class Cosmo_DataProfileControllerEditUnimarcKohaTest extends Cosmo_DataProfileCo
   }
 
 
+  /** @test */
+  public function itemZoneValueShouldBe995() {
+    $this->assertXPath('//form//input[@name="item_zone"][@value="995"]');
+  }
+
+
   /** @test */
   public function itemCodebarreShouldBePresent() {
     $this->assertXPath('//form//select[@id="champ_code_barres"]/option[@value="f"][@selected]');
diff --git a/cosmogramme/php/classes/classe_notice_marc21.php b/cosmogramme/php/classes/classe_notice_marc21.php
index a4c6c59748f..609e459cf8a 100644
--- a/cosmogramme/php/classes/classe_notice_marc21.php
+++ b/cosmogramme/php/classes/classe_notice_marc21.php
@@ -87,6 +87,7 @@ class notice_marc21 extends notice_unimarc {
     $this->map["741"]="*";
     $this->map["801"]["a"]="b";
     $this->map["995"]="*";
+    $this->map["952"]="*";
     parent::__construct();
   }
 
@@ -254,6 +255,7 @@ class notice_marc21 extends notice_unimarc {
     if ('949' == $champ_code_barres)
       return $this->traiteZone('949', '996');
 
+    $this->traiteZone("952","952");
     $this->traiteZone("995","995");
     return $this->traiteZone('999', '996');
   }
diff --git a/cosmogramme/php/classes/classe_unimarc.php b/cosmogramme/php/classes/classe_unimarc.php
index d4313f1bfdc..0ad0a52b638 100644
--- a/cosmogramme/php/classes/classe_unimarc.php
+++ b/cosmogramme/php/classes/classe_unimarc.php
@@ -348,6 +348,10 @@ class notice_unimarc extends iso2709_record {
     if (!$champ_cote)
       $champ_cote = 'k';
 
+    $item_zone = $this->getProfilNumericAttribute('item_zone');
+    if (!$item_zone)
+      $item_zone = '995';
+
     $champ_section = $this->getProfilNumericAttribute('champ_section');
     $champ_genre = $this->getProfilNumericAttribute('champ_genre');
     $champ_emplacement = $this->getProfilNumericAttribute('champ_emplacement');
@@ -368,7 +372,7 @@ class notice_unimarc extends iso2709_record {
     $codes_barres = false;
     $cotes = false;
     $nb_ex_detruits = 0;
-    $exemplaires = $this->get_subfield('995');
+    $exemplaires = $this->get_subfield($item_zone);
     $nb_ex = 0;
     for ($i=0; $i < count($exemplaires); $i++) {
       $ex = $this->withExemplaireDo(
@@ -377,7 +381,7 @@ class notice_unimarc extends iso2709_record {
                                      $cotes, $nb_ex_detruits, $champs_nouveaute,
                                      $champ_genre, $champ_emplacement,
                                      $champ_annexe, $champ_section, $champ_cote,
-                                     $champ_availability) {
+                                     $champ_availability, $item_zone) {
 
           if ($champ['code'] == $champ_code_barres) {
             $this->setCodeBarre($champ['valeur'], $ex, $ret, $codes_barres);
@@ -415,16 +419,16 @@ class notice_unimarc extends iso2709_record {
 
           // Champs parametres
           if ($champ_genre and $champ['code'] == $champ_genre)
-            $ex['genre'] = $this->getIdCodeExemplaire('genre', '995', $champ_genre, $champ['valeur']);
+            $ex['genre'] = $this->getIdCodeExemplaire('genre', $item_zone, $champ_genre, $champ['valeur']);
 
           if ($champ_section and $champ['code'] == $champ_section) {
-            $ex['section'] = $this->getIdCodeExemplaire('section', '995', $champ_section, $champ['valeur']);
+            $ex['section'] = $this->getIdCodeExemplaire('section', $item_zone, $champ_section, $champ['valeur']);
             if ($this->isSectionInvisible($ex['section']))
               $ex['ignore_exemplaire'] = true;
           }
 
           if ($champ_emplacement and $champ['code'] == $champ_emplacement) {
-            $ex['emplacement'] = $this->getIdCodeExemplaire('emplacement', '995', $champ_emplacement, $champ['valeur']);
+            $ex['emplacement'] = $this->getIdCodeExemplaire('emplacement', $item_zone, $champ_emplacement, $champ['valeur']);
 
             if (trim($ex['emplacement'])
                 && $this->isEmplacementInvisible($ex['emplacement'])) {
@@ -439,7 +443,7 @@ class notice_unimarc extends iso2709_record {
             $ex['annexe'] = ($annexe) ? $annexe->getCode() : $champ['valeur'];
           }
 
-          if ($champs_nouveaute['zone'] == '995'
+          if ($champs_nouveaute['zone'] == $item_zone
               && $champ['code'] == $champs_nouveaute['champ']) {
             $ex['date_nouveaute'] = $this->calculDateNouveaute($champ['valeur']);
           }
diff --git a/cosmogramme/tests/php/classes/NoticeIntegrationTest.php b/cosmogramme/tests/php/classes/NoticeIntegrationTest.php
index 1a1f5f76c7f..6cd42517baf 100644
--- a/cosmogramme/tests/php/classes/NoticeIntegrationTest.php
+++ b/cosmogramme/tests/php/classes/NoticeIntegrationTest.php
@@ -322,6 +322,59 @@ class NoticeIntegrationMarc21BorisToUnimarcTest extends NoticeIntegrationMarc21D
 }
 
 
+
+
+class NoticeIntegrationMarc21WithItemsIn952Test extends NoticeIntegrationMarc21DynixTestCase {
+  public function getProfilDonnees() {
+    return Class_IntProfilDonnees
+      ::newInstance(
+                    ['libelle' => 'Marc21 Dynix',
+                     'accents' => Class_IntProfilDonnees::ENCODING_UTF8,
+                     'rejet_periodiques' => 1,
+                     'id_article_periodique' => 0,
+                     'type_fichier' => Class_IntProfilDonnees::FT_RECORDS,
+                     'format' => Class_IntProfilDonnees::FORMAT_MARC21,
+                     'attributs' => [['type_doc' => $type_doc,
+                                      Class_IntProfilDonnees::FIELD_ITEM_ZONE => '952',
+                                      Class_IntProfilDonnees::FIELD_ITEM_BARCODE => 'p',
+                                      Class_IntProfilDonnees::FIELD_ITEM_COTE => '',
+                                      Class_IntProfilDonnees::FIELD_ITEM_TYPE_DOC => '',
+                                      Class_IntProfilDonnees::FIELD_ITEM_GENRE => '',
+                                      Class_IntProfilDonnees::FIELD_ITEM_SECTION => '',
+                                      Class_IntProfilDonnees::FIELD_ITEM_EMPLACEMENT => 'c',
+                                      Class_IntProfilDonnees::FIELD_ITEM_ANNEXE => 'a'],
+                                     ['zone' => '996',
+                                      'champ' => 'u',
+                                      'format' => Class_IntProfilDonnees::NOVELTY_DATE_FORMAT_AAAA_MM_JJ,
+                                      'jours' => '90',
+                                      'valeurs' => '']]])
+      ->setIdProfil(23)
+      ->getRawAttributes();
+	}
+
+
+  public function setUp() {
+    parent::setUp();
+    $this->loadNotice('marc21_952_items');
+  }
+
+
+  /** @test */
+  public function recordTitleShouldBeAguaMedioAmbiente() {
+    $this->assertContains('Agua, medio ambiente y desarrollo en el siglo XXI : México desde una perspectiva global y regional',
+                          Class_Notice::find(1)->getTitrePrincipal());
+  }
+
+
+  /** @test */
+  public function recordShouldHaveTwoItems() {
+    $this->assertCount(2, Class_Notice::find(1)->getExemplaires());
+  }
+}
+
+
+
+
 class NoticeIntegrationBourdieuWithElectreGeneratedNoticeRecordTest extends NoticeIntegrationTestCase {
 	public function setUp() {
 		parent::setUp();
diff --git a/library/Class/IntProfilDonnees.php b/library/Class/IntProfilDonnees.php
index d0e10b22e3c..017aabdf9c1 100644
--- a/library/Class/IntProfilDonnees.php
+++ b/library/Class/IntProfilDonnees.php
@@ -34,7 +34,8 @@ class IntProfilDonneesLoader extends Storm_Model_Loader {
 
 
   public function getItemFields() {
-    return [Class_IntProfilDonnees::FIELD_ITEM_BARCODE => '',
+    return [Class_IntProfilDonnees::FIELD_ITEM_ZONE => 995,
+            Class_IntProfilDonnees::FIELD_ITEM_BARCODE => '',
             Class_IntProfilDonnees::FIELD_ITEM_COTE => '',
             Class_IntProfilDonnees::FIELD_ITEM_TYPE_DOC => '',
             Class_IntProfilDonnees::FIELD_ITEM_GENRE => '',
@@ -200,12 +201,13 @@ class IntProfilDonneesLoader extends Storm_Model_Loader {
 
 
   public function getItemBarCodes() {
-    return Class_CosmoVar::getList('champ_code_barres');
-  }
-
-
-  public function getItemCotes() {
-    return Class_CosmoVar::getList('champ_cote');
+    $values = $this->getAllZoneAndFields();
+    $values['997'] = '997$a (' . $this->_('obsolète') .')';
+    $values['852'] = '852$g (' . $this->_('obsolète') .')';
+    $values['999'] = '999$i (' . $this->_('obsolète') .')';
+    $values['996'] = '996$f (' . $this->_('obsolète') .')';
+    $values['949'] = '949$a (' . $this->_('obsolète') .')';
+    return $values;
   }
 
 
@@ -215,16 +217,10 @@ class IntProfilDonneesLoader extends Storm_Model_Loader {
 
 
   public function getAllZoneAndFields() {
-    $values = ['' => '',
-               '#' => '995$0'];
-    for($i=1; $i<10; $i++)
-      $values[$i] = '995$' . $i;
-
-    for($i=65; $i<91; $i++)	{
-      $key = strtolower(chr($i));
-      $values[$key] = '995$' . $key;
-    }
-    return $values;
+    $values = $keys = array_merge(range(1,9), range('a', 'z'));
+    array_walk($values, function(&$value) { $value = '$' . $value; });
+
+    return ['' => '', '#' => '$0'] + array_combine($keys, $values);
   }
 }
 
@@ -268,6 +264,7 @@ class Class_IntProfilDonnees extends Storm_Model_Abstract {
     NOVELTY_DATE_FORMAT_JJ_MM_AAAA = 4,
     NOVELTY_DATE_FORMAT_SLASHED_JMAAAA = 5,
     FIELD_TYPE_DOC_RECOGNITION = 'type_doc',
+    FIELD_ITEM_ZONE = 'item_zone',
     FIELD_ITEM_TYPE_DOC = 'champ_type_doc',
     FIELD_ITEM_BARCODE = 'champ_code_barres',
     FIELD_ITEM_COTE = 'champ_cote',
diff --git a/library/Class/ProfilePrefs.php b/library/Class/ProfilePrefs.php
index 17bbdb0b320..7408619c4bf 100644
--- a/library/Class/ProfilePrefs.php
+++ b/library/Class/ProfilePrefs.php
@@ -22,6 +22,13 @@
 
 class Class_ProfilePrefs extends Class_Entity {
 
+  public function getItemZone() {
+    $prefs = $this->getItemPrefs();
+    return isset($prefs[Class_IntProfilDonnees::FIELD_ITEM_ZONE])
+      ? $prefs[Class_IntProfilDonnees::FIELD_ITEM_ZONE]
+      : '995';
+  }
+
   public function getItemBarCode() {
     return $this->getItemPrefs()[Class_IntProfilDonnees::FIELD_ITEM_BARCODE];
   }
diff --git a/library/Class/ProfileSerializer/UnimarcRecord.php b/library/Class/ProfileSerializer/UnimarcRecord.php
index 7bb5cf6c37a..0d2d3b55ab7 100644
--- a/library/Class/ProfileSerializer/UnimarcRecord.php
+++ b/library/Class/ProfileSerializer/UnimarcRecord.php
@@ -39,6 +39,7 @@ class Class_ProfileSerializer_UnimarcRecord extends Class_ProfileSerializer_Abst
 
   public function populateForm($form) {
     return $form
+      ->populateItemZone()
       ->populateItemBarCode()
       ->populateItemCote()
       ->populateItemDocType()
diff --git a/library/ZendAfi/Form/Cosmo/DataProfile.php b/library/ZendAfi/Form/Cosmo/DataProfile.php
index c99c2f75ab7..1723b195ed3 100644
--- a/library/ZendAfi/Form/Cosmo/DataProfile.php
+++ b/library/ZendAfi/Form/Cosmo/DataProfile.php
@@ -219,31 +219,36 @@ class ZendAfi_Form_Cosmo_DataProfile extends ZendAfi_Form {
                                  'champ_annexe' => $this->_('annexe'),
                                  'champ_availability' => $this->_('disponilité')];
 
-    return $this->addElement('select',
-                             'champ_code_barres',
-                             ['label' => $this->_('Prendre le champ code-barres en'),
-                              'multiOptions' => Class_IntProfilDonnees::getItemBarCodes()])
+    return $this
+      ->addElement('text',
+                   'item_zone',
+                   ['label' => $this->_('Zone des exemplaires')])
+      ->addElement('select',
+                   'champ_code_barres',
+                   ['label' => $this->_('Prendre le champ code-barres en'),
+                    'multiOptions' => Class_IntProfilDonnees::getItemBarCodes()])
 
-                ->addElement('select',
-                             'champ_cote',
-                             ['label' => $this->_('Prendre le champ cote en'),
-                              'multiOptions' => Class_IntProfilDonnees::getItemCotes()])
+      ->addElement('select',
+                   'champ_cote',
+                   ['label' => $this->_('Prendre le champ cote en'),
+                    'multiOptions' => Class_IntProfilDonnees::getAllZoneAndFields()])
 
-                ->addElement('multiInput',
-                             'item_url',
-                             ['label' => $this->_('Prendre l\'url en'),
-                              'fields' => [['name' => 'url_zone', 'label' => $this->_('Zone')],
-                                           ['name' => 'url_champ', 'label' => $this->_('champ')]],
-                              'fixed' => true])
+      ->addElement('multiInput',
+                   'item_url',
+                   ['label' => $this->_('Prendre l\'url en'),
+                    'fields' => [['name' => 'url_zone', 'label' => $this->_('Zone')],
+                                 ['name' => 'url_champ', 'label' => $this->_('champ')]],
+                    'fixed' => true])
 
-                ->_addElementsWithAllFields($elements_with_all_fields)
+      ->_addElementsWithAllFields($elements_with_all_fields)
 
-                ->addDisplayGroup(array_merge(['champ_code_barres',
-                                               'champ_cote'],
-                                              array_keys($elements_with_all_fields),
-                                              ['item_url']),
-                                  'item_group',
-                                  ['legend' => $this->_('Champs exemplaires')]);
+      ->addDisplayGroup(array_merge(['item_zone',
+                                     'champ_code_barres',
+                                     'champ_cote'],
+                                    array_keys($elements_with_all_fields),
+                                    ['item_url']),
+                        'item_group',
+                        ['legend' => $this->_('Champs exemplaires')]);
   }
 
 
@@ -293,6 +298,12 @@ class ZendAfi_Form_Cosmo_DataProfile extends ZendAfi_Form {
   }
 
 
+  public function populateItemZone() {
+    $this->item_zone->setValue($this->_profile_prefs->getItemZone());
+    return $this;
+  }
+
+
   public function populateItemBarCode() {
     $this->champ_code_barres->setValue($this->_profile_prefs->getItemBarCode());
     return $this;
-- 
GitLab