From b08c1d2c4d613f0bb06e85e15396fe543b331fee Mon Sep 17 00:00:00 2001
From: gloas <gloas@afi-sa.fr>
Date: Wed, 22 Aug 2018 15:46:19 +0200
Subject: [PATCH] dev #74897 add xslt input to search result configuration form

---
 FEATURES/74897                                |  10 ++
 VERSIONS_WIP/74897                            |   2 +
 .../scripts/recherche/resultatRecherche.phtml |   1 -
 .../Form/Configuration/SearchResult.php       |  14 ++
 library/ZendAfi/View/Helper/ListeNotices.php  |   8 +-
 library/ZendAfi/View/Helper/Notice/Entete.php |   1 +
 tests/scenarios/Xsl/XslTest.php               | 132 +++++++++++++++++-
 tests/scenarios/Xsl/search_result.xsl         |  90 ++++++++++++
 8 files changed, 251 insertions(+), 7 deletions(-)
 create mode 100644 FEATURES/74897
 create mode 100644 VERSIONS_WIP/74897
 create mode 100644 tests/scenarios/Xsl/search_result.xsl

diff --git a/FEATURES/74897 b/FEATURES/74897
new file mode 100644
index 00000000000..2fde0164887
--- /dev/null
+++ b/FEATURES/74897
@@ -0,0 +1,10 @@
+        '74897' =>
+            ['Label' => $this->_('Personnalisation des notices avec XSLT'),
+             'Desc' => $this->_('Personnalisation de l\'affichage du résultat de recherche et d\'une notice par des fichiers XLST'),
+             'Image' => '',
+             'Video' => '',
+             'Category' => $this->_('Mise en page'),
+             'Right' => function($feature_description, $user) {return true;},
+             'Wiki' => '',
+             'Test' => '',
+             'Date' => '2018-08-22'],
\ No newline at end of file
diff --git a/VERSIONS_WIP/74897 b/VERSIONS_WIP/74897
new file mode 100644
index 00000000000..d9d27092767
--- /dev/null
+++ b/VERSIONS_WIP/74897
@@ -0,0 +1,2 @@
+ - ticket #74897 : Résultat de recherche : en mode d'affichage "vignettes", vous avez la possibilité de remplacer l'entête des notices par un fichier XSLT.
+ 
\ No newline at end of file
diff --git a/application/modules/opac/views/scripts/recherche/resultatRecherche.phtml b/application/modules/opac/views/scripts/recherche/resultatRecherche.phtml
index 931d49e038e..b667b57311e 100644
--- a/application/modules/opac/views/scripts/recherche/resultatRecherche.phtml
+++ b/application/modules/opac/views/scripts/recherche/resultatRecherche.phtml
@@ -3,4 +3,3 @@ $this->openBoite($this->titre);
 echo $this->Search_Header($this->search_result);
 $this->closeBoite();
 echo $this->Search_Result($this->search_result);
-?>
diff --git a/library/ZendAfi/Form/Configuration/SearchResult.php b/library/ZendAfi/Form/Configuration/SearchResult.php
index 9fcb2016324..7fa9e2251b7 100644
--- a/library/ZendAfi/Form/Configuration/SearchResult.php
+++ b/library/ZendAfi/Form/Configuration/SearchResult.php
@@ -41,6 +41,11 @@ class ZendAfi_Form_Configuration_SearchResult extends ZendAfi_Form {
 
   public function init() {
     parent::init();
+
+    Class_ScriptLoader::getInstance()
+      ->addJQueryReady(
+                       'formSelectToggleVisibilityForElement("#liste_format", $("#' . Class_Notice_Xsl::KEY . '").closest("tr"), ["3"]);');
+
     $this
       ->setAttrib('id',
                   'configuration_searchResult')
@@ -204,9 +209,18 @@ class ZendAfi_Form_Configuration_SearchResult extends ZendAfi_Form {
                    'bookmarks_enabled',
                    ['label' => $this->_('Afficher les favoris utilisateur')])
 
+      ->addElement('userfile',
+                   Class_Notice_Xsl::KEY,
+                   ['label' => $this->_('Remplacer l\'entête des notices par la XSLT suivante :'),
+                    'allowEmpty' => true,
+                    'validators' => [(new Zend_Validate_Regex('/^.*\.xsl$/i'))
+                                     ->setMessage($this->_('Le fichier doit être de type "xsl"'))]])
+
+
       ->addToDisplaySettingsGroup(['liste_format',
                                    'liste_nb_par_page',
                                    'liste_codes',
+                                   Class_Notice_Xsl::KEY,
                                    'zones_titre',
                                    'suggests_enabled',
                                    'suggests_number',
diff --git a/library/ZendAfi/View/Helper/ListeNotices.php b/library/ZendAfi/View/Helper/ListeNotices.php
index 39f057e5ab1..a48e848c12f 100644
--- a/library/ZendAfi/View/Helper/ListeNotices.php
+++ b/library/ZendAfi/View/Helper/ListeNotices.php
@@ -61,14 +61,12 @@ class ZendAfi_View_Helper_ListeNotices extends ZendAfi_View_Helper_BaseHelper {
   }
 
 
-  protected function _displayList($notices,$preferences) {
-    $helpers = [
-                Class_Systeme_ModulesAppli::LISTE_FORMAT_TABLEAU => 'ListeNotices_Tableau',
+  protected function _displayList($notices, $preferences) {
+    $helpers = [Class_Systeme_ModulesAppli::LISTE_FORMAT_TABLEAU => 'ListeNotices_Tableau',
                 Class_Systeme_ModulesAppli::LISTE_FORMAT_ACCORDEON => 'ListeNotices_Accordeon',
                 Class_Systeme_ModulesAppli::LISTE_FORMAT_VIGNETTES => 'ListeNotices_Vignettes',
                 Class_Systeme_ModulesAppli::LISTE_FORMAT_MUR => 'ListeNotices_Mur',
-                Class_Systeme_ModulesAppli::LISTE_FORMAT_CHRONO => 'ListeNotices_Chrono',
-    ];
+                Class_Systeme_ModulesAppli::LISTE_FORMAT_CHRONO => 'ListeNotices_Chrono'];
 
     $helper = $helpers[$preferences['liste_format']];
     return call_user_func_array([$this->view, $helper], [$notices, $preferences]);
diff --git a/library/ZendAfi/View/Helper/Notice/Entete.php b/library/ZendAfi/View/Helper/Notice/Entete.php
index 08c35cc06cd..b1d393ce032 100644
--- a/library/ZendAfi/View/Helper/Notice/Entete.php
+++ b/library/ZendAfi/View/Helper/Notice/Entete.php
@@ -21,6 +21,7 @@
 
 
 class ZendAfi_View_Helper_Notice_Entete extends ZendAfi_View_Helper_BaseHelper {
+
   public function notice_Entete($notice, $preferences) {
     if(!$notice)
       return '';
diff --git a/tests/scenarios/Xsl/XslTest.php b/tests/scenarios/Xsl/XslTest.php
index 3357c6ccfb9..f8763b5cb18 100644
--- a/tests/scenarios/Xsl/XslTest.php
+++ b/tests/scenarios/Xsl/XslTest.php
@@ -113,6 +113,7 @@ class XslDocTypeConfigurationPostDispatchTest extends Admin_AbstractControllerTe
 
 
 class XslNoticeajaxDetailDispatchTest extends AbstractControllerTestCase {
+
   protected $_storm_default_to_volatile = true;
 
   public function setUp() {
@@ -289,4 +290,133 @@ class XslFileManagerControllerWithXslInRechercheViewnoticeTest extends Admin_Abs
     $xslt = Class_Profil::getCurrentProfil()->getModulePreference('recherche', 'viewnoticeAssimil', 'xslt');
     $this->assertContains('userfiles/bib1/xsl/titi.xsl', $xslt);
   }
-}
\ No newline at end of file
+}
+
+
+
+
+class XslSearchResultConfigurationDispatchTest extends Admin_AbstractControllerTestCase {
+  protected $_storm_default_to_volatile = true;
+
+
+  public function setUp() {
+    parent::setUp();
+        $this->dispatch('/admin/modules/recherche/id_profil/2/action1/resultat/action2/simple/type_module/recherche/config/site', true);
+  }
+
+  /** @test */
+  public function inputReplaceDescriptionWithXSLTShouldBePresent() {
+    $this->assertXPath('//input[@type="text"][@name="xslt"]');
+  }
+
+
+  /** @test */
+  public function scriptSelectToggleVisibilityShouldBePresent() {
+    $this->assertXPathContentContains('//script', 'formSelectToggleVisibilityForElement("#liste_format"');
+  }
+}
+
+
+
+
+class XslSearchResultPostDispatchTest extends Admin_AbstractControllerTestCase {
+  protected
+    $_storm_default_to_volatile = true,
+    $viewnotice_pref;
+
+  public function setUp() {
+    parent::setUp();
+
+    $this->postDispatch('/admin/modules/recherche?config=site&type_module=recherche&id_profil=2&action1=viewnotice&action2=1',
+                        [Class_Notice_Xsl::KEY => 'fichier.xsl']);
+
+    $this->viewnotice_pref = Class_Profil::getCurrentProfil()
+      ->getCfgModulesAsArray()['recherche']['viewnotice1'];
+  }
+
+
+  /** @test */
+  public function preferencesShouldContainsXslt() {
+    $this->assertEquals('fichier.xsl',
+                        $this->viewnotice_pref[Class_Notice_Xsl::KEY]);
+  }
+}
+
+
+
+
+class XslSearchResultDispatchTest extends AbstractControllerTestCase {
+
+  protected $_storm_default_to_volatile = true;
+
+
+  public function setUp() {
+    parent::setUp();
+
+    $disk = $this->mock()
+                 ->whenCalled('directoryAt')
+                 ->answers(null)
+
+                 ->whenCalled('fileAt')
+                 ->answers((new Class_FileManager)
+                           ->setRealpath('tests/scenarios/Xsl/search_result.xsl'));
+
+    Class_FileManager::setFileSystem($disk);
+
+    $php_command = $this->mock()
+                        ->whenCalled('extension_loaded')
+                        ->answers(true)
+
+                        ->whenCalled('unlink')
+                        ->answers(true)
+
+                        ->whenCalled('libxml_use_internal_errors')
+                        ->answers(true)
+
+                        ->whenCalled('libxml_get_errors')
+                        ->answers([]);
+
+    Class_Notice_Xsl::setPhpCommand($php_command);
+
+    $dom_document = $this->mock()
+                         ->whenCalled('load')
+                         ->answers(true);
+
+    Class_Notice_Xsl::setDomDocument($dom_document);
+
+    $xslt_processor = $this->mock()
+                           ->whenCalled('importStylesheet')
+                           ->answers(true)
+
+                           ->whenCalled('transformToXml')
+                           ->answers('<li><strong>Numéro de notice Koha : </strong>2774</li><br><li>');
+
+    Class_Notice_Xsl::setXSLTProcessor($xslt_processor);
+
+    $profile = Class_Profil::getCurrentProfil();
+    $profile->setCfgModulesPreferences(['xslt' => '/tests/scenarios/Xsl/search_result.xsl'],
+                                       'recherche',
+                                       'resultat',
+                                       'simple');
+    $profile->save();
+
+    $this->fixture('Class_Notice',
+                   ['id' => 5,
+                    'type_doc' => 1,
+                    'unimarc' => "01185nam0 2200217   450 0010005000000100031000050350016000360900009000520990038000611000041000991010008001402000036001482100013001842150011001973300660002083330010008686760006008787000028008848010026009129020029009382774  a2-84563-280-0d19,90 Euros  aALOES355754  a2774  c2017-12-11d2018-03-16tLIVREx12  a20171211              frey50          afre  aSeras-tu là ?fGuillaume Musso  cXOd2012  a301 p.  aUn seul geste aurait suffi pour tout changer. Qui n'a jamais rêvé de revenir à cet instant décisif où le bonheur était possible ? San Francisco. Elliott, médecin passionné, ne s'est jamais consolé de la disparition d'Ilena, la femme qu'il aimait, morte il y a trente ans. Un jour, par une circonstance extraordinaire, il est ramené en arrière et rencontre le jeune homme qu'il était, trente ans plus tôt. Il est revenu à l'instant décisif où un geste de lui peut sauver Ilena. Et modifier l'implacable destin qui a figé son sort à jamais. Un stupéfiant face-à-face, Une histoire d'amour bouleversante, Un suspense à couper le souffle.  aAG 14  aR  aMussobGuillaume960415  aFRbCALUIREc20060516  981440aroman francophone"]);
+
+    $this->dispatch('/opac/recherche/simple', true);
+  }
+
+
+  /** @test */
+  public function shouldNotRedirect() {
+    $this->assertNotRedirect();
+  }
+
+
+  /** @test */
+  public function shouldDisplayMarcWithXslt() {
+    $this->assertContains('<strong>Numéro de notice Koha : </strong>2774</li><br><li>', $this->_response->getBody());
+  }
+}
diff --git a/tests/scenarios/Xsl/search_result.xsl b/tests/scenarios/Xsl/search_result.xsl
new file mode 100644
index 00000000000..55a5cbcf84c
--- /dev/null
+++ b/tests/scenarios/Xsl/search_result.xsl
@@ -0,0 +1,90 @@
+
+
+<!DOCTYPE stylesheet [<!ENTITY nbsp "&#160;" >]>
+
+<!-- $Id: MARC21slim2DC.xsl,v 1.1 2003/01/06 08:20:27 adam Exp $ -->
+<xsl:stylesheet version="1.0"
+  xmlns:marc="http://www.loc.gov/MARC21/slim"
+  xmlns:items="http://www.koha-community.org/items"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  exclude-result-prefixes="marc items">
+<xsl:import href="UNIMARCslimUtils.xsl"/>
+<xsl:output method = "html" indent="yes" omit-xml-declaration = "yes" encoding="UTF-8"/>
+<!--<xsl:key name="item-by-status" match="items:item" use="items:status"/>
+<xsl:key name="item-by-status-and-branch" match="items:item" use="concat(items:status, ' ', items:homebranch)"/>-->
+
+<xsl:template match="/">
+ <xsl:apply-templates/>
+</xsl:template>
+
+<xsl:template match="marc:record">
+ <xsl:variable name="IntranetBiblioDefaultView" select="marc:sysprefs/marc:syspref[@name='IntranetBiblioDefaultView']"/>
+ <xsl:variable name="leader" select="marc:leader"/>
+ <xsl:variable name="leader6" select="substring($leader,7,1)"/>
+ <xsl:variable name="leader7" select="substring($leader,8,1)"/>
+ <xsl:variable name="biblionumber" select="marc:controlfield[@tag=001]"/>
+ <xsl:variable name="isbn" select="marc:datafield[@tag=010]/marc:subfield[@code='a']"/>
+
+ <xsl:if test="marc:datafield[@tag=200]">
+ <xsl:for-each select="marc:datafield[@tag=200]">
+ <a>
+ <xsl:attribute name="href">
+ <xsl:call-template name="buildBiblioDefaultViewURL">
+ <xsl:with-param name="IntranetBiblioDefaultView">
+ <xsl:value-of select="$IntranetBiblioDefaultView"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ <xsl:value-of select="$biblionumber"/>
+ </xsl:attribute>
+ <xsl:attribute name="class">title</xsl:attribute>
+
+ <xsl:variable name="title" select="marc:subfield[@code='a']"/>
+ <xsl:variable name="ntitle"
+            select="translate($title, '&#x0098;&#x009C;&#xC29C;&#xC29B;&#xC298;&#xC288;&#xC289;','')"/>
+ <xsl:value-of select="$ntitle" />
+ </a>
+ <xsl:if test="marc:subfield[@code='e']">
+ <xsl:for-each select="marc:subfield[@code='e']">
+ <xsl:text> : </xsl:text>
+ <xsl:value-of select="."/>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="marc:subfield[@code='d']">
+ <xsl:for-each select="marc:subfield[@code='d']">
+ <xsl:text> = </xsl:text>
+ <xsl:value-of select="."/>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="marc:subfield[@code='b']">
+ <xsl:text> [</xsl:text>
+ <xsl:value-of select="marc:subfield[@code='b']"/>
+ <xsl:text>]</xsl:text>
+ </xsl:if>
+ <xsl:if test="marc:subfield[@code='h']">
+ <xsl:text> : </xsl:text>
+ <xsl:value-of select="marc:subfield[@code='h']"/>
+ </xsl:if>
+ <xsl:if test="marc:subfield[@code='i']">
+ <xsl:text> : </xsl:text>
+ <xsl:value-of select="marc:subfield[@code='i']"/>
+ </xsl:if>
+ <xsl:if test="marc:subfield[@code='f']">
+ <xsl:text> / </xsl:text>
+ <xsl:value-of select="marc:subfield[@code='f']"/>
+ </xsl:if>
+ <xsl:if test="marc:subfield[@code='g']">
+ <xsl:text> ; </xsl:text>
+ <xsl:value-of select="marc:subfield[@code='g']"/>
+ </xsl:if>
+ <xsl:text> </xsl:text>
+ </xsl:for-each>
+ </xsl:if>
+
+ <xsl:call-template name="tag_4xx" />
+
+ <xsl:call-template name="tag_210" />
+
+ <xsl:call-template name="tag_215" />
+
+</xsl:template>
+</xsl:stylesheet>
-- 
GitLab