Plugin.pm 4.72 KB
Newer Older
1
2
3
4
5
6
7
8
9
# -*- indent-tabs-mode: nil; -*-
# vim:ft=perl:et:sw=4
# $Id$

# Sympa - SYsteme de Multi-Postage Automatique
#
# Copyright (c) 1997, 1998, 1999 Institut Pasteur & Christophe Wolfhugel
# Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
# 2006, 2007, 2008, 2009, 2010, 2011 Comite Reseau des Universites
10
# Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017 GIP RENATER
11
12
13
# Copyright 2017 The Sympa Community. See the AUTHORS.md file at the top-level
# directory of this distribution and at
# <https://github.com/sympa-community/sympa.git>.
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

package Sympa::Message::Plugin;

use strict;
use warnings;
use English qw(-no_match_vars);
33
use Module::Runtime qw(use_module);
34

35
36
use Sympa::Log;

37
38
39
40
41
42
43
our %handlers;

sub execute {
    my $hook_name = shift;
    my $message   = shift;
    my @params    = @_;

sikeda's avatar
sikeda committed
44
    my $log = Sympa::Log->instance;
45

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
    my $list = $message->{context};

    my $hook_module;
    my $hook_handler;

    unless ($hook_name and $hook_name =~ /\A\w+\z/) {
        die 'bug in Logic.  Ask developer';
    }
    $hook_module = $list->{'admin'}{'message_hook'}->{$hook_name};    #XXX
    unless ($hook_module and $hook_module =~ /\A(::|\w)+\z/) {
        return 0;
    }
    $hook_module = 'Sympa::Message::Plugin::' . $hook_module
        unless $hook_module =~ /::/;

    unless (exists $handlers{$hook_module . '->' . $hook_name}) {
62
        unless (eval { use_module($hook_module); 1; }) {
63
            $log->syslog('err', 'Cannot load hook module %s: %s',
64
65
66
67
68
                $hook_module, $EVAL_ERROR);
            return undef;
        }
        eval { $hook_handler = $hook_module->can($hook_name); };
        if ($EVAL_ERROR) {
69
            $log->syslog('err', 'Cannot get hook handler %s->%s: %s',
70
71
72
73
74
75
76
77
78
79
80
81
82
83
                $hook_module, $hook_name, $EVAL_ERROR);
            return undef;
        }
        $handlers{$hook_module . '->' . $hook_name} = $hook_handler;
    }
    unless (ref($handlers{$hook_module . '->' . $hook_name}) eq 'CODE') {
        return 0;
    }

    my $result;
    eval {
        $result = $hook_module->$hook_name($hook_name, $message, @params);
    };
    if ($EVAL_ERROR) {
84
        $log->syslog('err', 'Error processing %s->%s on %s: %s',
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
            $hook_module, $hook_name, $list, $EVAL_ERROR);
        return undef;
    }
    return $result;
}

1;
__END__

=encoding utf-8

=head1 NAME

Sympa::Message::Plugin - process hooks

=head1 SYNOPSIS

    Sympa::Message::Plugin::execute('post_archive', $message);

=head1 DESCRIPTION

Sympa::Message::Plugin provides hook mechanism to intervene in processing by
Sympa.
Each hook may modify objects (messages and so on) or may break ordinary
processing.

B<Notice>:
112
Hook mechanism is experimental.
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
Module names and interfaces may be changed in the future.

=head2 Methods

=over 4

=item execute ( HOOK_NAME, MESSAGE, [ KEY =E<gt> VAL, ... ] )

Process message hook.

=back

=head2 Hooks

Currently, following hooks are supported:

=over 4

=item pre_distribute

I<Message hook>.
Message had been approved distribution (by scenario or by moderator), however,
it has not been decorated (adding custom subject etc.) nor archived yet.

=item post_archive

I<Message hook>.
Message had been archived, however, it has not been distributed to users
including digest spool; message has not been signed nor encrypted (if
142
necessary).
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179

=back

=head2 How to add a hook to your Sympa

First, write your hook module:

  package My::Hook;

  use constant gettext_id => 'My message hook';
  
  sub post_archive {
      my $module  = shift;    # module name: "My::Hook"
      my $name    = shift;    # handler name: "post_archive"
      my $message = shift;    # Message object
      my %options = @_;
  
      # Processing, possiblly changing $message...
  
      # Return suitable result.
      # If unrecoverable error occurred, you may return undef or simply die.
      return 1;
  }
  
  1;

Then activate hook handler in your list config:

  message_hook
    post_archive My::Hook

=head1 SEE ALSO

L<Sympa::Message::Plugin::FixEncoding> - An example module for message hook.

=head1 HISTORY

sikeda's avatar
sikeda committed
180
L<Sympa::Message::Plugin> appeared on Sympa 6.2.
181
It was initially written by IKEDA Soji <ikeda@conversion.co.jp>.