Rewrites/fixes in extension registration
[mailer.git] / inc / extensions-functions.php
1 <?php
2 /************************************************************************
3  * Mailer v0.2.1-FINAL                                Start: 10/25/2009 *
4  * ===================                          Last change: 10/25/2009 *
5  *                                                                      *
6  * -------------------------------------------------------------------- *
7  * File              : extensions-functions.php                         *
8  * -------------------------------------------------------------------- *
9  * Short description : Extension management                             *
10  * -------------------------------------------------------------------- *
11  * Kurzbeschreibung  : Erweiterungen-Management                         *
12  * -------------------------------------------------------------------- *
13  * $Revision::                                                        $ *
14  * $Date::                                                            $ *
15  * $Tag:: 0.2.1-FINAL                                                 $ *
16  * $Author::                                                          $ *
17  * Needs to be in all Files and every File needs "svn propset           *
18  * svn:keywords Date Revision" (autoprobset!) at least!!!!!!            *
19  * -------------------------------------------------------------------- *
20  * Copyright (c) 2003 - 2009 by Roland Haeder                           *
21  * Copyright (c) 2009, 2010 by Mailer Developer Team                    *
22  * For more information visit: http://www.mxchange.org                  *
23  *                                                                      *
24  * This program is free software; you can redistribute it and/or modify *
25  * it under the terms of the GNU General Public License as published by *
26  * the Free Software Foundation; either version 2 of the License, or    *
27  * (at your option) any later version.                                  *
28  *                                                                      *
29  * This program is distributed in the hope that it will be useful,      *
30  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
31  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
32  * GNU General Public License for more details.                         *
33  *                                                                      *
34  * You should have received a copy of the GNU General Public License    *
35  * along with this program; if not, write to the Free Software          *
36  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,               *
37  * MA  02110-1301  USA                                                  *
38  ************************************************************************/
39
40 // Some security stuff...
41 if (!defined('__SECURITY')) {
42         die();
43 } // END - if
44
45 // Load the extension and maybe found language and function files.
46 function loadExtension ($ext_name, $ext_mode = 'init', $ext_ver = '', $dry_run = false) {
47         // If this happens twice, we need the bug report from you, except for updates/tests
48         if ((isset($GLOBALS['loaded_extension'][$ext_name][$ext_mode])) && (!in_array($ext_mode, array('update', 'test')))) {
49                 debug_report_bug(__FUNCTION__, __LINE__, '() is called twice: ext_name=' . $ext_name . ', ext_mode='. $ext_mode . ',ext_sqls=' . print_r(getExtensionSqls(), true) . ', ext_register_running=' . print_r($GLOBALS['ext_register_running'], true) . ', ext_running_updates=' . print_r($GLOBALS['ext_running_updates'], true));
50         } // END - if
51
52         // Make sure this situation can only happen once
53         $GLOBALS['loaded_extension'][$ext_name][$ext_mode] = true;
54
55         // Set extension mode
56         setExtensionMode($ext_mode);
57
58         // Set current extension name
59         setCurrentExtensionName($ext_name);
60
61         if (!empty($ext_ver)) {
62                 // Set current extension version
63                 setCurrentExtensionVersion($ext_ver);
64         } else {
65                 // Set it to 0.0
66                 setCurrentExtensionVersion('0.0');
67
68                 // In all but test-mode we need these messages to debug! Please report all (together, e.g.)
69                 if ($ext_mode != 'test') {
70                         // Log empty versions not in test-mode, but maybe it is fine...
71                         logDebugMessage(__FUNCTION__, __LINE__, 'Extension version is empty, setting to 0.0. ext_name=' . $ext_name . ', ext_mode=' . $ext_mode . ', dry_run=' . intval($dry_run));
72                 } // END - if
73         }
74
75         // Set dry-run
76         enableExtensionDryRun($dry_run);
77
78         // Init array
79         initIncludePool('extension');
80
81         // Init EXT_UPDATE_DEPENDS if not yet done
82         if (!isExtensionUpdateDependenciesInitialized()) {
83                 // Init here...
84                 initExtensionUpdateDependencies();
85         } // END - if
86
87         // Init current extension name list
88         initExtensionSqls();
89
90         // Is the extension already loaded?
91         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Loading extension ' . $ext_name . ', mode=' . getExtensionMode() . ', ver=' . getCurrentExtensionVersion());
92         if ((isset($GLOBALS['ext_loaded']['ext'][$ext_name])) && (getExtensionMode() == 'init')) {
93                 // Debug message
94                 logDebugMessage(__FUNCTION__, __LINE__, sprintf("Extension %s already loaded.", $ext_name));
95
96                 // Abort here
97                 return false;
98         } // END - if
99
100         // Is the extension file NOT there?
101         if (!isExtensionNameValid($ext_name)) {
102                 // Debug message
103                 logDebugMessage(__FUNCTION__, __LINE__, sprintf("Extension %s not found or not readable.", $ext_name));
104
105                 // Abort here
106                 return false;
107         } // END - if
108
109         // Load extension's own language file if not in test mode
110         if ((getExtensionMode() != 'test') && (ifExtensionHasLanguageFile($ext_name))) {
111                 // Load it
112                 loadLanguageFile($ext_name);
113         } // END - if
114
115         // Do we have cache?
116         if (isExtensionFunctionFileReadable($ext_name)) {
117                 // Not yet loaded?
118                 if ((($GLOBALS['cache_array']['extension']['ext_func'][$ext_name] == 'Y') || (!isset($GLOBALS['cache_array']['extension']['ext_func'][$ext_name]))) && (!isset($GLOBALS['ext_loaded']['funcs'][$ext_name]))) {
119                         // Construct IFN for functions file
120                         $funcsInclude = sprintf("inc/libs/%s_functions.php", $ext_name);
121
122                         // Mark it as loaded
123                         $GLOBALS['ext_loaded']['funcs'][$ext_name] = true;
124
125                         // Download functions file
126                         loadIncludeOnce($funcsInclude);
127                 } // END - if
128         } elseif ((!isset($GLOBALS['cache_array']['extension']['ext_func'][$ext_name])) && (isDebugModeEnabled()) && (getOutputMode() == '0') && ($ext_name != 'sql_patches') && (substr($ext_name, 0, 10) != 'admintheme') && (getExtensionMode() == 'test')) {
129                 // No functions file is not so good...
130                 logDebugMessage(__FUNCTION__, __LINE__, sprintf("NOTICE: Extension %s has no own functions file or we cannot read from it. mode=%s",
131                         $ext_name,
132                         getExtensionMode()
133                 ));
134         }
135
136         // Extensions are not deprecated by default
137         setExtensionDeprecated('N');
138
139         // Extensions are not always active by default
140         setExtensionAlwaysActive('N');
141
142         // Extension update notes
143         // @TODO Do we still need this? setExtensionUpdateNotes('');
144
145         // Include the extension file
146         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Extension loaded.');
147         loadExtensionInclude();
148
149         // Is this extension deprecated?
150         if (isExtensionDeprecated()) {
151                 // Deactivate the extension
152                 doDeactivateExtension($ext_name);
153
154                 // Abort here
155                 return false;
156         } // END - if
157
158         // Mark it as loaded in normal mode
159         if (getExtensionMode() == '') {
160                 // Mark it now...
161                 $GLOBALS['ext_loaded']['ext'][$ext_name] = true;
162         } // END - if
163
164         // All fine!
165         return true;
166 }
167
168 // Registeres an extension and possible update depencies
169 function registerExtension ($ext_name, $taskId, $dry_run = false, $logout = true) {
170         // Set current extension name
171         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',task_id=' . $taskId . ',dry_run=' . intval($dry_run) . ',logout=' . intval($logout) . ' - ENTERED!');
172         setCurrentExtensionName($ext_name);
173
174         // Enable dry-run
175         enableExtensionDryRun($dry_run);
176
177         // By default all extensions are in productive phase
178         enableExtensionProductive();
179
180         // This shall never do a non-admin user or if the extension is active (already installed)
181         if ((!isAdmin()) || (isExtensionInstalled($ext_name))) {
182                 // Abort here with 'false'
183                 return false;
184         } // END - if
185
186         // When this extension is already in registration/update phase, all is fine
187         if ((isExtensionRegistrationRunning($ext_name)) || (isExtensionUpdateRunning($ext_name))) {
188                 // Then abort here with 'true' becaus it is fine
189                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . ' - ALREADY!');
190                 return true;
191         } // END - if
192
193         // This registration is running
194         addExtensionRunningRegistration($ext_name);
195
196         // Init EXT_UPDATE_DEPENDS if not yet done
197         if (!isExtensionUpdateDependenciesInitialized()) {
198                 // Init here...
199                 initExtensionUpdateDependencies();
200         } // END - if
201
202         // Is the task id zero? Then we need to auto-fix it here
203         if ($taskId == '0') {
204                 // Try to find the task
205                 $taskId = determineExtensionTaskId(getCurrentExtensionName());
206
207                 // Still zero and not in dry-run?
208                 if (($taskId == '0') && (!isExtensionDryRun())) {
209                         // Now try to create a new task
210                         $taskId = createNewExtensionTask(getCurrentExtensionName());
211
212                         // Is it still zero?
213                         if ($taskId == '0') {
214                                 // Then request a bug report
215                                 debug_report_bug(__FUNCTION__, __LINE__, sprintf("%s: task_id is still zero after determineExtensionTaskId(%s)",
216                                         __FUNCTION__,
217                                         getCurrentExtensionName()
218                                 ));
219                         } // END - if
220                 } // END - if
221         } // END - if
222
223         // Init queries and notes
224         initExtensionSqls();
225         initExtensionNotes();
226
227         // Init variables
228         $ret = false;
229         $test = false;
230         initIncludePool('extension');
231
232         // By default we have no failures
233         setExtensionReportsFailure(false);
234
235         // Does this extension exists?
236         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName());
237         if (loadExtension(getCurrentExtensionName(), 'register', '', isExtensionDryRun())) {
238                 // Set current extension name again
239                 setCurrentExtensionName($ext_name);
240
241                 // And run possible updates
242                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currentExtension=' . getCurrentExtensionName());
243                 $history = getExtensionVersionHistory();
244                 foreach ($history as $ext_ver) {
245                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . getCurrentExtensionName() . ', ext_ver=' . $ext_ver);
246                         // Load extension in update mode
247                         loadExtension(getCurrentExtensionName(), 'update', $ext_ver, isExtensionDryRun());
248
249                         // Add update notes to our output
250                         addExtensionNotes($ext_ver);
251                 } // END - foreach
252
253                 // Does this extension depends on an outstanding update of another update?
254                 for ($dmy = getExtensionUpdateIterator(); getExtensionUpdateIterator() < countExtensionUpdateDependencies();) {
255                         // Get next update
256                         $ext_update = getExtensionUpdateDependenciesIterator();
257
258                         // Increment here to avoid endless loop
259                         incrementExtensionUpdateIterator();
260
261                         // Check if extension is not installed and not already in registration procedure and if loading it wents finally fine...
262                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',isExtensionRegistrationRunning(' . $ext_update . ')=' . intval(isExtensionRegistrationRunning($ext_update)));
263                         if ((!isExtensionInstalled($ext_update)) && (!isExtensionRegistrationRunning($ext_update)) && (loadExtension($ext_update, 'test', '', isExtensionDryRun()))) {
264                                 // Set current extension name again
265                                 setCurrentExtensionName($ext_name);
266
267                                 // If versions mismatch update extension first
268                                 $ext_ver = '';
269                                 if (isExtensionInstalled($ext_update)) {
270                                         // Get version only if installed
271                                         $ext_ver = getExtensionVersion($ext_update);
272                                 } // END - if
273
274                                 // Extension version set? If empty the extension is not registered
275                                 if (empty($ext_ver)) {
276                                         // Extension not registered so far so first load task's id...
277                                         $task = determineExtensionTaskId($ext_update);
278
279                                         // Entry found?
280                                         if ($task > 0) {
281                                                 // Try to register the extension
282                                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . ':ext_update=' . $ext_update . ',taskId=' . $task);
283                                                 $test = registerExtension($ext_update, $task, isExtensionDryRun(), false);
284
285                                                 // Reset extension name
286                                                 setCurrentExtensionName($ext_name);
287                                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . ',test=' . intval($test));
288                                         } // END - if
289                                 } elseif ($ext_ver != getCurrentExtensionVersion()) {
290                                         // Ok, update this extension now
291                                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . ',currVer=' . getCurrentExtensionVersion());
292                                         $GLOBALS['ext_backup_name'][$ext_update][$ext_ver] = getCurrentExtensionName();
293                                         $GLOBALS['ext_backup_ver'][$ext_update][$ext_ver] = getCurrentExtensionVersion();
294                                         updateExtension($ext_update, $ext_ver, isExtensionDryRun());
295                                         setCurrentExtensionName($GLOBALS['ext_backup_name'][$ext_update][$ext_ver]);
296                                         setCurrentExtensionVersion($GLOBALS['ext_backup_ver'][$ext_update][$ext_ver]);
297                                         unset($GLOBALS['ext_backup_name'][$ext_update][$ext_ver]);
298                                         unset($GLOBALS['ext_backup_ver'][$ext_update][$ext_ver]);
299                                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . ',currVer=' . getCurrentExtensionVersion());
300
301                                         // All okay!
302                                         $test = true;
303                                 } else {
304                                         // Nothing to register / update before...
305                                         $test = true;
306                                 }
307                         } else {
308                                 // Required file for update does not exists!
309                                 $test = true;
310                                 // But this is fine for the first time...
311                         }
312
313                         // Restore the current extension name
314                         setCurrentExtensionName($ext_name);
315                 } // END - for
316
317                 // Is there no update?
318                 if (countExtensionUpdateDependencies(getCurrentExtensionName()) == 0) {
319                         // Then test is passed!
320                         $test = true;
321                 } // END - if
322
323                 // Switch back to register mode
324                 setExtensionMode('register');
325
326                 // Remains true if extension registration reports no failures
327                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . ',test=' . intval($test));
328                 $test = (($test === true) && (getExtensionReportsFailure() === false));
329                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . ',test=' . intval($test));
330
331                 // Does everthing before wents ok?
332                 if ($test === true) {
333                         // "Dry-run-mode" activated?
334                         if ((isExtensionDryRun() === false) && (!isExtensionOnRemovalList())) {
335                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . getCurrentExtensionName());
336                                 // Init SQLs and transfer ext->generic
337                                 initSqls();
338                                 setSqlsArray(getExtensionSqls());
339
340                                 // Run installation pre-installation filters
341                                 runFilterChain('pre_extension_installed', array('dry_run' => isExtensionDryRun()));
342
343                                 // Register extension
344                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'insert=' . getCurrentExtensionName() . '/' . getCurrentExtensionVersion() . ' - INSERT!');
345                                 if (isExtensionInstalledAndNewer('sql_patches', '0.0.6')) {
346                                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . getCurrentExtensionName() . ',always_active=' . getExtensionAlwaysActive() . ', ext_ver=' . getCurrentExtensionVersion() . 'ext_css=' . getExtensionHasCss());
347                                         // New way, with CSS
348                                         SQL_QUERY_ESC("INSERT INTO `{?_MYSQL_PREFIX?}_extensions` (`ext_name`, `ext_active`, `ext_version`,`ext_has_css`) VALUES ('%s','%s','%s','%s')",
349                                                 array(
350                                                         getCurrentExtensionName(),
351                                                         getExtensionAlwaysActive(),
352                                                         getCurrentExtensionVersion(),
353                                                         getExtensionHasCss()
354                                                 ), __FUNCTION__, __LINE__);
355                                 } else {
356                                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . getCurrentExtensionName() . ',always_active=' . getExtensionAlwaysActive() . ', ext_ver=' . getCurrentExtensionVersion());
357                                         // Old way, no CSS
358                                         SQL_QUERY_ESC("INSERT INTO `{?_MYSQL_PREFIX?}_extensions` (`ext_name`, `ext_active`, `ext_version`) VALUES ('%s','%s','%s')",
359                                                 array(
360                                                         getCurrentExtensionName(),
361                                                         getExtensionAlwaysActive(),
362                                                         getCurrentExtensionVersion()
363                                                 ), __FUNCTION__, __LINE__);
364                                 }
365
366                                 // Use the insert id as extension id and cache it for early usage
367                                 $GLOBALS['cache_array']['extension']['ext_id'][getCurrentExtensionName()] = SQL_INSERTID();
368
369                                 // Remove cache file(s) if extension is active
370                                 runFilterChain('post_extension_installed', array(
371                                         'pool'     => 'extension',
372                                         'ext_name' => getCurrentExtensionName(),
373                                         'task_id'  => $taskId
374                                 ));
375
376                                 // Re-init queries and notes
377                                 initExtensionSqls(true);
378                                 initExtensionNotes(true);
379
380                                 // Mark it as installed
381                                 $GLOBALS['ext_is_installed'][getCurrentExtensionName()] = true;
382
383                                 // In normal mode return a true on success
384                                 $ret = true;
385                         } elseif (isExtensionDryRun() === true) {
386                                 // In  "dry-run" mode do always return a true
387                                 $ret = true;
388                         } else {
389                                 // Extension has been removed for updates, so all is fine!
390                                 $ret = true;
391                         }
392                 } else {
393                         // No, an error occurs while registering extension :-(
394                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currentExtension=' . getCurrentExtensionName());
395                         $ret = false;
396                 }
397         } elseif (($taskId > 0) && (getCurrentExtensionName() != '')) {
398                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName());
399                 // Remove task from system when id and extension's name is valid
400                 SQL_QUERY_ESC("DELETE LOW_PRIORITY FROM `{?_MYSQL_PREFIX?}_task_system` WHERE `id`=%s AND `status`='NEW' LIMIT 1",
401                         array(bigintval($taskId)), __FUNCTION__, __LINE__);
402         }
403
404         // Is this the sql_patches?
405         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currentExtension=' . getCurrentExtensionName() . '/' . getExtensionMode());
406         if ((getCurrentExtensionName() == 'sql_patches') && ((getExtensionMode() == 'register') || (getExtensionMode() == 'remove')) && (!isExtensionDryRun()) && ($test)) {
407                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currentExtension=' . getCurrentExtensionName() . ': LOAD!');
408                 if ($logout === true) {
409                         // Then redirect to logout
410                         redirectToUrl('modules.php?module=admin&amp;logout=1&amp;' . getExtensionMode() . '=sql_patches');
411                 } else {
412                         // Add temporary filter
413                         registerFilter('shutdown', 'REDIRECT_TO_LOGOUT_SQL_PATCHES', true, true);
414                         $GLOBALS['ext_load_mode'] = getExtensionMode();
415                 }
416         } // END - if
417
418         // Return status code
419         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . ',ext_name=' . $ext_name . ',test=' . intval($test) . ' - EXIT!');
420         return $ret;
421 }
422
423 // Run SQL queries for given extension id
424 // @TODO Change from ext_id to ext_name (not just even the variable! ;-) )
425 function doExtensionSqls ($ext_id, $load_mode) {
426         // This shall never do a non-admin user!
427         if (!isAdmin()) return false;
428
429         // Get extension's name
430         $ext_name = getExtensionName($ext_id);
431
432         // Set current SQL name
433         setCurrentExtensionName($ext_name);
434
435         // Init EXT_UPDATE_DEPENDS
436         if (!isExtensionUpdateDependenciesInitialized()) {
437                 // Init here...
438                 initExtensionUpdateDependencies();
439         } // END - if
440
441         // Init array
442         initExtensionSqls();
443
444         // By default no SQL has been executed
445         $sqlRan = false;
446
447         // Load extension in detected mode
448         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name[' . $ext_id . ']=' . getCurrentExtensionName());
449         loadExtension(getCurrentExtensionName(), $load_mode, '', false);
450
451         // Init these SQLs
452         initSqls();
453         setSqlsArray(getExtensionSqls());
454
455         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'SQLs::count=' . countSqls());
456         if (isSqlsValid()) {
457                 // Run SQL commands...
458                 runFilterChain('run_sqls');
459         } // END - if
460
461         // Run any filters depending on the action here
462         runFilterChain('extension_' . $load_mode);
463
464         // Remove cache file(s) if extension is active
465         if (((isExtensionActive('cache')) && ((SQL_AFFECTEDROWS() == 1)) || ($sqlRan === true) || ($load_mode == 'activate') || ($load_mode == 'deactivate'))) {
466                 // Run filters
467                 runFilterChain('post_extension_run_sql', getCurrentExtensionName());
468         } // END - if
469
470         // Is this the sql_patches?
471         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'id=' . $ext_id . ',currName=' . getCurrentExtensionName() . ',loadMode=' . $load_mode);
472         if ((getCurrentExtensionName() == 'sql_patches') && (($load_mode == 'register') || ($load_mode == 'remove'))) {
473                 // Then redirect to logout
474                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, ': LOAD!');
475                 redirectToUrl('modules.php?module=admin&amp;logout=1&amp;' . $load_mode . '=sql_patches');
476         } // END - if
477 }
478
479 // Check wether the given extension is installed
480 function isExtensionInstalled ($ext_name) {
481         // We don't like empty extension names here
482         if (empty($ext_name)) {
483                 // Please fix them all
484                 debug_report_bug(__FUNCTION__.': ext_name is empty.');
485         } // END - if
486
487         // By default non is installed
488         $isInstalled = false;
489
490         // Check if there is a cache entry
491         if (isset($GLOBALS['ext_is_installed'][$ext_name])) {
492                 // Use cache built from below queries
493                 $isInstalled = $GLOBALS['ext_is_installed'][$ext_name];
494         } elseif (isset($GLOBALS['cache_array']['extension']['ext_id'][$ext_name])) {
495                 // Found!
496                 $isInstalled = true;
497
498                 // Count cache hits
499                 incrementStatsEntry('cache_hits');
500         } elseif ((isInstallationPhase())) {
501                 // Extensions are all inactive/not installed during installation
502         } else {
503                 // Look in database
504                 $ext_id = getExtensionId($ext_name);
505
506                 // Do we have a record?
507                 $isInstalled = ($ext_id > 0);
508
509                 // Is it installed, then cache the entry
510                 if ($isInstalled === true) {
511                         // Dummy call (get is okay here)
512                         getExtensionId($ext_name, true);
513                 } // END - if
514
515                 // Remember the status
516                 $GLOBALS['ext_is_installed'][$ext_name] = $isInstalled;
517         }
518
519         // Return status
520         return $isInstalled;
521 }
522
523 // Check if given extension is active
524 function isExtensionActive ($ext_name) {
525         // Extensions are all inactive during installation
526         if ((isInstallationPhase()) || (empty($ext_name))) return false;
527
528         // Not active is the default
529         $data['ext_active'] = 'N';
530
531         // Check cache
532         if (isset($GLOBALS['cache_array']['extension']['ext_active'][$ext_name])) {
533                 // Load from cache
534                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'CACHE! ext_name=' . $ext_name);
535                 $data['ext_active'] = $GLOBALS['cache_array']['extension']['ext_active'][$ext_name];
536
537                 // Count cache hits
538                 incrementStatsEntry('cache_hits');
539         } elseif (isset($GLOBALS['ext_loaded'][$ext_name])) {
540                 // @TODO Extension is loaded, what next?
541                 debug_report_bug(__FUNCTION__, __LINE__, 'LOADED:' . $ext_name);
542         } elseif (($ext_name == 'cache') || (!isExtensionInstalled('cache'))) {
543                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'DB! ext_name=' . $ext_name);
544                 // Load from database
545                 $result = SQL_QUERY_ESC("SELECT `ext_active` FROM `{?_MYSQL_PREFIX?}_extensions` WHERE `ext_name`='%s' LIMIT 1",
546                         array($ext_name), __FUNCTION__, __LINE__);
547
548                 // Entry found?
549                 if (SQL_NUMROWS($result) == 1) {
550                         // Load entry
551                         $data = SQL_FETCHARRAY($result);
552                 } // END - if
553
554                 // Free result
555                 SQL_FREERESULT($result);
556
557                 // Write cache array
558                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . '[DB]: ' . $data['ext_active']);
559                 $GLOBALS['cache_array']['extension']['ext_active'][$ext_name] = $data['ext_active'];
560         } else {
561                 // Extension not active!
562                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ': Not active!');
563                 $GLOBALS['cache_array']['extension']['ext_active'][$ext_name] = 'N';
564         }
565
566         // Debug message
567         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',active=' . $data['ext_active']);
568
569         // Is this extension activated? (For admins we always have active extensions...)
570         return ($data['ext_active'] == 'Y');
571 }
572
573 // Get version from extensions
574 function getExtensionVersion ($ext_name, $force = false) {
575         // By default no extension is found
576         $data['ext_version'] = 'false';
577
578         // Empty extension name should be fixed!
579         if (empty($ext_name)) {
580                 // Please report this bug!
581                 debug_report_bug(__FUNCTION__, __LINE__, 'ext_name is empty which is not allowed here.');
582         } // END - if
583
584         // Extensions are all inactive during installation
585         if (isInstallationPhase()) return '';
586         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name);
587
588         // Is the cache written?
589         if (isset($GLOBALS['cache_array']['extension']['ext_version'][$ext_name])) {
590                 // Load data from cache
591                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, $ext_name . ': CACHE!');
592                 $data['ext_version'] = $GLOBALS['cache_array']['extension']['ext_version'][$ext_name];
593
594                 // Count cache hits
595                 incrementStatsEntry('cache_hits');
596         } elseif ((!isCacheInstanceValid()) || (isset($GLOBALS['cache_array']['extension'])) || (getOutputMode() != 0)) {
597                 // Load from database
598                 $result = SQL_QUERY_ESC("SELECT `ext_version` FROM `{?_MYSQL_PREFIX?}_extensions` WHERE `ext_name`='%s' LIMIT 1",
599                         array($ext_name), __FUNCTION__, __LINE__);
600                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, $ext_name . ': DB - '.SQL_NUMROWS($result).'');
601
602                 // Is the extension there?
603                 if (SQL_NUMROWS($result) == 1) {
604                         // Load entry
605                         $data = SQL_FETCHARRAY($result);
606                 } elseif (isDebugModeEnabled()) {
607                         // Not found, please report all
608                         debug_report_bug(__FUNCTION__, __LINE__, sprintf(": Cannot find extension %s in database!", $ext_name));
609                 }
610
611                 // Free result
612                 SQL_FREERESULT($result);
613
614                 // Set cache
615                 $GLOBALS['cache_array']['extension']['ext_version'][$ext_name] = $data['ext_version'];
616         }
617
618         // Extension version should not be invalid
619         if (($data['ext_version'] == 'false') && ($force === false)) {
620                 // Please report this trouble
621                 debug_report_bug(__FUNCTION__, __LINE__, sprintf("Extension <span class=\"data\">%s</span> has empty version!", $ext_name));
622         } // END - if
623
624         // Return result
625         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_version=' . $data['ext_version']);
626         return $data['ext_version'];
627 }
628
629 // Updates a given extension with current extension version to latest version
630 function updateExtension ($ext_name, $ext_ver, $dry_run = false) {
631         // Only admins are allowed to update extensions
632         if ((!isAdmin()) || (empty($ext_name))) return false;
633
634         // Set current SQL name
635         setCurrentExtensionName($ext_name);
636
637         // Init arrays
638         initExtensionSqls();
639         initExtensionNotes();
640         initIncludePool('extension');
641
642         // Load extension in test mode
643         loadExtension($ext_name, 'test', $ext_ver, isExtensionDryRun());
644
645         // Save version history
646         $history = getExtensionVersionHistory();
647
648         // Remove old SQLs array to prevent possible bugs
649         initExtensionSqls();
650
651         // Check if version is updated
652         //* DEBUG: */ debugOutput(getCurrentExtensionName().'/'.$ext_name.':'.getThisExtensionVersion().'/'.$ext_ver.'/'.intval(is_array($history)));
653         if (((getThisExtensionVersion() != $ext_ver) || (isExtensionDryRun())) && (is_array($history))) {
654                 // Search for starting point
655                 $start = array_search($ext_ver, $history);
656
657                 // And load SQL queries in order of version history
658                 for ($idx = ($start + 1); $idx < count($history); $idx++) {
659                         // Set extension version
660                         $GLOBALS['update_ver'][getCurrentExtensionName()] = $history[$idx];
661
662                         // Load again...
663                         loadExtension(getCurrentExtensionName(), 'update', $GLOBALS['update_ver'][getCurrentExtensionName()], isExtensionDryRun());
664
665                         // Get all depencies
666                         $depencies = getExtensionUpdateDependencies();
667
668                         // Nothing to apply?
669                         if (count($depencies) > 0) {
670                                 // Apply all extension depencies
671                                 foreach ($depencies as $ext_depend) {
672                                         // Did we already update/register this?
673                                         if (!isset($GLOBALS['ext_updated'][$ext_depend])) {
674                                                 // Set it as current
675                                                 setCurrentExtensionName($ext_depend);
676
677                                                 // Mark it as already updated before we update it
678                                                 $GLOBALS['ext_updated'][$ext_depend] = true;
679
680                                                 // Is the extension there?
681                                                 if (isExtensionInstalled($ext_depend)) {
682                                                         // Update another extension first!
683                                                         $test = updateExtension($ext_depend, getExtensionVersion($ext_depend), isExtensionDryRun());
684                                                 } else {
685                                                         // Register new extension
686                                                         $test = registerExtension($ext_depend, 0, isExtensionDryRun(), false);
687                                                 }
688                                         } // END - if
689                                 } // END - foreach
690
691                                 // Set extension version here
692                                 setCurrentExtensionVersion($ext_ver);
693
694                                 // Set name back
695                                 setCurrentExtensionName($ext_name);
696                         } // END - if
697
698                         // Add notes
699                         addExtensionNotes($history[$idx]);
700                 } // END - for
701
702                 // In real-mode execute any existing includes
703                 if (isExtensionDryRun() === false) {
704                         $GLOBALS['ext_inc_pool'][getCurrentExtensionName()] = getIncludePool('extension');
705                         runFilterChain('load_includes', 'extension');
706                         setIncludePool('extension', $GLOBALS['ext_inc_pool'][getCurrentExtensionName()]);
707                         unset($GLOBALS['ext_inc_pool'][getCurrentExtensionName()]);
708                 } // END - if
709
710                 // Init these SQLs
711                 initSqls();
712                 setSqlsArray(getExtensionSqls());
713
714                 // Run SQLs
715                 runFilterChain('run_sqls', array('dry_run' => isExtensionDryRun()));
716
717                 if (isExtensionDryRun() === false) {
718                         // Run filters on success extension update
719                         runFilterChain('extension_update', getCurrentExtensionName());
720                 } // END - if
721         } // END - if
722 }
723
724 // Output verbose SQL table for extension
725 function addExtensionVerboseSqlTable ($title = '', $dashed = '', $switch = false, $width = '100%') {
726         // Empty title?
727         if (empty($title)) {
728                 // Then fix it to default
729                 $title = '{--ADMIN_SQLS_EXECUTED_ON_REMOVAL--}';
730         } // END - if
731
732         // Init variables
733         $OUT = '';
734
735         // Do we have queries?
736         if ((isExtensionInstalledAndNewer('sql_patches', '0.0.7')) && (getConfig('verbose_sql') == 'Y')) {
737                 // Do we have entries?
738                 if (countExtensionSqls() > 0) {
739                         // Init counter
740                         $idx = 0;
741                         // Get all SQLs
742                         foreach (getExtensionSqls() as $sqls) {
743                                 // New array format is recursive
744                                 foreach ($sqls as $sql) {
745                                         // Trim out spaces
746                                         $sql = trim($sql);
747
748                                         // Output command if set
749                                         if (!empty($sql)) {
750                                                 // Prepare output for template
751                                                 $content = array(
752                                                         'i'   => ($idx + 1),
753                                                         'sql' => $sql
754                                                 );
755
756                                                 // Load row template
757                                                 $OUT .= loadTemplate('admin_extension_sql_row', true, $content);
758
759                                                 // Count up
760                                                 $idx++;
761                                         } // END - if
762                                 } // END - foreach
763                         } // END - foreach
764
765                         // Prepare content for template
766                         $content = array(
767                                 'width'  => $width,
768                                 'dashed' => $dashed,
769                                 'title'  => $title,
770                                 'rows'   => $OUT
771                         );
772
773                         // Load main template
774                         $OUT = loadTemplate('admin_extension_sql_table', true, $content);
775                 } else {
776                         // No addional SQL commands to run
777                         $OUT = loadTemplate('admin_settings_saved', true, '{--ADMIN_NO_ADDITIONAL_SQLS--}');
778                 }
779         } // END - if
780
781         // Return output
782         return $OUT;
783 }
784
785 // Get extension name from id
786 function getExtensionName ($ext_id) {
787         // Init extension name
788         $data['ext_name'] = '';
789
790         // Is cache there?
791         if (isset($GLOBALS['cache_array']['extension']['ext_name'][$ext_id])) {
792                 // Load from cache
793                 $data['ext_name'] = $GLOBALS['cache_array']['extension']['ext_name'][$ext_id];
794
795                 // Count cache hits
796                 incrementStatsEntry('cache_hits');
797         } elseif (!isExtensionActive('cache')) {
798                 // Load from database
799                 $result = SQL_QUERY_ESC("SELECT `ext_name` FROM `{?_MYSQL_PREFIX?}_extensions` WHERE `id`=%s LIMIT 1",
800                         array(bigintval($ext_id)), __FUNCTION__, __LINE__);
801
802                 // Is the entry there?
803                 if (SQL_NUMROWS($result) == 1) {
804                         // Get the extension's name from database
805                         $data = SQL_FETCHARRAY($result);
806                 } // END - if
807
808                 // Free result
809                 SQL_FREERESULT($result);
810         }
811
812         // Did we find some extension?
813         if (empty($data['ext_name'])) {
814                 // We should fix these all!
815                 debug_report_bug(__FUNCTION__, __LINE__, 'ext_name is empty. ext_id=' . $ext_id);
816         } // END - if
817
818         // Return the extension name
819         return $data['ext_name'];
820 }
821
822 // Get extension id from name
823 function getExtensionId ($ext_name) {
824         // Init id number
825         $data['ext_id'] = '0';
826
827         // Do we have cache?
828         if (isset($GLOBALS['cache_array']['extension']['ext_id'][$ext_name])) {
829                 // Load from cache
830                 $data['ext_id'] = $GLOBALS['cache_array']['extension']['ext_id'][$ext_name];
831
832                 // Count cache hits
833                 incrementStatsEntry('cache_hits');
834         } else {
835                 // Load from database
836                 $result = SQL_QUERY_ESC("SELECT `id` AS ext_id FROM `{?_MYSQL_PREFIX?}_extensions` WHERE `ext_name`='%s' LIMIT 1",
837                         array($ext_name), __FUNCTION__, __LINE__);
838
839                 // Is the entry there?
840                 if (SQL_NUMROWS($result) == 1) {
841                         // Get the extension's id from database
842                         $data = SQL_FETCHARRAY($result);
843                 } // END - if
844
845                 // Free result
846                 SQL_FREERESULT($result);
847
848                 // Cache it
849                 $GLOBALS['cache_array']['extension']['ext_id'][$ext_name] = $data['ext_id'];
850         }
851
852         // Return value
853         return $data['ext_id'];
854 }
855
856 // Determines wether the given extension name is valid
857 function isExtensionNameValid ($ext_name) {
858         // Do we have cache?
859         if (!isset($GLOBALS['ext_name_valid'][$ext_name])) {
860                 // Generate include file name
861                 $INC = sprintf("inc/extensions/ext-%s.php", $ext_name);
862
863                 // Is there a file in inc/extensions/ ?
864                 $GLOBALS['ext_name_valid'][$ext_name] = isIncludeReadable($INC);
865         } // END - if
866
867         // Return result
868         return $GLOBALS['ext_name_valid'][$ext_name];
869 }
870
871 // Determines wether the given extension id is valid
872 function isExtensionIdValid ($ext_id) {
873         // Default is nothing valid
874         $isValid = false;
875
876         // Check in cache then in database
877         if (isset($GLOBALS['cache_array']['extension']['ext_name'][$ext_id])) {
878                 // Valid!
879                 $isValid = true;
880
881                 // Count cache hits
882                 incrementStatsEntry('cache_hits');
883         } else {
884                 // Query database
885                 $isValid = (countSumTotalData($ext_id, 'extensions', 'id', 'id', true) == 1);
886         }
887
888         // Return result
889         return $isValid;
890 }
891
892 // Activate given extension
893 function doActivateExtension ($ext_name) {
894         // Activate the extension
895         SQL_QUERY_ESC("UPDATE `{?_MYSQL_PREFIX?}_extensions` SET `ext_active`='Y' WHERE `ext_name`='%s' LIMIT 1",
896                 array($ext_name), __FUNCTION__, __LINE__);
897
898         // Extension has been activated?
899         if (SQL_AFFECTEDROWS() == 1) {
900                 // Then run all queries
901                 doExtensionSqls(getExtensionId($ext_name), 'activate');
902         } // END - if
903 }
904
905 // Deactivate given extension
906 function doDeactivateExtension($ext_name) {
907         // Activate the extension
908         SQL_QUERY_ESC("UPDATE `{?_MYSQL_PREFIX?}_extensions` SET `ext_active`='N' WHERE `ext_name`='%s' LIMIT 1",
909                 array($ext_name), __FUNCTION__, __LINE__);
910
911         // Extension has been activated?
912         if (SQL_AFFECTEDROWS() == 1) {
913                 // Then run all queries
914                 doExtensionSqls(getExtensionId($ext_name), 'deactivate');
915
916                 // Create new task (we ignore the task id here)
917                 createExtensionDeactivationTask($ext_name);
918
919                 // Notify the admin
920                 sendAdminNotification(
921                         '{--ADMIN_EXTENSION_DEACTIVATED_SUBJECT--}',
922                         'admin_extension_deactivated',
923                         array('ext_name' => $ext_name)
924                 );
925         } // END - if
926 }
927
928 // Checks wether the extension is older than given
929 function isExtensionOlder ($ext_name, $ext_ver) {
930         // Get current extension version
931         $currVersion = getExtensionVersion($ext_name);
932
933         // Remove all dots from both versions
934         $currVersion = str_replace('.', '', $currVersion);
935         $ext_ver = str_replace('.', '', $ext_ver);
936
937         // Now compare both and return the result
938         return ($currVersion < $ext_ver);
939 }
940
941 // Creates a new task for updated extension
942 function createExtensionUpdateTask ($adminId, $ext_name, $ext_ver, $notes) {
943         // Create subject line
944         $subject = '[UPDATE-' . $ext_name . '-' . $ext_ver . ':] {--ADMIN_UPDATE_EXTENSION_SUBJECT--}';
945
946         // Get task id
947         $taskId = determineTaskIdBySubject($subject);
948
949         // Is the extension there?
950         if (isExtensionInstalled($ext_name)) {
951                 // Check if task is not there
952                 if ($taskId == '0') {
953                         // Create extension update-task
954                         $taskId = createNewTask($subject, $notes, 'EXTENSION_UPDATE', 0, $adminId);
955                 } // END - if
956         } else {
957                 // Extension not there! :-(
958                 debug_report_bug(__FUNCTION__, __LINE__, sprintf("Extension <span class=\"data\">%s</span> not found but should be updated?", $ext_name));
959         }
960
961         // Return task id
962         return $taskId;
963 }
964
965 // Creates a new task for newly installed extension
966 function createNewExtensionTask ($ext_name) {
967         // Generate subject line
968         $subject = sprintf("[%s:]", $ext_name);
969
970         // Get task id
971         $taskId = determineTaskIdBySubject($subject);
972
973         // Not installed and do we have created a task for the admin?
974         if (($taskId == '0') && (!isExtensionInstalled($ext_name))) {
975                 // Set default message if ext-foo is missing
976                 $message = getMaskedMessage('ADMIN_EXTENSION_TEXT_FILE_MISSING', $ext_name);
977
978                 // Template file
979                 $tpl = sprintf("%stemplates/%s/html/ext/ext_%s.tpl",
980                         getConfig('PATH'),
981                         getLanguage(),
982                         $ext_name
983                 );
984
985                 // Load text for task if found
986                 if (isFileReadable($tpl)) {
987                         // Load extension's own text template (HTML!)
988                         $message = loadTemplate('ext_' . $ext_name, true);
989                 } else {
990                         // Write this in debug.log as well
991                         logDebugMessage(__FUNCTION__, __LINE__, $message);
992                 }
993
994                 // Task not created so it's a brand-new extension which we need to register and create a task for!
995                 $taskId = createNewTask($subject, $message, 'EXTENSION', 0, getCurrentAdminId(), false);
996         } // END - if
997
998         // Return task id
999         return $taskId;
1000 }
1001
1002 // Creates a task for automatically deactivated (deprecated) extension
1003 function createExtensionDeactivationTask ($ext_name) {
1004         // Create subject line
1005         $subject = sprintf("[%s:] %s", $ext_name, '{--ADMIN_TASK_EXTENSION_DEACTIVATED_SUBJECT--}');
1006
1007         // Get task id
1008         $taskId = determineTaskIdBySubject($subject);
1009
1010         // Not installed and do we have created a task for the admin?
1011         if (($taskId == '0') && (isExtensionInstalled($ext_name))) {
1012                 // Task not created so add it
1013                 $taskId = createNewTask($subject, SQL_ESCAPE(loadTemplate('task_EXTENSION_deactivated', true, $ext_name)), 'EXTENSION_DEACTIVATION');
1014         } // END - if
1015
1016         // Return task id
1017         return $taskId;
1018 }
1019
1020 // Checks if the module has a menu
1021 function ifModuleHasMenu ($mod, $forceDb = false) {
1022         // All is false by default
1023         $ret = false;
1024
1025         // Extension installed and newer than or has version 0.1.2?
1026         if (isExtensionInstalledAndNewer('cache', '0.1.2')) {
1027                 // Cache version is okay, so let's check the cache!
1028                 if (isset($GLOBALS['cache_array']['modules']['has_menu'][$mod])) {
1029                         // Check module cache and count hit
1030                         $ret = ($GLOBALS['cache_array']['modules']['has_menu'][$mod] == 'Y');
1031                         incrementStatsEntry('cache_hits');
1032                 } elseif (isset($GLOBALS['cache_array']['extension']['ext_menu'][$mod])) {
1033                         // Check cache and count hit
1034                         $ret = ($GLOBALS['cache_array']['extension']['ext_menu'][$mod] == 'Y');
1035                         incrementStatsEntry('cache_hits');
1036                 } else {
1037                         // Admin/guest/member/sponsor modules have always a menu!
1038                         $ret = in_array($mod, array('admin', 'index', 'login', 'sponsor'));
1039                 }
1040         } elseif ((isExtensionInstalledAndNewer('sql_patches', '0.3.6')) && ((!isExtensionActive('cache')) || ($forceDb === true))) {
1041                 // Check database for entry
1042                 $result = SQL_QUERY_ESC("SELECT `has_menu` FROM `{?_MYSQL_PREFIX?}_mod_reg` WHERE `module`='%s' LIMIT 1",
1043                         array($mod), __FUNCTION__, __LINE__);
1044
1045                 // Entry found?
1046                 if (SQL_NUMROWS($result) == 1) {
1047                         // Load "has_menu" column
1048                         $data = SQL_FETCHARRAY($result);
1049
1050                         // Fake cache... ;-)
1051                         $GLOBALS['cache_array']['extension']['ext_menu'][$mod] = $data['has_menu'];
1052
1053                         // Does it have a menu?
1054                         $ret = ($data['has_menu'] == 'Y');
1055                 } // END  - if
1056
1057                 // Free memory
1058                 SQL_FREERESULT($result);
1059         } elseif (!isExtensionInstalled('sql_patches')) {
1060                 // No sql_patches installed, so maybe in admin/guest/member/sponsor area or no admin registered?
1061                 $ret = in_array($mod, array('admin', 'index', 'login', 'sponsor')); // Then there is a menu!
1062         } else {
1063                 // Unsupported state!
1064                 logDebugMessage(__FUNCTION__, __LINE__, 'This should never be reached.');
1065         }
1066
1067         // Return status
1068         return $ret;
1069 }
1070
1071 // Determines the task id for given extension
1072 function determineExtensionTaskId ($ext_name) {
1073         // Default is not found
1074         $data['task_id'] = '0';
1075
1076         // Search for extension task's id
1077         $result = SQL_QUERY_ESC("SELECT `id` AS task_id FROM `{?_MYSQL_PREFIX?}_task_system` WHERE `task_type`='EXTENSION' AND `subject`='[%s:]' LIMIT 1",
1078                 array($ext_name), __FUNCTION__, __LINE__);
1079
1080         // Entry found?
1081         if (SQL_NUMROWS($result) == 1) {
1082                 // Task found so load task's id and register extension...
1083                 $data = SQL_FETCHARRAY($result);
1084         } // END - if
1085
1086         // Free result
1087         SQL_FREERESULT($result);
1088
1089         // Return it
1090         return $data['task_id'];
1091 }
1092
1093 // Determines the task id for given subject
1094 function determineTaskIdBySubject ($subject) {
1095         // Default is not found
1096         $data['task_id'] = '0';
1097
1098         // Search for task id
1099         $result = SQL_QUERY_ESC("SELECT `id` AS task_id FROM `{?_MYSQL_PREFIX?}_task_system` WHERE `subject` LIKE '%s%%' LIMIT 1",
1100                 array($subject), __FUNCTION__, __LINE__);
1101
1102         // Entry found?
1103         if (SQL_NUMROWS($result) == 1) {
1104                 // Task found so load task's id and register extension...
1105                 $data = SQL_FETCHARRAY($result);
1106         } // END - if
1107
1108         // Free result
1109         SQL_FREERESULT($result);
1110
1111         // Return it
1112         return $data['task_id'];
1113 }
1114
1115 // Add updates notes for given version
1116 function addExtensionNotes ($ext_ver) {
1117         // Init notes/content
1118         $out = '';
1119         $content = array();
1120
1121         // Is do we have verbose output enabled?
1122         if ((!isExtensionActive('sql_patches')) || (getConfig('verbose_sql') == 'Y')) {
1123                 // Update notes found?
1124                 if (isExtensionUpdateNoteSet($ext_ver)) {
1125                         // Update notes found
1126                         $content = array(
1127                                 'ver'   => $ext_ver,
1128                                 'notes' => getExtensionUpdateNotes($ext_ver)
1129                         );
1130
1131                         // Reset them
1132                         setExtensionUpdateNotes('', $ext_ver);
1133                 } elseif (in_array($ext_ver, array('0.0', '0.0.0'))) {
1134                         // Initial release
1135                         $content = array(
1136                                 'ver'   => $ext_ver,
1137                                 'notes' => '{--INITIAL_RELEASE--}'
1138                         );
1139                 } else {
1140                         // No update notes found!
1141                         $content = array(
1142                                 'ver'   => $ext_ver,
1143                                 'notes' => '{--NO_UPDATE_NOTES--}'
1144                         );
1145                 }
1146
1147                 // Load template
1148                 $out = loadTemplate('admin_extension_notes', true, $content);
1149         } // END - if
1150
1151         // Add the notes
1152         appendExtensionNotes($out);
1153 }
1154
1155 // Getter for CSS files array
1156 function getExtensionCssFiles () {
1157         // By default no additional CSS files are found
1158         $cssFiles = array();
1159
1160         // Is the array there?
1161         if (isset($GLOBALS['css_files'])) {
1162                 // Then use it
1163                 $cssFiles = $GLOBALS['css_files'];
1164         } // END - if
1165
1166         // Return array
1167         return $cssFiles;
1168 }
1169
1170 // Init CSS files array
1171 function initExtensionCssFiles () {
1172         // Simply init it
1173         $GLOBALS['css_files'] = array();
1174 }
1175
1176 // Add new entry
1177 function addExtensionCssFile ($file) {
1178         // Is the array there?
1179         if (!isset($GLOBALS['css_files'])) {
1180                 // Then auto-init them
1181                 initExtensionCssFiles();
1182         } // END - if
1183
1184         // Add the entry
1185         $GLOBALS['css_files'][] = $file;
1186 }
1187
1188 // Setter for EXT_ALWAYS_ACTIVE flag
1189 function setExtensionAlwaysActive ($active) {
1190         $GLOBALS['ext_always_active'][getCurrentExtensionName()] = (string) $active;
1191 }
1192
1193 // Getter for EXT_ALWAYS_ACTIVE flag
1194 function getExtensionAlwaysActive () {
1195         return $GLOBALS['ext_always_active'][getCurrentExtensionName()];
1196 }
1197
1198 // Checks wether the current extension is always active
1199 function isExtensionAlwaysActive () {
1200         return (getExtensionAlwaysActive() == 'Y');
1201 }
1202
1203 // Setter for EXT_VERSION flag
1204 function setThisExtensionVersion ($ext_version) {
1205         $GLOBALS['ext_version'][getCurrentExtensionName()] = (string) $ext_version;
1206 }
1207
1208 // Getter for EXT_VERSION flag
1209 function getThisExtensionVersion () {
1210         return $GLOBALS['ext_version'][getCurrentExtensionName()];
1211 }
1212
1213 // Setter for EXT_DEPRECATED flag
1214 function setExtensionDeprecated ($deprecated) {
1215         $GLOBALS['ext_deprecated'][getCurrentExtensionName()] = (string) $deprecated;
1216 }
1217
1218 // Getter for EXT_DEPRECATED flag
1219 function isExtensionDeprecated () {
1220         return ($GLOBALS['ext_deprecated'][getCurrentExtensionName()] == 'Y');
1221 }
1222
1223 // Setter for EXT_UPDATE_DEPENDS flag
1224 function addExtensionUpdateDependency ($updateDepends) {
1225         //* DEBUG */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . '/' . $updateDepends . ' - ENTERED!');
1226         // Is the update depency empty? (NEED TO BE FIXED!)
1227         if (empty($updateDepends)) {
1228                 // Please report this bug!
1229                 debug_report_bug(__FUNCTION__, __LINE__, 'updateDepends is empty: currentExtension=' . getCurrentExtensionName());
1230         } // END - if
1231
1232         // Is it not yet added?
1233         /* Only for debugging!
1234         if ((isset($updateDepends, $GLOBALS['ext_running_updates'][getCurrentExtensionName()])) && (in_array($updateDepends, getExtensionUpdatesRunning()))) {
1235                 // Double-adding isn't fine, too
1236                 debug_report_bug(__FUNCTION__, __LINE__, '() called twice: updateDepends=' . $updateDepends . ',currentExtension=' . getCurrentExtensionName());
1237         } // END - if
1238         */
1239
1240         // Add it to the list of extension update depencies map
1241         $GLOBALS['ext_update_depends'][getCurrentExtensionName()][] = (string) $updateDepends;
1242
1243         // Remember it in the list of running updates
1244         $GLOBALS['ext_running_updates'][getCurrentExtensionName()][] = $updateDepends;
1245         //* DEBUG */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . '/' . $updateDepends . ' - EXIT!');
1246 }
1247
1248 // Getter for running updates
1249 function getExtensionUpdatesRunning () {
1250         return $GLOBALS['ext_running_updates'][getCurrentExtensionName()];
1251 }
1252
1253 // Checks wether the given extension registration is in progress
1254 function isExtensionRegistrationRunning ($ext_name) {
1255         // Simply check it
1256         $isRunning = ((isset($GLOBALS['ext_register_running'])) && (in_array($ext_name, $GLOBALS['ext_register_running'])));
1257
1258         // Return it
1259         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ', isRunning=' . intval($isRunning));
1260         return $isRunning;
1261 }
1262
1263 // Init EXT_UPDATE_DEPENDS flag
1264 function initExtensionUpdateDependencies () {
1265         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . ' - ENTERED!');
1266
1267         // Init update depency map automatically if not found
1268         if (isExtensionUpdateDependenciesInitialized()) {
1269                 // We need these bug reports as well...
1270                 debug_report_bug(__FUNCTION__, __LINE__, '() is called twice: currName=' . getCurrentExtensionName());
1271         } // END - if
1272
1273         $GLOBALS['ext_update_depends'][getCurrentExtensionName()] = array();
1274
1275         // Init running updates array
1276         initExtensionRuningUpdates();
1277
1278         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . ' - EXIT!');
1279 }
1280
1281 // Adds an extension as "registration in progress"
1282 function addExtensionRunningRegistration ($ext_name) {
1283         // Is it running?
1284         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Registration in progress: ext_name=' . $ext_name . ' - ENTERED!');
1285         if (isExtensionRegistrationRunning($ext_name)) {
1286                 // This is really bad and should not be quietly ignored
1287                 debug_report_bug(__FUNCTION__, __LINE__, '() already called! ext_name=' . $ext_name);
1288         } // END - if
1289
1290         // Then add it!
1291         $GLOBALS['ext_register_running'][] = $ext_name;
1292         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Registration in progress: ext_name=' . $ext_name . ' - EXIT!');
1293 }
1294
1295 // Checks wether EXT_UPDATE_DEPENDS is initialized
1296 function isExtensionUpdateDependenciesInitialized () {
1297         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName());
1298         return (isset($GLOBALS['ext_update_depends'][getCurrentExtensionName()]));
1299 }
1300
1301 // Checks wether an update is already running for given extension
1302 function isExtensionUpdateRunning ($ext_name) {
1303         // Current and given extensions means whole array
1304         if ($ext_name == getCurrentExtensionName()) {
1305                 // Default is not found
1306                 $isRunning = false;
1307
1308                 // Walk through whole array
1309                 foreach ($GLOBALS['ext_running_updates'] as $ext1=>$depends) {
1310                         // Is it found?
1311                         if (($ext1 == $ext_name) || ($isRunning === true)) {
1312                                 // Found!
1313                                 logDebugMessage(__FUNCTION__, __LINE__, 'ext1=' . $ext1 . ',ext_name=' . $ext_name . ',isRunning=' . intval($isRunning));
1314                                 $isRunning = true;
1315                                 break;
1316                         } // END - if
1317                 } // END - foreach
1318
1319                 // Return result
1320                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currentExtension=' . getCurrentExtensionName() . ',ext_name=' . $ext_name . ', isRunning=' . intval($isRunning));
1321                 return $isRunning;
1322         } // END - if
1323
1324         // Simply check it
1325         $isRunning = ((isExtensionUpdateDependenciesInitialized()) && (in_array($ext_name, getExtensionRunningUpdates())));
1326
1327         // Return it
1328         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currentExtension=' . getCurrentExtensionName() . ',ext_name=' . $ext_name . ', isRunning=' . intval($isRunning));
1329         return $isRunning;
1330 }
1331
1332 // Initializes the list of running updates
1333 function initExtensionRuningUpdates () {
1334         // Auto-init ext_running_updates
1335         if (!isset($GLOBALS['ext_running_updates'])) {
1336                 $GLOBALS['ext_running_updates'] = array();
1337                 $GLOBALS['ext_register_running'] = array();
1338         } // END - if
1339 }
1340
1341 // Getter for EXT_UPDATE_DEPENDS flag
1342 function getExtensionUpdateDependencies () {
1343         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, "currName=".getCurrentExtensionName());
1344         return $GLOBALS['ext_update_depends'][getCurrentExtensionName()];
1345 }
1346
1347 // Getter for next iterator depency
1348 function getExtensionUpdateDependenciesIterator () {
1349         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, "currName=".getCurrentExtensionName());
1350         return ($GLOBALS['ext_update_depends'][getCurrentExtensionName()][getExtensionUpdateIterator()]);
1351 }
1352
1353 // Counter for extension update depencies
1354 function countExtensionUpdateDependencies () {
1355         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, "currName=".getCurrentExtensionName());
1356         return count($GLOBALS['ext_update_depends'][getCurrentExtensionName()]);
1357 }
1358
1359 // Removes given extension from update denpency list
1360 function removeExtensionUpdateDependency ($ext_name) {
1361         // Look it up
1362         $key = array_search($ext_name, getExtensionUpdateDependencies());
1363
1364         // Is it valid?
1365         if ($key !== false) {
1366                 // Then remove it
1367                 unset($GLOBALS['ext_update_depends'][getCurrentExtensionName()][$key]);
1368
1369                 // And sort the array
1370                 ksort($GLOBALS['ext_update_depends'][getCurrentExtensionName()]);
1371         } // END - if
1372 }
1373
1374 // Init iterator for update depencies
1375 function initExtensionUpdateIterator () {
1376         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, "currName=".getCurrentExtensionName());
1377         $GLOBALS['ext_depend_iterator'][getCurrentExtensionName()] = '0';
1378 }
1379
1380 // Getter for depency iterator
1381 function getExtensionUpdateIterator () {
1382         // Auto-init iterator
1383         if (!isset($GLOBALS['ext_depend_iterator'][getCurrentExtensionName()])) initExtensionUpdateIterator();
1384
1385         // Return it
1386         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, "currName=".getCurrentExtensionName().'/'.$GLOBALS['ext_depend_iterator'][getCurrentExtensionName()]);
1387         return $GLOBALS['ext_depend_iterator'][getCurrentExtensionName()];
1388 }
1389
1390 // Increments the update iterator
1391 function incrementExtensionUpdateIterator () {
1392         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, "currName=".getCurrentExtensionName());
1393         $GLOBALS['ext_depend_iterator'][getCurrentExtensionName()]++;
1394 }
1395
1396 // Setter for EXT_REPORTS_FAILURE flag
1397 function setExtensionReportsFailure ($reportsFailure) {
1398         $GLOBALS['ext_reports_failure'] = (bool) $reportsFailure;
1399 }
1400
1401 // Getter for EXT_REPORTS_FAILURE flag
1402 function getExtensionReportsFailure () {
1403         return $GLOBALS['ext_reports_failure'];
1404 }
1405
1406 // Setter for EXT_VER_HISTORY flag
1407 function setExtensionVersionHistory ($versionHistory) {
1408         $GLOBALS['ext_ver_history'][getCurrentExtensionName()] = (array) $versionHistory;
1409 }
1410
1411 // Getter for EXT_VER_HISTORY array
1412 function getExtensionVersionHistory () {
1413         return $GLOBALS['ext_ver_history'][getCurrentExtensionName()];
1414 }
1415
1416 // Setter for EXT_UPDATE_NOTES
1417 function setExtensionUpdateNotes ($updateNotes, $ext_ver = '') {
1418         // . '/' . getCurrentExtensionVersion()
1419         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'getCurrentExtensionName()=' . getCurrentExtensionName() . ',getExtensionMode()=' . getExtensionMode() . ',ext_ver=' . $ext_ver . ',updateNotes()=' . strlen($updateNotes));
1420         if (empty($ext_ver)) {
1421                 $GLOBALS['ext_update_notes'][getCurrentExtensionName()][getCurrentExtensionVersion()] = (string) $updateNotes;
1422         } else {
1423                 $GLOBALS['ext_update_notes'][getCurrentExtensionName()][$ext_ver] = (string) $updateNotes;
1424         }
1425 }
1426
1427 // Getter for EXT_UPDATE_NOTES
1428 function getExtensionUpdateNotes ($ext_ver) {
1429         return $GLOBALS['ext_update_notes'][getCurrentExtensionName()][$ext_ver];
1430 }
1431
1432 // Checks if ext_update_notes is set
1433 function isExtensionUpdateNoteSet ($ext_ver) {
1434         return isset($GLOBALS['ext_update_notes'][getCurrentExtensionName()][$ext_ver]);
1435 }
1436
1437 // Init extension notice
1438 function initExtensionNotes ($force = false) {
1439         // Is it already initialized?
1440         if (($force === false) && (isset($GLOBALS['ext_notes'][getCurrentExtensionName()]))) {
1441                 // This is mostly not wanted, so please report it
1442                 debug_report_bug(__FUNCTION__, __LINE__, 'ext_notes already set for extension ' . getCurrentExtensionName());
1443         } // END - if
1444
1445         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'getCurrentExtensionName()=' . getCurrentExtensionName());
1446         $GLOBALS['ext_notes'][getCurrentExtensionName()] = '';
1447 }
1448
1449 // Append extension notice
1450 function appendExtensionNotes ($notes) {
1451         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'getCurrentExtensionName()=' . getCurrentExtensionName() . ', notes()=' . strlen($notes));
1452         $GLOBALS['ext_notes'][getCurrentExtensionName()] .= (string) trim($notes);
1453 }
1454
1455 // Getter for extension notes
1456 function getExtensionNotes () {
1457         return $GLOBALS['ext_notes'][getCurrentExtensionName()];
1458 }
1459
1460 // Setter for current extension name
1461 function setCurrentExtensionName ($ext_name) {
1462         $GLOBALS['curr_extension_name'] = (string) trim($ext_name);
1463 }
1464
1465 // Getter for current extension name
1466 function getCurrentExtensionName () {
1467         if (!isset($GLOBALS['curr_extension_name'])) {
1468                 // Not set!
1469                 debug_report_bug(__FUNCTION__, __LINE__, 'curr_extension_name not initialized. Please execute initExtensionSqls() before calling this function.');
1470         } // END - if
1471
1472         // Return it
1473         return $GLOBALS['curr_extension_name'];
1474 }
1475
1476 // Init SQLs array for current extension
1477 function initExtensionSqls ($force = false) {
1478         // Auto-init the array or if forced
1479         if (($force === true) || (!isset($GLOBALS['ext_sqls'][getCurrentExtensionName()]))) {
1480                 // Set the array
1481                 $GLOBALS['ext_sqls'][getCurrentExtensionName()] = array();
1482
1483                 // Initialize the generic array
1484                 initSqls();
1485         } // END - if
1486 }
1487
1488 // Adds SQLs to the SQLs array but "assigns" it with current extension name
1489 function addExtensionSql ($sql) {
1490         // Add it
1491         $GLOBALS['ext_sqls'][getCurrentExtensionName()][getCurrentExtensionVersion()][] = $sql;
1492 }
1493
1494 // Getter for SQLs array for current extension
1495 function getExtensionSqls () {
1496         // Output debug backtrace if not found (SHOULD NOT HAPPEN!)
1497         if (!isset($GLOBALS['ext_sqls'][getCurrentExtensionName()])) {
1498                 // Not found, should not happen
1499                 debug_report_bug(__FUNCTION__, __LINE__, sprintf("ext_sqls is empty, current extension: %s",
1500                         getCurrentExtensionName()
1501                 ));
1502         } // END - if
1503
1504         // Return the array
1505         return $GLOBALS['ext_sqls'][getCurrentExtensionName()];
1506 }
1507
1508 // Count SQLs for current extension
1509 function countExtensionSqls () {
1510         // Output debug backtrace if not found (SHOULD NOT HAPPEN!)
1511         if (!isset($GLOBALS['ext_sqls'][getCurrentExtensionName()])) {
1512                 // Not found, should not happen
1513                 debug_report_bug(__FUNCTION__, __LINE__, sprintf("ext_sqls is empty, current extension: %s",
1514                         getCurrentExtensionName()
1515                 ));
1516         } // END - if
1517
1518         // Count them all
1519         return count($GLOBALS['ext_sqls'][getCurrentExtensionName()]);
1520 }
1521
1522 // Removes SQLs for current extension
1523 function unsetExtensionSqls () {
1524         unset($GLOBALS['ext_sqls'][getCurrentExtensionName()]);
1525 }
1526
1527 // Auto-initializes the removal list
1528 function initExtensionRemovalList () {
1529         // Is the remove list there?
1530         if (!isset($GLOBALS['ext_update_remove'])) {
1531                 // Then create it
1532                 $GLOBALS['ext_update_remove'] = array();
1533         } // END - if
1534 }
1535
1536 // Checks wether the current extension is on the removal list
1537 function isExtensionOnRemovalList () {
1538         // Init removal list
1539         initExtensionRemovalList();
1540
1541         // Is it there?
1542         return (in_array(getCurrentExtensionName(), $GLOBALS['ext_update_remove']));
1543 }
1544
1545 // Adds the current extension to the removal list
1546 function addCurrentExtensionToRemovalList () {
1547         // Simply add it
1548         $GLOBALS['ext_update_remove'][] = getCurrentExtensionName();
1549 }
1550
1551 // Getter for removal list
1552 function getExtensionRemovalList () {
1553         // Return the removal list
1554         return $GLOBALS['ext_update_remove'];
1555 }
1556
1557 // Redirects if the provided extension is not installed
1558 function redirectOnUninstalledExtension ($ext_name) {
1559         // So is the extension there?
1560         if ((!isExtensionInstalled($ext_name)) || (!isExtensionActive($ext_name))) {
1561                 // Redirect to index
1562                 redirectToUrl('modules.php?module=index&amp;code=' . getCode('EXTENSION_PROBLEM') . '&amp;ext=' . $ext_name);
1563         } // END - if
1564 }
1565
1566 // Filter for initialization of all extensions by loading them in 'init' mode
1567 function FILTER_INIT_EXTENSIONS () {
1568         // Do we have some entries?
1569         //* DEBUG */ logDebugMessage(__FUNCTION__, __LINE__, 'ENTRY!');
1570         if (isset($GLOBALS['cache_array']['extension']['ext_name'])) {
1571                 // Load all found extensions if found
1572                 //* DEBUG */ logDebugMessage(__FUNCTION__, __LINE__, 'CACHE - START!');
1573                 foreach ($GLOBALS['cache_array']['extension']['ext_name'] as $key => $ext_name) {
1574                         // Load it
1575                         //* DEBUG */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name='.$ext_name.' - START');
1576                         loadExtension($ext_name, 'init', getExtensionVersion($ext_name));
1577                         //* DEBUG */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name='.$ext_name.' - END');
1578                 } // END - foreach
1579                 //* DEBUG */ logDebugMessage(__FUNCTION__, __LINE__, 'CACHE - END!');
1580         } // END - if
1581         //* DEBUG */ logDebugMessage(__FUNCTION__, __LINE__, 'EXIT!');
1582 }
1583
1584 // Setter for extension mode
1585 function setExtensionMode ($ext_mode) {
1586         $GLOBALS['ext_mode'] = (string) $ext_mode;
1587 }
1588
1589 // Getter for extension mode
1590 function getExtensionMode () {
1591         return $GLOBALS['ext_mode'];
1592 }
1593
1594 // Setter for dry-run
1595 function enableExtensionDryRun ($dry_run = true) {
1596         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'getCurrentExtensionName()='.getCurrentExtensionName().',dry='.intval($dry_run));
1597         $GLOBALS['ext_dry_run'] = (bool) $dry_run;
1598 }
1599
1600 // Getter for dry-run
1601 function isExtensionDryRun () {
1602         return $GLOBALS['ext_dry_run'];
1603 }
1604
1605 // Setter for current extension version
1606 function setCurrentExtensionVersion ($ext_ver) {
1607         // ext_ver should never be empty in other modes than 'test'
1608         if ((empty($ext_ver)) && (getExtensionMode() != 'test')) {
1609                 // Please report all these messages
1610                 debug_report_bug(__FUNCTION__, __LINE__, 'ext_ver is empty. Current extension name: ' . getCurrentExtensionName() . ', mode=' . getExtensionMode());
1611         } // END - if
1612
1613         // Add version
1614         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . getCurrentExtensionName() . ', ext_ver[' . gettype($ext_ver) . ']=' . $ext_ver);
1615         $GLOBALS['ext_current_version'][getCurrentExtensionName()] = (string) $ext_ver;
1616 }
1617
1618 // Getter for current extension version
1619 function getCurrentExtensionVersion () {
1620         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . getCurrentExtensionName() . ', ext_ver=' . $GLOBALS['ext_current_version'][getCurrentExtensionName()]);
1621         return $GLOBALS['ext_current_version'][getCurrentExtensionName()];
1622 }
1623
1624 // Remove the extension from cache array
1625 function removeExtensionFromArray () {
1626         // "Cache" this name
1627         $ext_name = getCurrentExtensionName();
1628
1629         // Now loop through the whole cache
1630         foreach ($GLOBALS['cache_array']['extension'] as $cacheName => $cacheArray) {
1631                 // Is it an element?
1632                 if (isset($cacheArray[$ext_name])) {
1633                         // Array element
1634                         unset($cacheArray[$ext_name]);
1635                         $GLOBALS['cache_array']['extension'][$cacheName] = $cacheArray;
1636                 } else {
1637                         // Maybe in array?
1638                         $key = array_search($ext_name, $cacheArray);
1639
1640                         // Is it there?
1641                         if ($key !== false) {
1642                                 // Found, so remove it
1643                                 unset($cacheArray[$key]);
1644                                 $GLOBALS['cache_array']['extension'][$cacheName] = $cacheArray;
1645                         } // END - if
1646                 }
1647         } // END - foreach
1648 }
1649
1650 // "Getter" for 'extension has a CSS file' (with same name, of course)
1651 function getExtensionHasCss () {
1652         // Default is no CSS
1653         $hasCss = 'N';
1654
1655         // Construct FQFN for check
1656         $FQFN = sprintf("%stheme/%s/css/%s.css",
1657                 getConfig('PATH'),
1658                 getCurrentTheme(),
1659                 getCurrentExtensionName()
1660         );
1661
1662         // Is it there?
1663         if (isFileReadable($FQFN)) {
1664                 // Readable, so it is there...
1665                 $hasCss = 'Y';
1666         } // END - if
1667
1668         // Return it
1669         return $hasCss;
1670 }
1671
1672 // Checks wether the given extension has a language file
1673 function ifExtensionHasLanguageFile ($ext_name) {
1674         // Default is no language file
1675         $hasLanguage = false;
1676
1677         // Do we have cache?
1678         if (isset($GLOBALS['cache_array']['extension']['ext_lang'][$ext_name])) {
1679                 // Then use it
1680                 $hasLanguage = ($GLOBALS['cache_array']['extension']['ext_lang'][$ext_name] == 'Y');
1681
1682                 // Count cache hits
1683                 incrementStatsEntry('cache_hits');
1684         } else {
1685                 // Not readable is default
1686                 $readable = 'N';
1687
1688                 // Is the language file readable for this extension?
1689                 if (isLanguageIncludeReadable($ext_name)) {
1690                         // Readable
1691                         $readable = 'Y';
1692                 } // END - if
1693
1694                 // Put it in cache
1695                 $GLOBALS['cache_array']['extension']['ext_lang'][$ext_name] = 'Y';
1696         }
1697
1698         // Return result
1699         return ($GLOBALS['cache_array']['extension']['ext_lang'][$ext_name] == 'Y');
1700 }
1701
1702 // Load an extension's include file
1703 function loadExtensionInclude () {
1704         // Is it readable?
1705         if (!isExtensionIncludeReadable()) {
1706                 // Not readable
1707                 debug_report_bug(__FUNCTION__, __LINE__, 'Extension ' . getCurrentExtensionName() . ' should be loaded, but is not readable.');
1708         } // END - if
1709
1710         // Generate INC name
1711         $INC = sprintf("inc/extensions/ext-%s.php", getCurrentExtensionName());
1712
1713         // Load it
1714         loadInclude($INC);
1715 }
1716
1717 // Checks wether an extension is readable
1718 function isExtensionIncludeReadable ($ext_name = '') {
1719         // If empty, use current
1720         if (empty($ext_name)) $ext_name = getCurrentExtensionName();
1721
1722         // Array found?
1723         if (!isset($GLOBALS['ext_inc_readable'][$ext_name])) {
1724                 // Generate INC name
1725                 $INC = sprintf("inc/extensions/ext-%s.php", getCurrentExtensionName());
1726
1727                 // Is it readable?
1728                 $GLOBALS['ext_inc_readable'][$ext_name] = isIncludeReadable($INC);
1729         } // END - if
1730
1731         // Return result
1732         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',realable='.intval($GLOBALS['ext_inc_readable'][$ext_name]));
1733         return $GLOBALS['ext_inc_readable'][$ext_name];
1734 }
1735
1736 // Checks if an extension's function file is readable
1737 function isExtensionFunctionFileReadable ($ext_name) {
1738         // Is cache there?
1739         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name);
1740         if (isset($GLOBALS['cache_array']['extension']['ext_func'][$ext_name])) {
1741                 // Just count cache hits
1742                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',ext_func=' . $GLOBALS['cache_array']['extension']['ext_func'][$ext_name] .' - CACHE!');
1743                 incrementStatsEntry('cache_hits');
1744         } else {
1745                 // Construct IFN for functions file
1746                 $funcsInclude = sprintf("inc/libs/%s_functions.php", $ext_name);
1747
1748                 // Is this include there?
1749                 if ((isFileReadable($funcsInclude)) && (!isset($GLOBALS['ext_loaded']['funcs'][$ext_name])) && (getExtensionMode() == 'test')) {
1750                         // Cache it!
1751                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',ext_func=Y - FOUND!');
1752                         $GLOBALS['cache_array']['extension']['ext_func'][$ext_name] = 'Y';
1753                 } else {
1754                         // Cache it!
1755                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',ext_func=N - NOT FOUND!');
1756                         $GLOBALS['cache_array']['extension']['ext_func'][$ext_name] = 'N';
1757                 }
1758         }
1759
1760         // Return result
1761         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',ext_func=' . $GLOBALS['cache_array']['extension']['ext_func'][$ext_name]);
1762         return ($GLOBALS['cache_array']['extension']['ext_func'][$ext_name] == 'Y');
1763 }
1764
1765 // Adds an admin menu to the SQL queue of the menu entry is not found
1766 function addAdminMenuSql ($action, $what, $title, $descr, $sort) {
1767         // Now check if this menu is there
1768         if (!isMenuActionValid('admin', $action, $what)) {
1769                 // Is what null?
1770                 if (is_null($what)) {
1771                         // Add main menu
1772                         $sql = sprintf("INSERT INTO `{?_MYSQL_PREFIX?}_admin_menu` (`action`,`what`,`title`,`descr`,`sort`) VALUES('%s',NULL,'%s','%s',%s)",
1773                                 $action,
1774                                 $title,
1775                                 $descr,
1776                                 bigintval($sort)
1777                         );
1778                 } else {
1779                         // Add sub menu
1780                         $sql = sprintf("INSERT INTO `{?_MYSQL_PREFIX?}_admin_menu` (`action`,`what`,`title`,`descr`,`sort`) VALUES('%s','%s','%s','%s',%s)",
1781                                 $action,
1782                                 $what,
1783                                 $title,
1784                                 $descr,
1785                                 bigintval($sort)
1786                         );
1787                 }
1788
1789                 // Add it to the queue
1790                 addExtensionSql($sql);
1791         } elseif (isDebugModeEnabled()) {
1792                 // Double menus should be located and fixed!
1793                 logDebugMessage(__FUNCTION__, __LINE__, sprintf("Double admin menu action=%s, what=%s detected.", $action, $what));
1794         }
1795 }
1796
1797 // Adds a guest menu to the SQL queue if the menu entry is not found
1798 function addGuestMenuSql ($action, $what, $title, $visible, $locked, $sort) {
1799         // Now check if this menu is there
1800         if (!isMenuActionValid('guest', $action, $what)) {
1801                 // Is what null?
1802                 if (is_null($what)) {
1803                         // Add main menu
1804                         $sql = sprintf("INSERT INTO `{?_MYSQL_PREFIX?}_guest_menu` (`action`,`what`,`title`,`visible`,`locked`,`sort`) VALUES('%s',NULL,'%s','%s','%s',%s)",
1805                                 $action,
1806                                 $title,
1807                                 $visible,
1808                                 $locked,
1809                                 bigintval($sort)
1810                         );
1811                 } else {
1812                         // Add sub menu
1813                         $sql = sprintf("INSERT INTO `{?_MYSQL_PREFIX?}_guest_menu` (`action`,`what`,`title`,`visible`,`locked`,`sort`) VALUES('%s','%s','%s','%s','%s',%s)",
1814                                 $action,
1815                                 $what,
1816                                 $title,
1817                                 $visible,
1818                                 $locked,
1819                                 bigintval($sort)
1820                         );
1821                 }
1822
1823                 // Add it to the queue
1824                 addExtensionSql($sql);
1825         } elseif (isDebugModeEnabled()) {
1826                 // Double menus should be located and fixed!
1827                 logDebugMessage(__FUNCTION__, __LINE__, sprintf("Double guest menu action=%s, what=%s detected.", $action, $what));
1828         }
1829 }
1830
1831 // Adds a member menu to the SQL queue if the menu entry is not found
1832 function addMemberMenuSql ($action, $what, $title, $visible, $locked, $sort) {
1833         // Now check if this menu is there
1834         if (!isMenuActionValid('member', $action, $what)) {
1835                 // Is what null?
1836                 if (is_null($what)) {
1837                         // Add main menu
1838                         $sql = sprintf("INSERT INTO `{?_MYSQL_PREFIX?}_member_menu` (`action`,`what`,`title`,`visible`,`locked`,`sort`) VALUES('%s',NULL,'%s','%s','%s',%s)",
1839                                 $action,
1840                                 $title,
1841                                 $visible,
1842                                 $locked,
1843                                 bigintval($sort)
1844                         );
1845                 } else {
1846                         // Add sub menu
1847                         $sql = sprintf("INSERT INTO `{?_MYSQL_PREFIX?}_member_menu` (`action`,`what`,`title`,`visible`,`locked`,`sort`) VALUES('%s','%s','%s','%s','%s',%s)",
1848                                 $action,
1849                                 $what,
1850                                 $title,
1851                                 $visible,
1852                                 $locked,
1853                                 bigintval($sort)
1854                         );
1855                 }
1856
1857                 // Add it to the queue
1858                 addExtensionSql($sql);
1859         } elseif (isDebugModeEnabled()) {
1860                 // Double menus should be located and fixed!
1861                 logDebugMessage(__FUNCTION__, __LINE__, sprintf("Double member menu action=%s, what=%s detected.", $action, $what));
1862         }
1863 }
1864
1865 // Adds a sponsor menu to the SQL queue if the menu entry is not found
1866 function addSponsorMenuSql ($action, $what, $title, $active, $sort) {
1867         // Now check if this menu is there, if no ext-sponsor is installed all is not yet added
1868         if ((!isExtensionInstalled('sponsor')) || (!isMenuActionValid('sponsor', $action, $what))) {
1869                 // Is what null?
1870                 if (is_null($what)) {
1871                         // Add main menu
1872                         $sql = sprintf("INSERT INTO `{?_MYSQL_PREFIX?}_sponsor_menu` (`action`,`what`,`title`,`active`,`sort`) VALUES('%s',NULL,'%s','%s',%s)",
1873                                 $action,
1874                                 $title,
1875                                 $active,
1876                                 bigintval($sort)
1877                         );
1878                 } else {
1879                         // Add sub menu
1880                         $sql = sprintf("INSERT INTO `{?_MYSQL_PREFIX?}_sponsor_menu` (`action`,`what`,`title`,`active`,`sort`) VALUES('%s','%s','%s','%s',%s)",
1881                                 $action,
1882                                 $what,
1883                                 $title,
1884                                 $active,
1885                                 bigintval($sort)
1886                         );
1887                 }
1888
1889                 // Add it to the queue
1890                 addExtensionSql($sql);
1891         } elseif (isDebugModeEnabled()) {
1892                 // Double menus should be located and fixed!
1893                 logDebugMessage(__FUNCTION__, __LINE__, sprintf("Double sponsor menu action=%s, what=%s detected.", $action, $what));
1894         }
1895 }
1896
1897 // Enables/disables productive mode for current extension (used only while
1898 // registration).
1899 function enableExtensionProductive ($isProductive = true) {
1900         $GLOBALS['ext_productive'][getCurrentExtensionName()] = (bool) $isProductive;
1901 }
1902
1903 // Checks wether the extension is in productive phase. If not set, development
1904 // phase (=false) is assumed.
1905 function isExtensionProductive () {
1906         return ((isset($GLOBALS['ext_productive'][getCurrentExtensionName()])) && ($GLOBALS['ext_productive'][getCurrentExtensionName()] === true));
1907 }
1908
1909 // [EOF]
1910 ?>