Price_in_words and retrieve_ex_rate commented out in base hook class (required becaus...
[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         {
71 //              $app->add_application(new example_class); // add menu tab defined by example_class
72         }
73         //
74         //      Install additonal menu options provided by extension
75         //
76         function install_options($app)
77         {
78 //              global $path_to_root;
79 //
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         }
86         
87         function install_access()
88         {
89 //              $security_areas['SA_EXAMPLE'] = array(SS_EXAMPLE|100, _("Example security area."));
90 //
91 //              $security_sections = array(SS_EXAMPLE => _("Example module implementation"));
92 //
93 //              return array($security_areas, $security_sections);
94         }
95
96         //
97         // Price in words. $doc_type is set to document type and can be used to suppress 
98         // price in words printing for selected document types.
99         // Used instead of built in simple english price_in_words() function.
100         //
101         //      Returns: amount in words as string.
102
103 /*      commented out in base class to enable use with hook_invoke_last
104         function price_in_words($amount, $doc_type)
105         {
106         }
107 */
108         //
109         // Exchange rate currency $curr as on date $date.
110         // Keep in mind FA has internally implemented 3 exrate providers
111         // If any of them supports your currency, you can simply use function below
112         // with apprioprate provider set, otherwise implement your own.
113         // Returns: $curr value in home currency units as a real number.
114
115 /*      commented out in base class to enable use with hook_invoke_last
116         function retrieve_exrate($curr, $date)
117         {
118 //              $provider = 'ECB'; // 'ECB', 'YAHOO' or 'GOOGLE'
119 //              return get_extern_rate($curr, $provider, $date);
120                 return null;
121         }
122 */
123         // Generic function called at the end of Tax Report (report 709)
124         // Can be used e.g. for special database updates on every report printing
125         // or to print special tax report footer 
126         //
127         // Returns: nothing
128         function tax_report_done()
129         {
130         }
131         // Following database transaction hooks akcepts array of parameters:
132         // 'cart' => transaction data
133         // 'trans_type' => transaction type
134
135         function db_prewrite(&$cart, $trans_type)
136         {
137                 return true;
138         }
139
140         function db_postwrite(&$cart, $trans_type)
141         {
142                 return true;
143         }
144
145         function db_prevoid($trans_type, $trans_no)
146         {
147                 return true;
148         }
149         /*
150                 This method is called after module install.
151         */
152         function install_extension($check_only=true)
153         {
154                 return true;
155         }
156         /*
157                 This method is called after module uninstall.
158         */
159         function uninstall_extension($check_only=true)
160         {
161                 return true;
162         }
163         /*
164                 This method is called on extension activation for company.
165         */
166         function activate_extension($company, $check_only=true)
167         {
168                 return true;
169         }
170         /*
171                 This method is called when extension is deactivated for company.
172         */
173         function deactivate_extension($company, $check_only=true)
174         {
175                 return true;
176         }
177 }
178
179 /*
180         Installs hooks provided by extension modules
181 */
182 function install_hooks()
183 {
184         global $path_to_root, $Hooks, $installed_extensions;
185
186         $Hooks = array();
187         
188         // include current language related $Hooks object if locale file exists
189         if (file_exists($path_to_root . "/lang/".$_SESSION['language']->code."/locale.inc"))
190         {
191                 include_once($path_to_root . "/lang/".$_SESSION['language']->code."/locale.inc");
192                 $code = $_SESSION['language']->code;
193                 $hook_class = 'hooks_'.$code;
194                 $Hooks[$code] = new $hook_class;
195                 unset($code, $hook_class);
196         }
197         // install hooks provided by active extensions
198         foreach($installed_extensions as $ext) {
199                         $hook_class = 'hooks_'.$ext['package'];
200                         if ($ext['active'] && class_exists($hook_class)) {
201                                 $Hooks[$ext['package']] = new $hook_class;
202                         }
203         }
204 }
205 /*
206         Non active hooks are not included in $Hooks array, so we can use special function to 
207         activate.
208 */
209 function activate_hooks($ext, $comp)
210 {
211         global $Hooks;
212         
213         $hooks = @$Hooks[$ext];
214         if (!$hooks) {
215                 $hookclass = 'hooks_'.$ext;
216                 if (class_exists($hookclass))
217                         $hooks = new $hookclass;
218                 else
219                         return true; // extension does not have hooks file
220         }
221         if (!$hooks)
222                 return false;
223         else
224                 return $hooks->activate_extension($comp, false);
225 }
226 /*
227         Calls hook $method defined in extension $ext (if any)
228 */
229 function hook_invoke($ext, $method, &$data, $opts=null)
230 {
231
232         global $Hooks;
233
234         $ret = null;
235         if (isset($Hooks[$ext]) && method_exists($Hooks[$ext], $method)) {
236                 set_ext_domain('modules/'.$ext);
237                 $ret = $Hooks[$ext]->$method($data, $opts);
238                 set_ext_domain();
239         } 
240         return $ret;
241 }
242
243 /*
244         Calls hook $methods defined in all extensions (if any)
245 */
246 function hook_invoke_all($method, &$data, $opts=null)
247 {
248
249         global $Hooks;
250         
251         $return = array();
252         foreach($Hooks as $ext => $hook)
253                 if (method_exists($hook, $method)) {
254                         set_ext_domain('modules/'.$ext);
255                         $result = $hook->$method($data, $opts);
256                         if (isset($result) && is_array($result)) {
257                                 $return = array_merge_recursive($return, $result);
258                         } else if (isset($result)) {
259                                 $return[] = $result;
260                                 }
261                 }
262         set_ext_domain();
263         return $return;
264 }
265 /*
266         Returns first non-null result returned from hook.
267 */
268 function hook_invoke_first($method, &$data, $opts=null)
269 {
270
271         global $Hooks;
272         
273         $result = null;
274         foreach($Hooks as $ext => $hook) {
275                 if (method_exists($hook, $method)) {
276                         set_ext_domain('modules/'.$ext);
277                         $result = $hook->$method($data, $opts);
278                         if (isset($result))
279                                 break;
280                 }
281         }
282         set_ext_domain();
283         return $result;
284 }
285 /*
286         Returns result of last hook installed. Helps implement hooks overriding by 
287         extensions installed later.
288         
289 */
290 function hook_invoke_last($method, &$data, $opts=null)
291 {
292
293         global $Hooks;
294
295         $found = false;
296         foreach($Hooks as $ext => $hook) {
297                 if (method_exists($hook, $method)) {
298                         $found = $ext;
299                 }
300         }
301         $ret = null;
302         if ($found) {
303                 set_ext_domain('modules/'.$found);
304                 $ret = $Hooks[$found]->$method($data, $opts);
305                 set_ext_domain();
306         }
307         return $ret;
308 }
309 //------------------------------------------------------------------------------------------
310 //      Database transaction hooks.
311 //      $type - type of transaction (simplifies cart processing)
312 //      $cart - transaction cart
313 //      $args is optional array of parameters
314 //
315 // For FA 2.3 prewrite, postwrite and prevoid hooks are implemented for following transaction types:
316 //
317 // ST_BANKPAYMENT, ST_BANKDEPOSIT, ST_BANKTRANSFER,
318 // ST_SALESORDER, ST_SALESQUOTE, ST_SALESINVOICE, ST_CUSTCREDIT, ST_CUSTPAYMENT, ST_CUSTDELIVERY,
319 // ST_LOCTRANSFER, ST_INVADJUST, 
320 // ST_PURCHORDER, ST_SUPPINVOICE, ST_SUPPCREDIT, ST_SUPPAYMENT, ST_SUPPRECEIVE,
321 // ST_WORKORDER, ST_MANUISSUE, ST_MANURECEIVE, 
322
323 /*
324         Invoked after transaction has been read from database to cart.
325         Not implemented yet.
326 */
327 //function hook_db_postread(&$cart, $type)
328 //{
329 //      hook_invoke_all('db_postread', $cart, $type);
330 //}
331
332 /*
333         Invoked before transaction is written to database.
334 */
335 function hook_db_prewrite(&$cart, $type)
336 {
337         return hook_invoke_all('db_prewrite', $cart, $type);
338 }
339
340 /*
341         Invoked after transaction has been written to database.
342 */
343 function hook_db_postwrite(&$cart, $type)
344 {
345         return hook_invoke_all('db_postwrite', $cart, $type);
346 }
347 /*
348         Invoked before transaction is voided
349 */
350 function hook_db_prevoid($type, $type_no)
351 {
352         return hook_invoke_all('db_prevoid', $type, $type_no);
353 }
354
355 //-------------------------------------------------------------------------------------------
356 //
357 //      Various hooks
358 //
359 //      Alternative exchange rates feeds.
360 //
361 function hook_retrieve_exrate($currency, $date)
362 {
363         return hook_invoke_last('retrieve_exrate', $currency, $date);
364 }
365 //
366 // Generic function called at the end of Tax Report (report 709)
367 //
368 function hook_tax_report_done()
369 {
370         return hook_invoke_all('tax_report_done', $dummy);
371 }
372 //
373 //      Amount in words displayed on various documents (especially sales invoice)
374 //
375 function hook_price_in_words($amount, $document)
376 {
377         return hook_invoke_last('price_in_words', $amount, $document);
378 }
379 //
380 //      Session handling hook. This is special case of hook class which have to be run before session is started.
381 //      If fa_session_manager class is defined in any installed extension, this class provides session handling
382 //      for application, otherwise standard php session handling is used.
383 //
384 function hook_session_start($company)
385 {
386         if (class_exists('fa_session_manager')) {
387                 global $SessionManager;
388                 $SessionManager = new fa_session_manager($company);
389                 return $SessionManager->installed;
390         }
391         return false;
392 }