From 195456fa7670a4f142d640068461798b72d53814 Mon Sep 17 00:00:00 2001 From: Pierrick Le Gall Date: Sat, 29 Apr 2023 17:47:36 +0200 Subject: [PATCH] copy from DokuWiki --- ...veral-tricks-from-the-Copyrights-plugin.md | 468 ++++++++++++++++++ 1 file changed, 468 insertions(+) create mode 100644 Plugin-Tutorial:-Several-tricks-from-the-Copyrights-plugin.md 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