proxied added content support for ContentCafe
authorphasefx <phasefx@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Fri, 25 Jun 2010 22:11:36 +0000 (22:11 +0000)
committerphasefx <phasefx@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Fri, 25 Jun 2010 22:11:36 +0000 (22:11 +0000)
git-svn-id: svn://svn.open-ils.org/ILS/trunk@16818 dcc99617-32d9-48b4-a31d-7c20da2025e4

Open-ILS/examples/opensrf.xml.example
Open-ILS/src/perlmods/OpenILS/WWW/AddedContent/ContentCafe.pm [new file with mode: 0644]
Open-ILS/web/opac/common/js/added_content.js
Open-ILS/web/opac/locale/en-US/opac.dtd
Open-ILS/web/opac/skin/default/js/rdetail.js
Open-ILS/web/opac/skin/default/xml/rdetail/rdetail_extras.xml

index a25277c..98fb60a 100644 (file)
@@ -297,6 +297,23 @@ vim:et:ts=4:sw=4:
             <userid>MY_USER_ID</userid>
 
             <!--
+            Segregating the details for ContentCafe out for easier use.  At some point, we
+            may want to support multiple services at one time.
+            -->
+            <ContentCafe>
+                <userid>MY_USER_ID</userid>
+                <password>MY_PASSWORD</password>
+
+                <!--
+                If no cover/jacket image exists for a given ISBN, then a value of T here will
+                return an 80x120 pixel image containing the text "No Image Available".  A
+                value of 1 will return a 1x1 pixel image.
+                -->
+                <return_behavior_on_no_jacket_image>T</return_behavior_on_no_jacket_image>
+            </ContentCafe>
+
+            <!--
             You can add free-form settings here and they will be accessible
             within the added content module
             -->
diff --git a/Open-ILS/src/perlmods/OpenILS/WWW/AddedContent/ContentCafe.pm b/Open-ILS/src/perlmods/OpenILS/WWW/AddedContent/ContentCafe.pm
new file mode 100644 (file)
index 0000000..19a767d
--- /dev/null
@@ -0,0 +1,289 @@
+package OpenILS::WWW::AddedContent::ContentCafe;
+use strict; use warnings;
+use OpenSRF::Utils::Logger qw/$logger/;
+use OpenSRF::Utils::SettingsParser;
+use OpenSRF::Utils::JSON;
+use OpenSRF::EX qw/:try/;
+use OpenILS::WWW::AddedContent;
+use XML::LibXML;
+use MIME::Base64;
+
+my $AC = 'OpenILS::WWW::AddedContent';
+
+my $base_url = 'http://contentcafe2.btol.com/ContentCafe/ContentCafe.asmx/Single';
+my $cover_base_url = 'http://contentcafe2.btol.com/ContentCafe/Jacket.aspx';
+
+sub new {
+    my( $class, $args ) = @_;
+    $class = ref $class || $class;
+    return bless($args, $class);
+}
+
+sub userid {
+    my $self = shift;
+    return $self->{ContentCafe}->{userid};
+}
+
+sub password {
+    my $self = shift;
+    return $self->{ContentCafe}->{password};
+}
+
+sub return_behavior_on_no_jacket_image {
+    my $self = shift;
+    return $self->{ContentCafe}->{return_behavior_on_no_jacket_image};
+}
+
+# --------------------------------------------------------------------------
+sub jacket_small {
+    my( $self, $key ) = @_;
+    return $self->send_img(
+        $self->fetch_cover_response('S', $key));
+}
+
+sub jacket_medium {
+    my( $self, $key ) = @_;
+    return $self->send_img(
+        $self->fetch_cover_response('M', $key));
+
+}
+sub jacket_large {
+    my( $self, $key ) = @_;
+    return $self->send_img(
+        $self->fetch_cover_response('L', $key));
+}
+
+# --------------------------------------------------------------------------
+
+sub toc_html {
+    my( $self, $key ) = @_;
+    my $xml = $self->fetch_content('TocDetail', $key);
+    my $doc = XML::LibXML->new->parse_string($xml);
+    $doc->documentElement->setNamespace('http://ContentCafe2.btol.com', 'cc');
+    my $html = '';
+    foreach my $node ( $doc->findnodes('//cc:Toc') ) {
+        $html .= $node->textContent . '</P></P>';
+    }
+    return $self->send_html($html);
+}
+
+sub toc_xml {
+    my( $self, $key ) = @_;
+    return $self->send_xml(
+        $self->fetch_content('TocDetail', $key));
+}
+
+sub toc_json {
+    my( $self, $key ) = @_;
+    return $self->send_json(
+        $self->fetch_content('TocDetail', $key));
+}
+
+# --------------------------------------------------------------------------
+
+sub anotes_html {
+    my( $self, $key ) = @_;
+    my $xml = $self->fetch_content('BiographyDetail', $key);
+    my $doc = XML::LibXML->new->parse_string($xml);
+    $doc->documentElement->setNamespace('http://ContentCafe2.btol.com', 'cc');
+    my $html = '';
+    foreach my $node ( $doc->findnodes('//cc:Biography') ) {
+        $html .= '<P class="biography">' . $node->textContent . '</P>';
+    }
+    return $self->send_html($html);
+}
+
+sub anotes_xml {
+    my( $self, $key ) = @_;
+    return $self->send_xml(
+        $self->fetch_content('BiographyDetail', $key));
+}
+
+sub anotes_json {
+    my( $self, $key ) = @_;
+    return $self->send_json(
+        $self->fetch_content('BiographyDetail', $key));
+}
+
+
+# --------------------------------------------------------------------------
+
+sub excerpt_html {
+    my( $self, $key ) = @_;
+    my $xml = $self->fetch_content('ExcerptDetail', $key);
+    my $doc = XML::LibXML->new->parse_string($xml);
+    $doc->documentElement->setNamespace('http://ContentCafe2.btol.com', 'cc');
+    my $html = '';
+    foreach my $node ( $doc->findnodes('//cc:Excerpt') ) {
+        $html .= $node->textContent;
+    }
+    return $self->send_html($html);
+}
+
+sub excerpt_xml {
+    my( $self, $key ) = @_;
+    return $self->send_xml(
+        $self->fetch_content('ExcerptDetail', $key));
+}
+
+sub excerpt_json {
+    my( $self, $key ) = @_;
+    return $self->send_json(
+        $self->fetch_content('ExcerptDetail', $key));
+}
+
+# --------------------------------------------------------------------------
+
+sub reviews_html {
+    my( $self, $key ) = @_;
+    my $xml = $self->fetch_content('ReviewDetail', $key);
+    my $doc = XML::LibXML->new->parse_string($xml);
+    $doc->documentElement->setNamespace('http://ContentCafe2.btol.com', 'cc');
+    my $html = '<ul>';
+    foreach my $node ( $doc->findnodes('//cc:ReviewItem') ) {
+        my @s_nodes = $node->findnodes('./cc:Supplier');
+        my @p_nodes = $node->findnodes('./cc:Publication');
+        my @i_nodes = $node->findnodes('./cc:Issue');
+        my @r_nodes = $node->findnodes('./cc:Review');
+        $html .= '<li><b>' . (scalar(@p_nodes) ? $p_nodes[0]->textContent : '') . '</b>';
+        if (scalar(@i_nodes) && scalar(@p_nodes)) { $html .= ' : '; }
+        $html .= (scalar(@i_nodes) ? $i_nodes[0]->textContent : '') . '<br/>';
+        $html .= (scalar(@r_nodes) ? $r_nodes[0]->textContent : '') . '</li>';
+    }
+    $html .= '</ul>';
+    return $self->send_html($html);
+}
+
+sub reviews_xml {
+    my( $self, $key ) = @_;
+    return $self->send_xml(
+        $self->fetch_content('ReviewDetail', $key));
+}
+
+sub reviews_json {
+    my( $self, $key ) = @_;
+    return $self->send_json(
+        $self->fetch_content('ReviewDetail', $key));
+}
+
+# --------------------------------------------------------------------------
+
+sub summary_html {
+    my( $self, $key ) = @_;
+    my $xml = $self->fetch_content('AnnotationDetail', $key);
+    my $doc = XML::LibXML->new->parse_string($xml);
+    $doc->documentElement->setNamespace('http://ContentCafe2.btol.com', 'cc');
+    my $html = '<ul>';
+    foreach my $node ( $doc->findnodes('//cc:AnnotationItem') ) {
+        my @s_nodes = $node->findnodes('./cc:Supplier');
+        my @a_nodes = $node->findnodes('./cc:Annotation');
+        $html .= '<li><b>' . (scalar(@s_nodes) ? $s_nodes[0]->textContent : '') . '</b><br/>';
+        $html .= (scalar(@a_nodes) ? $a_nodes[0]->textContent : '') . '</li>';
+    }
+    $html .= '</ul>';
+    return $self->send_html($html);
+}
+
+sub summary_xml {
+    my( $self, $key ) = @_;
+    return $self->send_xml(
+        $self->fetch_content('AnnotationDetail', $key));
+}
+
+sub summary_json {
+    my( $self, $key ) = @_;
+    return $self->send_json(
+        $self->fetch_content('AnnotationDetail', $key));
+}
+
+
+# --------------------------------------------------------------------------
+
+
+sub data_exists {
+    my( $self, $data ) = @_;
+    return 0 if $data =~ m/<title>error<\/title>/iog;
+    return 1;
+}
+
+
+sub send_json {
+    my( $self, $xml ) = @_;
+    return 0 unless $self->data_exists($xml);
+    my $doc;
+
+    try {
+        $doc = XML::LibXML->new->parse_string($xml);
+    } catch Error with {
+        my $err = shift;
+        $logger->error("added content XML parser error: $err\n\n$xml");
+        $doc = undef;
+    };
+
+    return 0 unless $doc;
+    my $perl = OpenSRF::Utils::SettingsParser::XML2perl($doc->documentElement);
+    my $json = OpenSRF::Utils::JSON->perl2JSON($perl);
+    return { content_type => 'text/plain', content => $json };
+}
+
+sub send_xml {
+    my( $self, $xml ) = @_;
+    return 0 unless $self->data_exists($xml);
+    return { content_type => 'application/xml', content => $xml };
+}
+
+sub send_html {
+    my( $self, $content ) = @_;
+    return 0 unless $self->data_exists($content);
+
+    # Hide anything that might contain a link since it will be broken
+    my $HTML = <<"    HTML";
+        <div>
+            <style type='text/css'>
+                div.ac input, div.ac a[href],div.ac img, div.ac button { display: none; visibility: hidden }
+            </style>
+            <div class='ac'>
+                $content
+            </div>
+        </div>
+    HTML
+
+    return { content_type => 'text/html', content => $HTML };
+}
+
+sub send_img {
+    my($self, $response) = @_;
+    return { 
+        content_type => $response->header('Content-type'),
+        content => $response->content, 
+        binary => 1 
+    };
+}
+
+# returns the raw content returned from the URL fetch
+sub fetch_content {
+    my( $self, $contentType, $key ) = @_;
+    return $self->fetch_response($contentType, $key)->content;
+}
+
+# returns the HTTP response object from the URL fetch
+sub fetch_response {
+    my( $self, $contentType, $key ) = @_;
+    my $userid = $self->userid;
+    my $password = $self->password;
+    my $url = $base_url . "?UserID=$userid&Password=$password&Key=$key&Content=$contentType";
+    return $AC->get_url($url);
+}
+
+# returns the HTTP response object from the URL fetch
+sub fetch_cover_response {
+    my( $self, $size, $key ) = @_;
+    my $userid = $self->userid;
+    my $password = $self->password;
+    my $return = $self->return_behavior_on_no_jacket_image;
+    my $url = $cover_base_url . "?UserID=$userid&Password=$password&Return=$return&Type=$size&Value=$key";
+    return $AC->get_url($url);
+}
+
+
+1;
index 4e2074c..4240b4f 100644 (file)
@@ -19,6 +19,7 @@ function acMakeURL(type, key) {
 
 function acCollectData( key, callback ) {
        var context = { key : key, callback: callback, data : {} };
+       acCollectItem(context, 'summary');
        acCollectItem(context, 'reviews');
        acCollectItem(context, 'toc');
        acCollectItem(context, 'excerpt');
index 07864d1..3ea8c4c 100644 (file)
@@ -537,6 +537,7 @@ We recommend that you remove this title from any bookbags it may have been added
 <!ENTITY rdetail.copyInfo.hold "Place Hold">
 <!ENTITY rdetail.extras.summary "Copy Summary">
 <!ENTITY rdetail.extras.browser "Shelf Browser">
+<!ENTITY rdetail.extras.bib_summary "Summary">
 <!ENTITY rdetail.extras.reviews "Reviews">
 <!ENTITY rdetail.extras.toc "Table of Contents">
 <!ENTITY rdetail.extras.excerpt "Excerpt">
index 8dee437..2455b29 100644 (file)
@@ -568,6 +568,7 @@ var rdetailMarcFetched = false;
 function rdetailShowExtra(type, args) {
 
        hideMe($('rdetail_copy_info_div'));
+       hideMe($('rdetail_summary_div'));
        hideMe($('rdetail_reviews_div'));
        hideMe($('rdetail_toc_div'));
        hideMe($('rdetail_anotes_div'));
@@ -581,6 +582,7 @@ function rdetailShowExtra(type, args) {
 
        removeCSSClass($('rdetail_copy_info_link'), 'rdetail_extras_selected');
        removeCSSClass($('rdetail_viewcn_link'), 'rdetail_extras_selected');
+       removeCSSClass($('rdetail_summary_link'), 'rdetail_extras_selected');
        removeCSSClass($('rdetail_reviews_link'), 'rdetail_extras_selected');
        removeCSSClass($('rdetail_toc_link'), 'rdetail_extras_selected');
        removeCSSClass($('rdetail_excerpt_link'), 'rdetail_extras_selected');
@@ -597,6 +599,11 @@ function rdetailShowExtra(type, args) {
                        addCSSClass($('rdetail_copy_info_link'), 'rdetail_extras_selected');
                        break;
 
+        case "summary":
+            addCSSClass($('rdetail_summary_link'), 'rdetail_extras_selected');
+            unHideMe($('rdetail_summary_div'));
+            break;
+
                case "reviews": 
                        addCSSClass($('rdetail_reviews_link'), 'rdetail_extras_selected');
                        unHideMe($('rdetail_reviews_div')); 
@@ -696,6 +703,7 @@ function rdetailShowCNBrowse( cn, loc, depth, fromOnclick ) {
        setSelector( $('cn_browse_selector'), cn );
        hideMe($('rdetail_copy_info_div'));
        hideMe($('rdetail_reviews_div'));
+       hideMe($('rdetail_summary_div'));
        hideMe($('rdetail_toc_div'));
        hideMe($('rdetail_marc_div'));
        unHideMe($('rdetail_cn_browse_div'));
@@ -706,6 +714,11 @@ function rdetailShowCNBrowse( cn, loc, depth, fromOnclick ) {
 
 function rdetailhandleAC(data) {
 
+       if( data.summary.html ) {
+               $('rdetail_summary_div').innerHTML = data.summary.html;
+               unHideMe($('rdetail_summary_link'));
+       }
+
        if( data.reviews.html ) {
                $('rdetail_review_container').innerHTML = data.reviews.html;
                unHideMe($('rdetail_reviews_link'));
index 1913c69..4a2b94d 100644 (file)
                                                class='classic_link'>&rdetail.extras.browser;</a>
                                </td>
 
+                               <td id='rdetail_summary_link' class='hide_me rdetail_extras_td'
+                                       style='padding-right: 15px; padding-left: 15px;' >
+                                       <a href='javascript:rdetailShowExtra("summary");' 
+                                               class='classic_link'>&rdetail.extras.bib_summary;</a>
+                               </td>
+
                                <td id='rdetail_reviews_link' class='hide_me rdetail_extras_td'
                                        style='padding-right: 15px; padding-left: 15px;' >
                                        <a href='javascript:rdetailShowExtra("reviews");' 
@@ -73,6 +79,8 @@
                        style='padding: 10px;'>&common.loading;</div>
                <!--#include virtual="rdetail_copyinfo.xml"-->
 
+               <div id='rdetail_summary_div' class='rdetail_extras_div hide_me'> </div>
+
                <div id='rdetail_reviews_div' class='rdetail_extras_div hide_me'> 
                        <div id='rdetail_review_container'/>
                        <!--