Introduced Piwik as an optional plugin

Change-Id: I57d6961ac9e922e1a661ea94a5a6c7563688ed0b
diff --git a/Changes b/Changes
index aa37e7c..8275345 100755
--- a/Changes
+++ b/Changes
@@ -1,4 +1,4 @@
-0.30 2018-11-09
+0.30 2018-11-12
         - Rewrote backend:
           - Removed dependency of Mojolicious::Plugin::Search.
           - Removed abstract API.
@@ -6,6 +6,8 @@
         - Improved backend test suite.
         - Removed MMap cache from default configuration
           and rely on in-memory cache.
+        - Introduced Piwik as a separated plugin
+          (no longer a mandatory plugin).
 
 0.29 2018-10-05
         - Deprecated Kalamar.api configuration key
diff --git a/README.md b/README.md
index 736a81d..e0eec58 100644
--- a/README.md
+++ b/README.md
@@ -168,7 +168,8 @@
 Some sections of the user interface can be customized
 by adding new
 [content blocks](https://github.com/Akron/Mojolicious-Plugin-TagHelpers-ContentBlock).
-Currently the sections are in ```footer```, in the bottom line of the user interface,
+Currently the documented sections are in ```footer```,
+in the bottom line of the user interface,
 and ```loginInfo```, below the login form, if present.
 
 ## COPYRIGHT AND LICENSE
diff --git a/dev/js/src/api.js b/dev/js/src/api.js
index 0b096f1..1d71550 100644
--- a/dev/js/src/api.js
+++ b/dev/js/src/api.js
@@ -6,10 +6,10 @@
   // http://www.javascriptkit.com/javatutors/loadjavascriptcss.shtml
   // http://stackoverflow.com/questions/6112744/load-javascript-on-demand
 
-  KorAP.URL = KorAP.URL !== undefined ? KorAP.URL : 'http://korap.ids-mannheim.de/kalamar';
+  KorAP.URL = KorAP.URL !== undefined ? KorAP.URL : '';
 
   KorAP.API = KorAP.API || {};
-
+  
   /**
    * Retrieve information about a match
    */
@@ -124,6 +124,14 @@
   KorAP.API.getJSON = function (url, onload) {
     var req = new XMLHttpRequest();
     req.open("GET", url, true);
+
+    // Dispatch global "window" event
+    var reqE = new CustomEvent('korapRequest', {
+      bubbles : false,
+      detail: { "url" : url }
+    });
+    window.dispatchEvent(reqE);
+    
     req.setRequestHeader("Accept", "application/json");
     req.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); 
     req.onreadystatechange = function () {
diff --git a/kalamar.conf b/kalamar.conf
index e194d0a..4d4e94e 100644
--- a/kalamar.conf
+++ b/kalamar.conf
@@ -27,6 +27,10 @@
 # - CHI
 #     See Mojolicious::Plugin::CHI
 
+# For Plugins,
+# - Piwik
+#     See Mojolicious::Plugin::Piwik
+
 # The default Kustvakt api endpoint
 my $api = 'http://localhost:9999/api/';
 {
@@ -47,16 +51,15 @@
     # The name of the base corpus,
     # for query examples (see kalamar.queries.dict)
     # examplecorpus => 'dereko'
+
+    # For further Plugins, add them
+    # to this array:
+    # plugins => []
   },
 
   # See Mojolicious::Plugin::TagHelpers::MailToChiffre
   'TagHelpers-MailToChiffre' => {
     method_name => 'PArok',
     pattern_rotate => 673
-  },
-
-  # See Mojolicious::Plugin::Piwik
-  Piwik => {
-    embed => 0
   }
 }
diff --git a/kalamar.dict b/kalamar.dict
index 9961603..c63a78d 100644
--- a/kalamar.dict
+++ b/kalamar.dict
@@ -205,5 +205,13 @@
       '#default-foundries' => 'Default Foundries',
       'faq' => 'F.A.Q.'
     }
+  },
+  Piwik => {
+    en => {
+      'HowToOptOut' => 'How to opt-out from Piwik/Matomo tracking?'
+    },
+    de => {
+      'HowToOptOut' => 'Wie kann ich die Weitergabe meiner Daten per Matomo/Piwik unterbinden?'
+    }
   }
 };
diff --git a/lib/Kalamar.pm b/lib/Kalamar.pm
index 83cea41..68b73dc 100644
--- a/lib/Kalamar.pm
+++ b/lib/Kalamar.pm
@@ -5,6 +5,7 @@
 use Mojo::File;
 use Mojo::JSON 'decode_json';
 use Mojo::Util qw/url_escape/;
+use List::Util 'none';
 
 # Minor version - may be patched from package.json
 our $VERSION = '0.30';
@@ -149,7 +150,6 @@
     'ClientIP',                  # Get client IP from X-Forwarded-For
     'ClosedRedirect',            # Redirect with OpenRedirect protection
     'TagHelpers::ContentBlock',  # Flexible content blocks
-    'Piwik'                      # Integrate Piwik/Matomo Analytics
   ) {
     $self->plugin($_);
   };
@@ -171,6 +171,23 @@
     $self->plugin('MailException' => $self->config('MailException'));
   };
 
+  # Load further plugins
+  if (exists $conf->{'plugins'}) {
+    foreach (@{$conf->{'plugins'}}) {
+      $self->plugin('Kalamar::Plugin::' . $_);
+    };
+  };
+
+  # Deprecated Legacy code -
+  # TODO: Remove 2019-02
+  if ($self->config('Piwik') &&
+        none { $_ eq 'Piwik' } @{$conf->{plugins} // []}) {
+    use Data::Dumper;
+    warn Dumper $self->config('Piwik');
+    $self->log->error('Piwik is no longer considered a mandatory plugin');
+    $self->plugin('Piwik');
+  };
+
   # Configure documentation navigation
   my $navi = Mojo::File->new($self->home->child('templates','doc','navigation.json'))->slurp;
   $self->config(navi => decode_json($navi)) if $navi;
diff --git a/lib/Kalamar/Plugin/Piwik.pm b/lib/Kalamar/Plugin/Piwik.pm
new file mode 100644
index 0000000..a4dfb68
--- /dev/null
+++ b/lib/Kalamar/Plugin/Piwik.pm
@@ -0,0 +1,44 @@
+package Kalamar::Plugin::Piwik;
+use Mojo::Base 'Mojolicious::Plugin';
+
+sub register {
+  my ($plugin, $mojo, $param) = @_;
+
+  # Load Piwik if not yet loaded
+  unless (exists $mojo->renderer->helpers->{piwik_tag}) {
+    $mojo->plugin('Piwik');
+  };
+
+  # Add opt-out to FAQ
+  $mojo->content_block(
+    'faq' => {
+      inline => '<section name="piwik-opt-out">' .
+        '<h3><%= loc("Piwik_HowToOptOut", "How can I opt-out?") %></h3>' .
+        '<%= piwik_tag "opt-out" %>' .
+        '</section>'
+      }
+  );
+
+  # Add piwik tag to scripts
+  $mojo->content_block(scripts => {
+    inline => '<%= piwik_tag %>'
+  });
+
+  # Add event handler for korap requests
+  $mojo->content_block(scripts => {
+    inline => <<'SCRIPT'
+%= javascript begin
+window.addEventListener('korapRequest', function(e) {
+  _paq.push(['setReferrerUrl', location.href]);
+  _paq.push(['setCustomUrl', e.detail.url]);
+  _paq.push(['trackPageView'])
+% end
+SCRIPT
+  });
+};
+
+
+1;
+
+
+__END__
diff --git a/t/plugin/piwik.t b/t/plugin/piwik.t
new file mode 100644
index 0000000..69cd401
--- /dev/null
+++ b/t/plugin/piwik.t
@@ -0,0 +1,25 @@
+use Mojo::Base -strict;
+use Test::More;
+use Test::Mojo;
+
+# Test the documentation
+my $t = Test::Mojo->new('Kalamar');
+
+$t->app->plugin('Piwik' => {
+  url => 'https://piwik.korap.ids-mannheim.de/',
+  site_id => 1,
+  embed => 1
+});
+
+# Load piwik
+$t->app->plugin('Kalamar::Plugin::Piwik');
+
+$t->get_ok('/doc/faq')
+  ->status_is(200)
+  ->text_like('section[name=piwik-opt-out] h3', qr!can I opt-out!)
+  ->element_exists('section[name=piwik-opt-out] iframe')
+  ->content_like(qr!var _paq!)
+  ->content_like(qr!window\.addEventListener\('korapRequest!)
+  ;
+
+done_testing();
diff --git a/templates/doc/faq.html.ep b/templates/doc/faq.html.ep
index 7a3284d..26eb0a3 100644
--- a/templates/doc/faq.html.ep
+++ b/templates/doc/faq.html.ep
@@ -19,3 +19,5 @@
   <p>Please refer to our public ticketing system <%= doc_ext_link_to 'for the frontend at GitHub', 'https://github.com/KorAP/Kalamar/issues' %>, to report on any issues. If you don't have a GitHub account, please send us an <%= mail_to_chiffre join('@', 'korap', 'ids-mannheim.de'), subject => 'I found an issue', begin %>e-mail<% end %>.</p>
   %# This option is the preferred one because it gathers some (and will in time gather more) important versioning data.
 </section>
+
+%= content_block 'faq'
diff --git a/templates/layouts/main.html.ep b/templates/layouts/main.html.ep
index 5f9983c..88c364d 100644
--- a/templates/layouts/main.html.ep
+++ b/templates/layouts/main.html.ep
@@ -81,6 +81,7 @@
       %= include 'partial/footer'
     % };
     %= notifications 'Kalamar::Plugin::Notifications'
-    %= piwik_tag
+
   </body>
+  %= content_block 'scripts'
 </html>