Added core translation support for modules.
[fa-stable.git] / includes / hooks.inc
1 <?php
2 /**********************************************************************
3     Copyright (C) FrontAccounting, LLC.
4         Released under the terms of the GNU General Public License, GPL, 
5         as published by the Free Software Foundation, either version 3 
6         of the License, or (at your option) any later version.
7     This program is distributed in the hope that it will be useful,
8     but WITHOUT ANY WARRANTY; without even the implied warranty of
9     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
10     See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
11 ***********************************************************************/
12 //
13 // FrontAccounting extension modules integration.
14 // This file is included in session.inc even before session is started,
15 // and includes hooks.php connector files from all installed extensions.
16 // To make hooks active install_hooks() have to be called after interface
17 // language is set.
18 //
19 // To find how various hooks are processed look into respective hook_* functions below.
20 //
21 class hooks {
22         var $module_name; // extension module name.
23
24         // 
25         // Helper for updating databases with extension scheme
26         //
27         // $comp can be company number, -1 for all, 
28         // $updates - table of filename => array(table, field, property)
29         // $check_only - don't update database, check table/field/property existence only
30         //
31         function update_databases($comp, $updates, $check_only=false)
32         {
33                 global $db_connections, $path_to_root;
34         
35                 if ($comp == -1) 
36                         $conn = $db_connections;
37                 else
38                         $conn = array( $comp => $db_connections[$comp]);
39                 $result = true;
40
41                 foreach($conn as $comp => $con) {
42                         set_global_connection($comp);
43                         foreach($updates as $file => $update) {
44                                 $table = @$update[0];
45                                 $field = @$update[1];
46                                 $properties = @$update[2];
47
48                                 $ok = check_table($con['tbpref'], $table, $field, $properties) == 0;
49
50                                 if (!$check_only && !$ok) {
51                                         $ok = db_import($path_to_root.'/modules/'.$this->module_name.'/sql/'.$file,
52                                                 $con);
53                                 }
54                                 $result &= $ok;
55                                 if (!$result)
56                                         break;
57                         }
58                         db_close();
59                         if (!$result)
60                                 break;
61                 }
62                 set_global_connection(0); // return to siteadmin account
63
64                 return $result;
65         }
66         //
67         //      Install additional tabs provided by extension
68         //
69         function install_tabs($app) {
70 //              set_ext_domain('modules/example');        // set text domain for gettext
71 //              $app->add_application(new example_class); // add menu tab defined by example_class
72 //              set_ext_domain();
73         }
74         //
75         //      Install additonal menu options provided by extension
76         //
77         function install_options($app) {
78 //              global $path_to_root;
79 //              set_ext_domain('modules/example');
80 //              switch($app->id) {
81 //                      case 'orders':
82 //                              $app->add_rapp_function( 0, _("&Example option"), 
83 //                                      $path_to_root.'/modules/example/example.php?', 'SA_OPEN');
84 //              }
85 //              set_ext_domain();
86         }
87         //
88         // Price in words. $doc_type is set to document type and can be used to suppress 
89         // price in words printing for selected document types.
90         // Used instead of built in simple english price_in_words() function.
91         //
92         //      Returns: amount in words as string.
93
94         function price_in_words($amount, $doc_type)
95         {
96         }
97
98         //
99         // Exchange rate currency $curr as on date $date.
100         // Keep in mind FA has internally implemented 3 exrate providers
101         // If any of them supports your currency, you can simply use function below
102         // with apprioprate provider set, otherwise implement your own.
103         // Returns: $curr value in home currency units as a real number.
104
105         function retrieve_exrate($curr, $date)
106         {
107 //              $provider = 'ECB'; // 'ECB', 'YAHOO' or 'GOOGLE'
108 //              return get_extern_rate($curr, $provider, $date);
109                 return null;
110         }
111
112         // Generic function called at the end of Tax Report (report 709)
113         // Can be used e.g. for special database updates on every report printing
114         // or to print special tax report footer 
115         //
116         // Returns: nothing
117         function tax_report_done()
118         {
119         }
120         // Following database transaction hooks akcepts array of parameters:
121         // 'cart' => transaction data
122         // 'trans_type' => transaction type
123
124         function db_prewrite(&$cart, $trans_type)
125         {
126                 return true;
127         }
128
129         function db_postwrite(&$cart, $trans_type)
130         {
131                 return true;
132         }
133
134         function db_prevoid($trans_type, $trans_no)
135         {
136                 return true;
137         }
138 }
139 //
140 // include all extensions hook files.
141 //
142 foreach ($installed_extensions as $ext)
143 {
144         if (file_exists($path_to_root.'/'.$ext['path'].'/hooks.php'))
145                 include_once($path_to_root.'/'.$ext['path'].'/hooks.php');
146 }
147
148 /*
149         Installs hooks provided by extension modules
150 */
151 function install_hooks() {
152         global $path_to_root, $Hooks, $installed_extensions;
153
154         $Hooks = array();
155         
156         // include current language related $Hooks object if locale file exists
157         if (file_exists($path_to_root . "/lang/".$_SESSION['language']->code."/locale.inc"))
158         {
159                 include_once($path_to_root . "/lang/".$_SESSION['language']->code."/locale.inc");
160                 $code = $_SESSION['language']->code;
161                 $hook_class = 'hooks_'.$code;
162                 $Hooks[$code] = new $hook_class;
163                 unset($code, $hook_class);
164         }
165         // install hooks provided by active extensions
166         foreach($installed_extensions as $ext) {
167                         $hook_class = 'hooks_'.$ext['package'];
168                         if ($ext['active'] && class_exists($hook_class)) {
169                                 $Hooks[$ext['package']] = new $hook_class;
170                         }
171         }
172 }
173 /*
174         Non active hooks are not included in $Hooks array, so we can use special function to 
175         activate.
176 */
177 function activate_hooks($ext, $comp) {
178         global $Hooks;
179         
180         $hooks = @$Hooks[$ext];
181         if (!$hooks) {
182                 $hookclass = 'hooks_'.$ext;
183                 if (class_exists($hookclass))
184                         $hooks = new $hookclass;
185                 else
186                         return true; // extension does not have hooks file
187         }
188         if (!$hooks)
189                 return false;
190         else
191                 return $hooks->activate_extension($comp, false);
192 }
193 /*
194         Calls hook $method defined in extension $ext (if any)
195 */
196 function hook_invoke($ext, $method, &$data, $opts=null) {
197
198         global $Hooks;
199
200         $ret = null;
201         if (isset($Hooks[$ext]) && method_exists($Hooks[$ext], $method)) {
202                 set_ext_domain('modules/'.$ext);
203                 $ret = $Hooks[$ext]->$method($data, $opts);
204                 set_ext_domain();
205         } 
206         return $ret;
207 }
208
209 /*
210         Calls hook $methods defined in all extensions (if any)
211 */
212 function hook_invoke_all($method, &$data, $opts=null) {
213
214         global $Hooks;
215         
216         $result = array();
217         foreach($Hooks as $ext => $hook)
218                 if (method_exists($hook, $method)) {
219                         set_ext_domain('modules/'.$ext);
220                         $result = $hook->$method($data, $opts);
221                         if (isset($result) && is_array($result)) {
222                                 $return = array_merge_recursive($return, $result);
223                         } else if (isset($result)) {
224                                 $return[] = $result;
225                                 }
226                 }
227         set_ext_domain();
228         return $result;
229 }
230 /*
231         Returns first non-null result returned from hook.
232 */
233 function hook_invoke_first($method, &$data, $opts=null) {
234
235         global $Hooks;
236         
237         $result = null;
238         foreach($Hooks as $ext => $hook) {
239                 if (method_exists($hook, $method)) {
240                         set_ext_domain('modules/'.$ext);
241                         $result = $hook->$method($data, $opts);
242                         if (isset($result))
243                                 break;
244                 }
245         }
246         set_ext_domain();
247         return $result;
248 }
249 /*
250         Returns result of last hook installed. Helps implement hooks overriding by 
251         extensions installed later.
252         
253 */
254 function hook_invoke_last($method, &$data, $opts=null) {
255
256         global $Hooks;
257
258         $found = false;
259         foreach($Hooks as $ext => $hook) {
260                 if (method_exists($hook, $method)) {
261                         $found = $ext;
262                 }
263         }
264         $ret = null;
265         if ($found) {
266                 set_ext_domain('modules/'.$found);
267                 $ret = $Hooks[$found]->$method($data, $opts);
268                 set_ext_domain();
269         }
270         return $ret;
271 }
272 //------------------------------------------------------------------------------------------
273 //      Database transaction hooks.
274 //      $type - type of transaction (simplifies cart processing)
275 //      $cart - transaction cart
276 //      $args is optional array of parameters
277 //
278 // For FA 2.3 prewrite, postwrite and prevoid hooks are implemented for following transaction types:
279 //
280 // ST_BANKPAYMENT, ST_BANKDEPOSIT, ST_BANKTRANSFER,
281 // ST_SALESORDER, ST_SALESQUOTE, ST_SALESINVOICE, ST_CUSTCREDIT, ST_CUSTPAYMENT, ST_CUSTDELIVERY,
282 // ST_LOCTRANSFER, ST_INVADJUST, 
283 // ST_PURCHORDER, ST_SUPPINVOICE, ST_SUPPCREDIT, ST_SUPPAYMENT, ST_SUPPRECEIVE,
284 // ST_WORKORDER, ST_MANUISSUE, ST_MANURECEIVE, 
285
286 /*
287         Invoked after transaction has been read from database to cart.
288         Not implemented yet.
289 */
290 //function hook_db_postread(&$cart, $type)
291 //{
292 //      hook_invoke_all('db_postread', $cart, $type);
293 //}
294
295 /*
296         Invoked before transaction is written to database.
297 */
298 function hook_db_prewrite(&$cart, $type)
299 {
300         return hook_invoke_all('db_prewrite', $cart, $type);
301 }
302
303 /*
304         Invoked after transaction has been written to database.
305 */
306 function hook_db_postwrite(&$cart, $type)
307 {
308         return hook_invoke_all('db_postwrite', $cart, $type);
309 }
310 /*
311         Invoked before transaction is voided
312 */
313 function hook_db_prevoid($type, $type_no)
314 {
315         return hook_invoke_all('db_prevoid', $type, $type_no);
316 }
317
318 //-------------------------------------------------------------------------------------------
319 //
320 //      Various hooks
321 //
322 //      Alternative exchange rates feeds.
323 //
324 function hook_retrieve_exrate($currency, $date)
325 {
326         return hook_invoke_last('retrieve_exrate', $currency, $date);
327 }
328 //
329 // Generic function called at the end of Tax Report (report 709)
330 //
331 function hook_tax_report_done()
332 {
333         return hook_invoke_all('tax_report_done', $dummy);
334 }
335 //
336 //      Amount in words displayed on various documents (especially sales invoice)
337 //
338 function hook_price_in_words($amount, $document)
339 {
340         return hook_invoke_last('price_in_words', $amount, $document);
341 }