From 1ac4bf324d716aec73c766a538edbc21f466fc2c Mon Sep 17 00:00:00 2001
From: Matthias Meusburger <matthias.meusburger@biblibre.com>
Date: Tue, 21 Jul 2015 17:22:03 +0200
Subject: [PATCH] rel #27656 : external link in record details is 1DTouch's one

---
 library/Class/Notice.php                      |   5 +
 library/Class/Notice/Urls.php                 | 196 ++++++++++++------
 .../RechercheControllerAlbum1DTouchTest.php   |  58 ++++++
 ...echercheControllerAlbumAudioRecordTest.php |   3 -
 4 files changed, 195 insertions(+), 67 deletions(-)
 create mode 100644 tests/application/modules/opac/controllers/RechercheControllerAlbum1DTouchTest.php

diff --git a/library/Class/Notice.php b/library/Class/Notice.php
index c56c6a17cd8..de3227c5970 100644
--- a/library/Class/Notice.php
+++ b/library/Class/Notice.php
@@ -904,6 +904,11 @@ class Class_Notice extends Storm_Model_Abstract {
   }
 
 
+  public function is1DTouch() {
+    return Class_TypeDoc::ONEDTOUCH == $this->getTypeDoc();
+  }
+
+
   public function getMorceaux() {
     return Class_Notice_TracksReader::getTracksOf($this);
   }
diff --git a/library/Class/Notice/Urls.php b/library/Class/Notice/Urls.php
index 59c5d1c5a5c..771a989817a 100644
--- a/library/Class/Notice/Urls.php
+++ b/library/Class/Notice/Urls.php
@@ -22,10 +22,19 @@
 class Class_Notice_Urls {
   protected
     $_notice,
-    $_urls;
+    $_urls,
+    $_black_list,
+    $_url_site;
 
   public function __construct($notice) {
     $this->_notice = $notice;
+
+    $bl_word_list = Class_CosmoVar::get('black_list_856');
+    $this->_black_list = (trim($bl_word_list)) ? explode(';', $bl_word_list) : [];
+
+    $url_site = explode('/', Class_CosmoVar::get('url_site'));
+    $last_part = array_pop($url_site);
+    $this->_url_site = trim($last_part) ? $last_part : array_pop($url_site);
   }
 
 
@@ -37,9 +46,10 @@ class Class_Notice_Urls {
 
 
   protected function _extractUrlsFromPreferences() {
-    $links_zones = Class_Profil::getCurrentProfil()->getCfgModulesPreferences('recherche',
-                                                                              'viewnotice',
-                                                                              $this->_notice->getTypeDoc())['links_zones'];
+    $links_zones = Class_Profil::getCurrentProfil()
+      ->getCfgModulesPreferences('recherche',
+                                 'viewnotice',
+                                 $this->_notice->getTypeDoc())['links_zones'];
     if (!$links_zones)
       return $this;
 
@@ -53,16 +63,20 @@ class Class_Notice_Urls {
   protected function _extractUrlAndLabel($pref_url_label) {
     list($url_zone, $url_field, $label_field) = $pref_url_label;
 
-    $fields = $this->_notice->get_subfield($url_zone);
-    foreach($fields as $field)
-      $this->_extractUrlAndLabelFromField($field, $url_field, $label_field);
+    $closure = function($datas) use (&$result, $url_field, $label_field) {
+      if ((!$link = $this->_extractUrlAndLabelFromField($datas, $url_field, $label_field))
+          || $this->_isBlackListed($link[0]))
+        return;
 
+      $this->_urls[] = $this->_renderLink($link);
+    };
+
+    $this->_withBlocsDo($this->_notice->get_subfield($url_zone), $closure);
     return $this;
   }
 
 
-  protected function _extractUrlAndLabelFromField($field, $url_field, $label_field) {
-    $datas = $this->_notice->decoupe_bloc_champ($field);
+  protected function _extractUrlAndLabelFromField($datas, $url_field, $label_field) {
     $link_url = $link_label = null;
     foreach ($datas as $data) {
       if ($data['code'] == $url_field)
@@ -72,9 +86,7 @@ class Class_Notice_Urls {
         $link_label = $data['valeur'];
     }
 
-    if ($link_url)
-      $this->_urls[] = sprintf('<a href="%s">%s</a>',
-                               $link_url, $link_label ? $link_label : $link_url);
+    return $link_url ? [$link_url, $link_label] : null;
   }
 
 
@@ -82,67 +94,123 @@ class Class_Notice_Urls {
     if ($this->_notice->isCvs())
       return [];
 
-    $lien = [];
-    $blocs = $this->_notice->get_subfield(856);
+    $result = ($this->_notice->is1DTouch()) ?
+      $this->_get1DTouchLink() : $this->_getDefaultLinks();
+
+    $links = $this->_doBlackList($result);
+    $links = $this->_renderLinks($links);
+
+    return $links;
+  }
+
 
+  protected function _get1DTouchLink() {
+    $closure = function ($datas) use (&$result) {
+      $result[] = $this->_get1DTouchLinkFor($datas);
+    };
+
+    $this->_withBlocsDo($this->_notice->get_subfield(856), $closure);
+    $result = array_filter($result);
+
+    return empty($result) ? [] : [reset($result)];
+  }
+
+
+  protected function _getDefaultLinks() {
     $result = [];
+    $closure = function ($datas) use (&$result) {
+      $result[] = $this->_get856AlinkFor($datas);
+    };
+
+    $this->_withBlocsDo($this->_notice->get_subfield(856), $closure);
+
+    return array_filter($result);
+  }
+
+
+  protected function _renderLinks($links) {
+    return empty($links) ?
+      [] : array_map([$this, '_renderLink'], $links);
+  }
+
+
+  protected function _renderLink($link) {
+    $label = null;
+    if (is_array($link))
+      list($link, $label) = $link;
+
+    if (substr(strtoupper($link), 0, 4) != 'HTTP')
+      $link = 'http://' . $link;
+
+    $target = (strpos($link, $this->_url_site) === false)
+      ? 'target="_blank"' : '';
+
+    return '<a href="' . trim($link) . '" ' . $target . ">"
+      . ($label ? $label : trim($link))
+      . '</a>';
+  }
+
+
+  protected function _doBlackList($links) {
+    if (empty($links))
+      return [];
+    return $this->_black_list ? array_filter($links, [$this, '_isNotBlackListed']) : $links;
+  }
+
+
+  protected function _isBlackListed($link) {
+    foreach ($this->_black_list as $word) {
+      if (stripos($link, $word) !== false)
+        return true;
+    }
+    return false;
+  }
+
+
+  protected function _isNotBlackListed($link) {
+    return !$this->_isBlackListed($link);
+  }
+
+
+  protected function _withBlocsDo($blocs, $closure) {
     foreach ($blocs as $bloc) {
       $datas = $this->_notice->decoupe_bloc_champ($bloc);
-      $link = null;
-      foreach ($datas as $data) {
-        if ($data['code']=='x') {
-          $link = null;
-          break;
-        }
-        if ($data['code']=='u')
-          $link = $data['valeur'];
-
-        if ($data['code']=='a')
-          $link = $data['valeur'];
-      }
-      $result[]=$link;
+      $closure($datas);
     }
+  }
 
-    $result = array_filter($result);
 
-    if (isset($result[0]))  {
-      // black list
-      $trav = Class_CosmoVar::get('black_list_856');
-      $black_list = (trim($trav)) ? explode(';', $trav) : [];
-
-      // controle url pour target
-      $target = Class_CosmoVar::get('url_site');
-      $trav = explode('/', $target);
-      $ctrl_target = array_pop($trav);
-      if (!trim($ctrl_target))
-        $ctrl_target = array_pop($trav);
-
-      // tableau des liens
-      foreach ($result as $item) {
-        $controle = true;
-        if ($black_list) {
-          foreach ($black_list as $mot) {
-            if (stripos($item, $mot) !== false) {
-              $controle = false;
-              break;
-            }
-          }
-        }
-
-        if ($controle == true) {
-          if (substr(strtoupper($item), 0, 4) != 'HTTP')
-            $item = 'http://' . $item;
-
-          $target = (strpos($item, $ctrl_target) === false)
-            ? 'target="_blank"' : '';
-
-          $lien[] = '<a href="' . trim($item) . '" ' . $target . ">" . trim($item) . '</a>';
-        }
-      }
+  protected function _get856AlinkFor($datas) {
+    $link = null;
+
+    foreach ($datas as $data) {
+      if ($data['code']=='x')
+        return null;
+
+      if ($data['code']=='u')
+        $link = $data['valeur'];
+
+      if ($data['code']=='a')
+        $link = $data['valeur'];
     }
-    return($lien);
+
+    return $link;
   }
-}
 
 
+  protected function _get1DTouchLinkFor($datas) {
+    $link = $type = null;
+
+    foreach ($datas as $data) {
+      if ($data['code']=='x')
+        $type = $data['valeur'];
+
+      if ($data['code']=='a')
+        $link = $data['valeur'];
+    }
+
+    return ($type == 'external_uri' && $link) ?
+      $link : null;
+  }
+}
 ?>
\ No newline at end of file
diff --git a/tests/application/modules/opac/controllers/RechercheControllerAlbum1DTouchTest.php b/tests/application/modules/opac/controllers/RechercheControllerAlbum1DTouchTest.php
new file mode 100644
index 00000000000..f91a5e07f4f
--- /dev/null
+++ b/tests/application/modules/opac/controllers/RechercheControllerAlbum1DTouchTest.php
@@ -0,0 +1,58 @@
+<?php
+/**
+ * Copyright (c) 2012-2014, 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
+ */
+
+
+class RechercheControllerAlbum1DTouchTest extends AbstractControllerTestCase {
+
+  protected $_storm_default_to_volatile = true;
+
+  public function setUp() {
+    parent::setUp();
+
+    $bridges = $this->fixture('Class_Album',
+                   ['id' => 74721,
+                    'titre' => 'Bridges',
+                    'date_maj' => '2015-06-22 16:55:37',
+                    'type_doc_id' => 114,
+                    'id_langue' => 'fre',
+                    'id_origine' => 1,
+                    'notes' => 'a:7:{i:0;a:2:{s:5:"field";s:3:"701";s:4:"data";a:2:{s:1:"a";s:5:"Eivor";i:4;s:0:"";}}i:1;a:2:{s:5:"field";s:3:"856";s:4:"data";a:2:{s:1:"x";s:6:"poster";s:1:"a";s:88:"https://commondatastorage.googleapis.com/music-production/cargo/medium_0663993761558.jpg";}}i:2;a:2:{s:5:"field";s:3:"856";s:4:"data";a:2:{s:1:"x";s:12:"external_uri";s:1:"a";s:33:"http://music.1dtouch.com/albums/1";}}i:3;a:2:{s:5:"field";s:3:"856";s:4:"data";a:2:{s:1:"x";s:6:"poster";s:1:"a";s:88:"https://commondatastorage.googleapis.com/music-production/cargo/medium_0663993761558.jpg";}}i:4;a:2:{s:5:"field";s:3:"856";s:4:"data";a:2:{s:1:"x";s:12:"external_uri";s:1:"a";s:33:"http://music.1dtouch.com/albums/1";}}i:5;a:2:{s:5:"field";s:3:"856";s:4:"data";a:2:{s:1:"x";s:6:"poster";s:1:"a";s:88:"https://commondatastorage.googleapis.com/music-production/cargo/medium_0663993761558.jpg";}}i:6;a:2:{s:5:"field";s:3:"856";s:4:"data";a:2:{s:1:"x";s:12:"external_uri";s:1:"a";s:33:"http://music.1dtouch.com/albums/1";}}}',
+                    'url_origine' => 'http://export.1dtouch.com/oai',
+                    'visible' => 1,
+                    'status' => 3]);
+    $bridges->index();
+
+    $this->dispatch('/opac/noticeajax/detail/id/' . $bridges->getNoticeId(), true);
+  }
+
+
+  /** @test */
+  public function authorShouldBePresent() {
+    $this->assertXPathContentContains('//a[contains(@href, "/code_rebond/A1")]', 'Eivor');
+  }
+
+
+  /** @test */
+  public function externalUrlShouldTarget1Dtouch() {
+    $this->assertXPath('//a[@href="http://music.1dtouch.com/albums/1"]',
+                       $this->_response->getBody());
+  }
+}
\ No newline at end of file
diff --git a/tests/application/modules/opac/controllers/RechercheControllerAlbumAudioRecordTest.php b/tests/application/modules/opac/controllers/RechercheControllerAlbumAudioRecordTest.php
index e094ccbce1f..ae67edf24d3 100644
--- a/tests/application/modules/opac/controllers/RechercheControllerAlbumAudioRecordTest.php
+++ b/tests/application/modules/opac/controllers/RechercheControllerAlbumAudioRecordTest.php
@@ -20,9 +20,6 @@
  */
 
 
-require_once 'AbstractControllerTestCase.php';
-
-
 abstract class RechercheControllerAlbumAudioRecordTestCase extends AbstractControllerTestCase {
   protected
     $_notice,
-- 
GitLab