mirror of
https://github.com/Piwigo/Piwigo.git
synced 2026-08-09 18:23:18 +02:00
copy from DokuWiki
@@ -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
|
||||
<!-- Template for the copyright selector -->
|
||||
<div id="copyrights">
|
||||
{'Copyright'|@translate}
|
||||
<select name="copyrightID">
|
||||
<option value="0">--</option>
|
||||
{html_options options=$CRoptions}
|
||||
</select>
|
||||
</div>
|
||||
```
|
||||
|
||||
#### 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 = "#<td><strong>{'Creation date'#";
|
||||
|
||||
// We use the <tr> from the Creation date, and give them a new <tr>
|
||||
$replacement = '<td><strong>{\'Copyright\'|@translate}</strong></td>
|
||||
<td>
|
||||
<select id="copyright-{$element.ID}" name="copyright-{$element.ID}">
|
||||
<option value="0">--</option>
|
||||
{html_options options=$CRoptions selected=$CRcopyrights[$element.ID]}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><strong>{\'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!
|
||||
Reference in New Issue
Block a user