diff --git a/Plugin-Tutorial:-Several-tricks-from-the-Copyrights-plugin.md b/Plugin-Tutorial:-Several-tricks-from-the-Copyrights-plugin.md
new file mode 100644
index 0000000..98c272b
--- /dev/null
+++ b/Plugin-Tutorial:-Several-tricks-from-the-Copyrights-plugin.md
@@ -0,0 +1,468 @@
+# Plugin Tutorial: Several tricks from the Copyrights plugin
+
+In this tutorial you will learn more about the basics of plugin
+development for Piwigo. This tutorial is a follow up on [Tutorial: Hello
+World!](https://github.com/Piwigo/Piwigo/wiki/Plugin-Tutorial:-Hello-world!). The entire plugin can be installed from the
+extension gallery under the name
+['Copyrights'](http://piwigo.org/ext/extension_view.php?eid=537). Note
+that this tutorial follows the v1.0 revision of this plugin.
+
+Since the plugin is relatively large to put all the code on this page,
+we only explicitly put that code here that is important and clarifies
+the ideas explained. The reader should read the rest of the code from
+the sources pointed to above.
+
+## Introduction
+
+First of all, download the source code of the [Skeleton
+plugin](http://piwigo.org/ext/extension_view.php?eid=543). We will use
+that as basis for this plugin.
+
+### Outline
+
+With this plugin we want to achieve the following:
+
+1. Somewhere we want to manage our copyrights.
+2. Somehow copyrights must be added to photos.
+3. Somehow the copyright must be displayed when visitors view a photo.
+
+Therefore, we will write code for:
+
+1. An administration panel, where the admin can create and edit plugins
+2. An extension to the Batch manager (using events) so that copyrights
+ can be added to photos.
+3. Another event-hook that will display the copyright when a photo is
+ viewed.
+
+## The admin panel
+
+For the admin panel we need to do two things. First add a link to the
+plugins menu, second create an admin page.
+
+### The link in the menu
+
+To add a link to the menu of plugins we put the following code in
+main.inc.php. This is our first serious encounter with event handlers.
+To see what events are available we refer to the [Event tracer
+plugin](http://piwigo.org/ext/extension_view.php?eid=288).
+
+``` php
+/* +-----------------------------------------------------------------------+
+ * | Plugin admin |
+ * +-----------------------------------------------------------------------+ */
+
+// Add an entry to the plugins menu
+add_event_handler('get_admin_plugin_menu_links', 'copyrights_admin_menu');
+function copyrights_admin_menu($menu) {
+ array_push(
+ $menu,
+ array(
+ 'NAME' => 'Copyrights',
+ 'URL' => get_admin_plugin_menu_link(dirname(__FILE__)).'/admin.php'
+ )
+ );
+ return $menu;
+}
+```
+
+This adds an event handler to the event 'get_admin_plugin_menu_links'.
+The added handler is the function 'copyrights_admin_menu' that we define
+right below it. It consists of a simple array_push() to add our link to
+the plugins menu.
+
+Lets move on to the content of admin.php, since that is what we are
+linking to.
+
+### The admin page
+
+We would like to do several things on the admin page. First of all, we
+want to be able to create plugins. Next we should be able to view them,
+and lastly, we want to be able to edit existing copyrights.
+
+Firstly, however, we load the language file and perform a security
+check.
+
+``` php
+load_language('plugin.lang', COPYRIGHTS_PATH);
+
+// Check access and exit when user status is not ok
+check_status(ACCESS_ADMINISTRATOR);
+```
+
+The rest of the code of the admin page does not add much to the learning
+of plugin writing for Piwigo. It is best read from source directly. The
+code is commented farely well.
+
+It is, however, good to mention the special use of the '$tab' variable.
+This is a variable that is used by Piwigo to create the tabbed layout
+they use. The Copyrights plugin makes use of this variable for deleting
+and updating Copyrights as if those are 'unvisible' tabs.
+
+## Extending the Batch manager
+
+The Batch manager comes with two modes, so we will have to write
+extensions to both.
+
+### Batch Mode
+
+Here we will again use event handlers to extend the functionality of
+Piwigo. We use two of them:
+
+- One to add the copyrights selector to the possible actions of the
+ Batch Manager
+- The second to catch the 'Submit' button of the Batch Manager, and
+ update the database
+
+``` php
+// Add copyrights drop down menu to the batch manager
+add_event_handler('loc_end_element_set_global', 'copyrights_batch_global');
+// Add handler to the submit event of the batch manager
+add_event_handler('element_set_global_action', 'copyrights_batch_global_submit', 50, 2);
+```
+
+Now we should specify the contents of the functions
+'copyrights_batch_global' and 'copyrights_batch_global_submit'.
+
+#### copyrights_batch_global
+
+``` php
+function copyrights_batch_global()
+{
+ global $template;
+
+ load_language('plugin.lang', dirname(__FILE__).'/');
+
+ // Assign the template for batch management
+ $template->set_filename('CR_batch_global', dirname(__FILE__).'/batch_global.tpl');
+
+ // Fetch all the copyrights and assign them to the template
+ $query = sprintf(
+ 'SELECT `cr_id`,`name`
+ FROM %s
+ WHERE `visible`<>0
+ ;',
+ COPYRIGHTS_ADMIN);
+ $result = pwg_query($query);
+ $CRoptions = array();
+ while ($row = pwg_db_fetch_assoc($result)) {
+ $CRoptions[$row['cr_id']] = $row['name'];
+ }
+ $template->assign('CRoptions', $CRoptions);
+
+
+ // Add info on the "choose action" dropdown in the batch manager
+ $template->append('element_set_global_plugins_actions', array(
+ 'ID' => 'copyrights', // ID of the batch manager action
+ 'NAME' => l10n('Edit copyright'), // Description of the batch manager action
+ 'CONTENT' => $template->parse('CR_batch_global', true)
+ )
+ );
+}
+```
+
+As can be seen, we again load the language file. Next we add the
+contents of 'batch_global.tpl' to the template and finally assign the
+list of copyrights obtained from the database to this template.
+
+The file 'batch_global.tpl' contains a small bit of Smarty code to
+create a copyright selector.
+
+``` smarty
+
+
+ {'Copyright'|@translate}
+
+
+```
+
+#### copyrights_batch_global_submit
+
+When the 'Submit' button is clicked, an event is fired. We attached the
+following function to this event.
+
+``` php
+// Process the submit action
+function copyrights_batch_global_submit($action, $collection)
+{
+ // If its our plugin that is called
+ if ($action == 'copyrights')
+ {
+ $crID = pwg_db_real_escape_string($_POST['copyrightID']);
+
+ // Delete any previously assigned copyrights
+ if (count($collection) > 0) {
+ $query = sprintf(
+ 'DELETE
+ FROM %s
+ WHERE media_id IN (%s)
+ ;',
+ COPYRIGHTS_MEDIA, implode(',', $collection));
+ pwg_query($query);
+ }
+
+ // Add the copyrights from the submit form to an array
+ $edits = array();
+ foreach ($collection as $image_id)
+ {
+ array_push(
+ $edits,
+ array(
+ 'media_id' => $image_id,
+ 'cr_id' => $crID,
+ )
+ );
+ }
+
+ // Insert the array into the database
+ mass_inserts(
+ COPYRIGHTS_MEDIA, // Table name
+ array_keys($edits[0]), // Columns
+ $edits // Data
+ );
+ }
+}
+```
+
+So we first check whether it was our action ('Edit copyright') was
+chosen in the action list of the Batch Manager. If so, we obtain the
+chosen copyright id from the form $\_POST variable.
+
+Next we assign the the copyrights to all photos in the $collection, by
+first deleting any previously made assignments, and afterwards inserting
+the whole bunch with Piwigo's mass_inserts function.
+
+### Single Mode
+
+To extend the 'Single Mode' or 'Unit Mode' of the Batch Manager, we have
+to use prefilters. Prefilters are a really nifty feature of Smarty code.
+See [their
+site](http://www.smarty.net/docsv2/en/advanced.features.prefilters.tpl)
+for more information on all the functionality.
+
+When speaking for Piwigo, generally a prefilter can be attached to any
+file X.tpl that exists in the template folder.
+
+To attach a prefilter to such a file, one should find an event near to
+where the X.tpl is being used. This will be more clear below.
+
+##### Setting the prefilter
+
+For the Copyrights plugin, we want to modify the Smarty code of the
+batch_manager_unit.tpl file. We therefore use the following code.
+
+``` php
+// Add event handlers for the prefilter
+add_event_handler('loc_end_element_set_unit', 'CR_set_prefilter_batch_single', 55 );
+```
+
+This attaches the function 'CR_set_prefilter_batch_single' to the event
+'loc_end_element_set_unit' which is fired when Piwigo starts loading the
+Single Mode page of the Batch Manager.
+
+The event handler function then attaches a prefilter to
+batch_manager_unit.tpl.
+
+``` php
+// Add a prefilter to the template
+function CR_set_prefilter_batch_single()
+{
+ global $template;
+ $template->set_prefilter('batch_manager_unit', 'CR_batch_single');
+}
+```
+
+This means that when Smarty starts rendering batch_manager_unit.tpl, it
+will first execute CR_batch_single.
+
+That particular function will of course add the copyright selector to
+the page.
+
+``` php
+// Insert the copyright selector to the template
+function CR_batch_single($content, &$smarty)
+{
+ $search = "#
{'Creation date'#";
+
+ // We use the
from the Creation date, and give them a new
+ $replacement = '
{\'Copyright\'|@translate}
+
+
+
+
+
+
+
{\'Creation date\'';
+
+ return preg_replace($search, $replacement, $content);
+}
+```
+
+##### Assigning variables in Smarty
+
+Now that the Smarty code of the Single Mode is extended we obviously
+want to assign the variables. This can be done with another event
+handler.
+
+``` php
+// Change the variables used by the function that changes the template
+add_event_handler('loc_end_element_set_unit', 'CR_add_batch_single_vars_to_template');
+```
+
+Now the smart reader might object that we have to event handlers
+attached to the same event, the one depending on the other. How do we
+assure that the prefilter is executed before we try to assign the
+variables? The even smarter reader might have noticed that the first
+event_handler line ended with ', 55 );'. This number 55 states the
+priority of the event handler, which defaults to 50. Hence the first
+event handler will indeed be executed before the second.
+
+The contents of the second event handler are as follows.
+
+``` php
+// Assign the variables to the Smarty template
+function CR_add_batch_single_vars_to_template()
+{
+ global $template;
+
+ load_language('plugin.lang', dirname(__FILE__).'/');
+
+ // Fetch all the copyrights and assign them to the template
+ $query = sprintf(
+ 'SELECT `cr_id`,`name`
+ FROM %s
+ WHERE `visible`<>0
+ ;',
+ COPYRIGHTS_ADMIN);
+ $result = pwg_query($query);
+
+ $CRoptions = array();
+ while ($row = pwg_db_fetch_assoc($result)) {
+ $CRoptions[$row['cr_id']] = $row['name'];
+ }
+ $template->assign('CRoptions', $CRoptions);
+
+ // Get the copyright for each element
+ $query = sprintf(
+ 'SELECT `media_id`, `cr_id`
+ FROM %s
+ ;',
+ COPYRIGHTS_MEDIA);
+ $result = pwg_query($query);
+
+ $CRcopyrights = array();
+ while ($row = pwg_db_fetch_assoc($result)) {
+ $CRcopyrights[$row['media_id']] = $row['cr_id'];
+ }
+
+ // Assign the copyrights to the template
+ $template->assign('CRcopyrights', $CRcopyrights);
+}
+```
+
+Note that we again load the language file. Furthermore we just select
+the visible copyrights from the database and assign them to the
+copyright selector.
+
+##### Catching the 'Submit'
+
+Finally we want to really do something with the selected copyrights. So
+we will have to attach something to the submit button. We will again use
+an event handler.
+
+``` php
+add_event_handler('loc_begin_element_set_unit', 'CR_batch_single_submit', 50 );
+```
+
+The content of this event handler checks whether the $\_POST\['submit'\]
+variable is set. If so it executes some lines of code that very closely
+resemble the submit code for the Global Mode.
+
+``` php
+// Catch the submit and update the copyrights tables
+function CR_batch_single_submit()
+{
+ if (isset($_POST['submit']))
+ {
+ // The image id's:
+ $collection = explode(',', $_POST['element_ids']);
+
+ // Delete all existing id's of which the copyright is going to be set
+ if (count($collection) > 0) {
+ $query = sprintf(
+ 'DELETE
+ FROM %s
+ WHERE media_id IN (%s)
+ ;',
+ COPYRIGHTS_MEDIA, implode(',', $collection));
+ pwg_query($query);
+ }
+
+ // Add all copyrights to an array
+ $edits = array();
+ foreach ($collection as $image_id) {
+ // The copyright id's
+ $crID = pwg_db_real_escape_string($_POST['copyright-'.$image_id]);
+
+ array_push(
+ $edits,
+ array(
+ 'media_id' => $image_id,
+
+ 'cr_id' => $crID,
+ )
+ );
+ }
+
+ // Insert the array to the database
+ mass_inserts(
+ COPYRIGHTS_MEDIA, // Table name
+ array_keys($edits[0]), // Columns
+ $edits // Data
+ );
+ }
+}
+```
+
+## Modifying copyrights via picture_modify.php
+
+This part of the plugin works in the same way as the single mode of the
+Batch Manager.
+
+1. It attaches an event handler, to set a prefilter.
+2. The prefilter adds some Smarty code to the template.
+3. Another event handler assigns the variables in the Smarty code.
+4. Yet another event handler catches the 'Submit' button and updates
+ the database.
+
+The reader should try to understand how this is done by looking at the
+source code of the plugin.
+
+## Showing the copyrights to visitors
+
+To show the copyrights to people visiting the gallery, we again make use
+of a prefilter. Just like the ways mentioned above. It should by now be
+pretty straight forward to learn this from the source code.
+
+## Using maintain.inc.php
+
+In the file maintain.inc.php one can put code that should be executed at
+install, activation or deletion of a plugin. The reader can see from the
+source code of the plugin that the Copyrights plugin inserts several
+default copyrights into the database by using this file.
+
+## Conclusion
+
+One might have noticed from this tutorial that event handlers and in
+particular prefilters are a mighty tool in developing Piwigo extensions.
+Still it is difficult to cover everything in a single tutorial.
+Therefore, the reader should browse and study the source code of Piwigo
+itself and of other plugins, to gain a stronger sense of how to use
+these nifty features. In particular, one should also read tutorials on
+Smarty. Note for example that besides prefilters there also exist
+postfilters!
\ No newline at end of file