8dfde689bd230f9bc3be134c47b29850ef740518
[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  * -------------------------------------------------------------------- *
18  * Copyright (c) 2003 - 2009 by Roland Haeder                           *
19  * Copyright (c) 2009 - 2013 by Mailer Developer Team                   *
20  * For more information visit: http://mxchange.org                      *
21  *                                                                      *
22  * This program is free software; you can redistribute it and/or modify *
23  * it under the terms of the GNU General Public License as published by *
24  * the Free Software Foundation; either version 2 of the License, or    *
25  * (at your option) any later version.                                  *
26  *                                                                      *
27  * This program is distributed in the hope that it will be useful,      *
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
30  * GNU General Public License for more details.                         *
31  *                                                                      *
32  * You should have received a copy of the GNU General Public License    *
33  * along with this program; if not, write to the Free Software          *
34  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,               *
35  * MA  02110-1301  USA                                                  *
36  ************************************************************************/
37
38 // Some security stuff...
39 if (!defined('__SECURITY')) {
40         die();
41 } // END - if
42
43 // Load the extension and maybe found language and function files.
44 function loadExtension ($ext_name, $ext_mode, $ext_ver = '0.0.0', $isDryRun = FALSE, $previousExtension = NULL) {
45         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',ext_mode=' . $ext_mode . ',ext_ver=' . $ext_ver . ',isDryRun=' . intval($isDryRun) . ' - ENTERED!');
46         // Loading an extension in same mode, but not test/update, twice is not
47         // good, so is the extension $ext_name already loaded in mode $ext_mode?
48         if ((isset($GLOBALS['loaded_extension'][$ext_name][$ext_mode])) && (!in_array($ext_mode, array('update', 'test')))) {
49                 // If this happens twice, we need the bug report from you, except for updates/tests
50                 reportBug(__FUNCTION__, __LINE__, __FUNCTION__ . '() 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));
51         } // END - if
52
53         // Make sure this situation can only happen once
54         $GLOBALS['loaded_extension'][$ext_name][$ext_mode] = TRUE;
55
56         // Remember previous extension here
57         $GLOBALS['previous_extension'][$ext_name] = $previousExtension;
58
59         // Set extension mode
60         setExtensionMode($ext_mode);
61
62         // Set current extension name
63         setCurrentExtensionName($ext_name);
64
65         // By default all extensions are in productive phase
66         enableExtensionProductive();
67
68         if (!empty($ext_ver)) {
69                 // Set current extension version
70                 setCurrentExtensionVersion($ext_ver);
71         } else {
72                 // Set it to 0.0 by default
73                 setCurrentExtensionVersion('0.0.0');
74
75                 // Is the extension installed?
76                 if ((isExtensionInstalled($ext_name)) && ($ext_mode != 'setup')) {
77                         // Get extension's version
78                         setCurrentExtensionVersion(getExtensionVersion($ext_name));
79                 } // END - if
80
81                 // In all but test-mode we need these messages to debug! Please report all (together, e.g.)
82                 if (($ext_mode != 'test') && (getCurrentExtensionVersion() == '0.0.0')) {
83                         // Abort here, this must now always be set!
84                         reportBug(__FUNCTION__, __LINE__, 'Extension version is empty, setting to 0.0.0 ext_name=' . $ext_name . ', ext_mode=' . $ext_mode . ', isDryRun=' . intval($isDryRun));
85                 } // END - if
86         }
87
88         // Set dry-run
89         enableExtensionDryRun($isDryRun);
90
91         // Init array
92         initIncludePool('extension');
93
94         // Init EXT_UPDATE_DEPENDS if not yet done
95         if (!isExtensionUpdateDependenciesInitialized()) {
96                 // Init here...
97                 initExtensionUpdateDependencies();
98         } // END - if
99
100         // Init current extension name list
101         initExtensionSqls();
102
103         // Is the extension already loaded?
104         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Loading extension ' . $ext_name . ', getExtensionMode()=' . getExtensionMode() . ', getCurrentExtensionVersion()=' . getCurrentExtensionVersion());
105         if ((isExtensionLoaded($ext_name)) && (getExtensionMode() == 'init')) {
106                 // Debug message
107                 logDebugMessage(__FUNCTION__, __LINE__, sprintf('Extension %s already loaded.', $ext_name));
108
109                 // Abort here
110                 return FALSE;
111         } // END - if
112
113         // Is the extension file NOT there?
114         if (!isExtensionNameValid($ext_name)) {
115                 // Debug message
116                 logDebugMessage(__FUNCTION__, __LINE__, sprintf('Extension %s not found or not readable or the PHP script is deprecated.', $ext_name));
117
118                 // Abort here
119                 return FALSE;
120         } // END - if
121
122         // Load extension's own language file if not in test mode
123         if ((getExtensionMode() != 'test') && (isExtensionLanguageFileReadable($ext_name))) {
124                 // Load it
125                 loadLanguageFile($ext_name);
126         } // END - if
127
128         // Is there cache?
129         if (isExtensionFunctionFileReadable($ext_name)) {
130                 // Not yet loaded?
131                 if ((($GLOBALS['cache_array']['extension']['ext_func'][$ext_name] == 'Y') || (!isset($GLOBALS['cache_array']['extension']['ext_func'][$ext_name]))) && (!isExtensionLibraryLoaded($ext_name))) {
132                         // Construct IFN for functions file
133                         $funcsInclude = sprintf('inc/libs/%s_functions.php', $ext_name);
134
135                         // Mark it as loaded
136                         markExtensionLibraryAsLoaded($ext_name);
137
138                         // Download functions file
139                         loadIncludeOnce($funcsInclude);
140                 } // END - if
141         } elseif ((!isset($GLOBALS['cache_array']['extension']['ext_func'][$ext_name])) && (isDebugModeEnabled()) && (isHtmlOutputMode()) && ($ext_name != 'sql_patches') && (substr($ext_name, 0, 10) != 'admintheme') && (getExtensionMode() == 'test')) {
142                 // No functions file is not so good...
143                 logDebugMessage(__FUNCTION__, __LINE__, sprintf('NOTICE: Extension %s has no own functions file or we cannot read from it. mode=%s',
144                         $ext_name,
145                         getExtensionMode()
146                 ));
147         }
148
149         // Load extension's filter library if present
150         loadExtensionFilters($ext_name);
151
152         // Extensions are not deprecated by default
153         setExtensionDeprecated('N');
154
155         // Extensions are not always active by default
156         setExtensionAlwaysActive('N');
157
158         // Include the extension file
159         loadCurrentExtensionInclude();
160
161         // Load extra mode files
162         loadCurrentExtensionModeInclude();
163
164         // Is this extension deprecated?
165         if ((isExtensionDeprecated()) && (!in_array(getExtensionMode(), array('test', 'update', 'deactivate'))) && (isExtensionActive($ext_name))) {
166                 // Deactivate the extension
167                 doDeactivateExtension($ext_name);
168
169                 // Abort here
170                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Extension load aborted, ext_name=' . $ext_name . ' - Extension is deprecated.');
171                 return FALSE;
172         } // END - if
173
174         // Mark it as loaded in normal mode
175         if (getExtensionMode() == '') {
176                 // Mark it now...
177                 markExtensionAsLoaded($ext_name);
178         } // END - if
179
180         // All fine!
181         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Extension successfully loaded, ext_name=' . $ext_name);
182         return TRUE;
183 }
184
185 // Registers an extension and possible update dependencies
186 function registerExtension ($ext_name, $taskId, $isDryRun = FALSE, $ignoreUpdates = FALSE, $previousExtension = NULL) {
187         // Set current extension name
188         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',taskId=' . intval($taskId) . ',isDryRun=' . intval($isDryRun) . ',ignoreUpdates=' . intval($ignoreUpdates) . ' - ENTERED!');
189         setCurrentExtensionName($ext_name);
190
191         // Enable dry-run
192         enableExtensionDryRun($isDryRun);
193
194         // By default all extensions are in productive phase
195         enableExtensionProductive();
196
197         // This shall never do a non-admin user or if the extension is active (already installed)
198         if (((!isAdmin()) && (!isInstaller())) || (isExtensionInstalled($ext_name))) {
199                 // Abort here with 'false'
200                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ' - ABORTED: isAdmin()=' . intval(isAdmin()) . ',isInstaller()=' . intval(isInstaller()) . ',isExtensionInstalled()=' . intval(isExtensionInstalled($ext_name)));
201                 return FALSE;
202         } // END - if
203
204         // When this extension is already in registration/update phase, all is fine
205         if ((isExtensionRegistrationRunning($ext_name)) || ((isExtensionUpdateRunning($ext_name)) && ($ignoreUpdates === FALSE))) {
206                 // Then abort here with 'true' because it is fine
207                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ' - already in registration/update phase, all fine,isDryRun=' . intval($isDryRun) . ',ignoreUpdates=' . intval($ignoreUpdates));
208                 //* BUG: */ reportBug(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',isDryRun=' . intval($isDryRun) . ',ignoreUpdates=' . intval($ignoreUpdates) . ' - Please investigate!');
209                 return TRUE;
210         } // END - if
211
212         // This registration is running
213         addExtensionRunningRegistration($ext_name);
214
215         // Init EXT_UPDATE_DEPENDS if not yet done
216         if (!isExtensionUpdateDependenciesInitialized()) {
217                 // Init here...
218                 initExtensionUpdateDependencies();
219         } // END - if
220
221         // Is the task id zero? Then we need to auto-fix it here
222         if ((!isValidId($taskId)) && (!isInstaller())) {
223                 // Try to find the task
224                 $taskId = determineExtensionTaskId(getCurrentExtensionName());
225
226                 // Still zero and not in dry-run?
227                 if ((!isValidId($taskId)) && (!isExtensionDryRun())) {
228                         // Now try to create a new task
229                         $taskId = createNewExtensionTask(getCurrentExtensionName());
230
231                         // Is it still zero?
232                         if (!isValidId($taskId)) {
233                                 // Then request a bug report
234                                 reportBug(__FUNCTION__, __LINE__, sprintf('%s: task_id is still zero after determineExtensionTaskId/createNewExtensionTask(%s)',
235                                         __FUNCTION__,
236                                         getCurrentExtensionName()
237                                 ));
238                         } // END - if
239                 } // END - if
240         } // END - if
241
242         // Init queries and notes
243         initExtensionSqls();
244         initExtensionNotes();
245
246         // Init variables
247         $ret = FALSE;
248         $processResult = FALSE;
249         initIncludePool('extension');
250
251         // By default there is no failure
252         enableExtensionReportingFailure();
253
254         // Does this extension exists?
255         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . ' - CALLING loadExtension() ...');
256         if (loadExtension(getCurrentExtensionName(), 'setup', '0.0.0', isExtensionDryRun(), $previousExtension)) {
257                 // Set current extension name again
258                 setCurrentExtensionName($ext_name);
259
260                 // And run possible updates
261                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currentExtension=' . getCurrentExtensionName());
262                 $history = getExtensionVersionHistory();
263                 foreach ($history as $ext_ver) {
264                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . getCurrentExtensionName() . ', ext_ver=' . $ext_ver);
265                         // Load extension in update mode
266                         loadExtension(getCurrentExtensionName(), 'update', $ext_ver, isExtensionDryRun(), $previousExtension);
267
268                         // Add update notes to our output
269                         addExtensionNotes($ext_ver);
270                 } // END - foreach
271
272                 // Does this extension depends on an outstanding update of another update?
273                 for ($dmy = getExtensionUpdateIterator(); getExtensionUpdateIterator() < countExtensionUpdateDependencies();) {
274                         // Get next update
275                         $ext_update = getExtensionUpdateDependenciesIterator();
276
277                         // Increment here to avoid endless loop
278                         incrementExtensionUpdateIterator();
279
280                         // Check if extension is not installed and not already in registration procedure and if loading it wents finally fine...
281                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',isExtensionRegistrationRunning(' . $ext_update . ')=' . intval(isExtensionRegistrationRunning($ext_update)));
282                         if ((!isExtensionInstalled($ext_update)) && (!isExtensionRegistrationRunning($ext_update)) && (loadExtension($ext_update, 'test', '', isExtensionDryRun(), $previousExtension))) {
283                                 // Set current extension name again
284                                 setCurrentExtensionName($ext_name);
285
286                                 // If versions mismatch update extension first
287                                 $ext_ver = '';
288                                 if (isExtensionInstalled($ext_update)) {
289                                         // Get version only if installed
290                                         $ext_ver = getExtensionVersion($ext_update);
291                                 } // END - if
292
293                                 // Extension version set? If empty the extension is not registered
294                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_ver[' . gettype($ext_ver) . ']=' . $ext_ver . ',isInstaller()=' . intval(isInstaller()) . ',currName=' . getCurrentExtensionName() . ',ext_update=' . $ext_update . ' - EMPTY?');
295                                 if (empty($ext_ver)) {
296                                         // Extension not registered so far so first load task's id...
297                                         $updateTaskId = determineExtensionTaskId($ext_update);
298
299                                         // Entry found?
300                                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'updateTaskId=' . $updateTaskId . ',isInstaller()=' . intval(isInstaller()) . ',currName=' . getCurrentExtensionName() . ',ext_update=' . $ext_update . ' - CHECKING!');
301                                         if ((isValidId($updateTaskId)) || (isInstaller())) {
302                                                 // Try to register the extension
303                                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . ',ext_update=' . $ext_update . ',updateTaskId=' . $updateTaskId . ',isExtensionDryRun()=' . intval(isExtensionDryRun()));
304                                                 $processResult = registerExtension($ext_update, $updateTaskId, isExtensionDryRun(), TRUE, $ext_name);
305
306                                                 // Reset extension name
307                                                 setCurrentExtensionName($ext_name);
308                                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . ',ext_update=' . $ext_update . ',processResult=' . intval($processResult));
309                                         } // END - if
310                                 } elseif ($ext_ver != getCurrentExtensionVersion()) {
311                                         // Ok, update this extension now
312                                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . ',currVer=' . getCurrentExtensionVersion());
313                                         $GLOBALS['ext_backup_name'][$ext_update][$ext_ver] = getCurrentExtensionName();
314                                         $GLOBALS['ext_backup_ver'][$ext_update][$ext_ver] = getCurrentExtensionVersion();
315                                         updateExtension($ext_update, $ext_ver, isExtensionDryRun());
316                                         setCurrentExtensionName($GLOBALS['ext_backup_name'][$ext_update][$ext_ver]);
317                                         setCurrentExtensionVersion($GLOBALS['ext_backup_ver'][$ext_update][$ext_ver]);
318                                         unset($GLOBALS['ext_backup_name'][$ext_update][$ext_ver]);
319                                         unset($GLOBALS['ext_backup_ver'][$ext_update][$ext_ver]);
320                                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . ',currVer=' . getCurrentExtensionVersion());
321
322                                         // All okay!
323                                         $processResult = TRUE;
324                                 } else {
325                                         // Nothing to register / update before...
326                                         $processResult = TRUE;
327                                 }
328                         } else {
329                                 // Required file for update does not exists!
330                                 $processResult = TRUE;
331                                 // But this is fine for the first time...
332                         }
333
334                         // Restore the current extension name
335                         setCurrentExtensionName($ext_name);
336                 } // END - for
337
338                 // Is there no update?
339                 if (countExtensionUpdateDependencies(getCurrentExtensionName()) == 0) {
340                         // Then test is passed!
341                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . ',processResult=true,countExtensionUpdateDependencies()=0 - Test passed!');
342                         $processResult = TRUE;
343                 } // END - if
344
345                 // Switch back to register mode
346                 setExtensionMode('setup');
347
348                 // Remains true if extension registration reports no failures
349                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . ',processResult=' . intval($processResult));
350                 $processResult = (($processResult === TRUE) && (isExtensionReportingFailure() === FALSE));
351                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . ',processResult=' . intval($processResult));
352
353                 // Does everthing before wents ok?
354                 if ($processResult === TRUE) {
355                         // "Dry-run-mode" activated?
356                         if ((isExtensionDryRun() === FALSE) && (!isExtensionOnRemovalList())) {
357                                 // Init SQLs and transfer ext->generic
358                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . getCurrentExtensionName());
359                                 initSqls();
360                                 setSqlsArray(getExtensionSqls());
361
362                                 // Copy current name to save calls
363                                 $currentName = getCurrentExtensionName();
364
365                                 // Mark it as NOT installed
366                                 $GLOBALS['ext_is_installed'][$currentName] = FALSE;
367
368                                 // Run installation pre-installation filters
369                                 runFilterChain('pre_extension_installed', array('dry_run' => isExtensionDryRun(), 'ext_installing' => TRUE, 'enable_codes' => FALSE));
370
371                                 // Register extension
372                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'insert=' . $currentName . '/' . getCurrentExtensionVersion() . ' - INSERT!');
373                                 if (isExtensionInstalledAndNewer('sql_patches', '0.0.6')) {
374                                         // New way, with CSS
375                                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $currentName . ',always_active=' . getThisExtensionAlwaysActive() . ', ext_ver=' . getCurrentExtensionVersion() . 'ext_css=' . getExtensionHasCss());
376                                         sqlQueryEscaped("INSERT INTO `{?_MYSQL_PREFIX?}_extensions` (`ext_name`, `ext_active`, `ext_version`, `ext_has_css`) VALUES ('%s','%s','%s','%s')",
377                                                 array(
378                                                         $currentName,
379                                                         getThisExtensionAlwaysActive(),
380                                                         getCurrentExtensionVersion(),
381                                                         getExtensionHasCss()
382                                                 ), __FUNCTION__, __LINE__);
383                                 } else {
384                                         // Old way, no CSS
385                                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $currentName . ',always_active=' . getThisExtensionAlwaysActive() . ', ext_ver=' . getCurrentExtensionVersion());
386                                         sqlQueryEscaped("INSERT INTO `{?_MYSQL_PREFIX?}_extensions` (`ext_name`, `ext_active`, `ext_version`) VALUES ('%s','%s','%s')",
387                                                 array(
388                                                         $currentName,
389                                                         getThisExtensionAlwaysActive(),
390                                                         getCurrentExtensionVersion()
391                                                 ), __FUNCTION__, __LINE__);
392                                 }
393
394                                 /*
395                                  * Use the insert id as extension id and "cache" all data for
396                                  * this extension for early usage.
397                                  */
398                                 copyExtensionDataToCacheArray($currentName, getSqlInsertId());
399
400                                 // Mark it as installed
401                                 $GLOBALS['ext_is_installed'][$currentName] = TRUE;
402
403                                 /*
404                                  * Run filter chain after extension has been "installed" which
405                                  * means that the extension has been registered in 'extensions'
406                                  * table and marked as "installed".
407                                  */
408                                 runFilterChain('post_extension_installed', array(
409                                         'pool'     => 'extension',
410                                         'ext_name' => $currentName,
411                                         'task_id'  => $taskId
412                                 ));
413
414                                 // Re-init queries and notes
415                                 initExtensionSqls(TRUE);
416                                 initExtensionNotes(TRUE);
417
418                                 // In normal mode return a true on success
419                                 $ret = TRUE;
420                         } elseif (isExtensionDryRun() === TRUE) {
421                                 // In  "dry-run" mode do always return a true
422                                 $ret = TRUE;
423                         } else {
424                                 // Extension has been removed for updates, so all is fine!
425                                 $ret = TRUE;
426                         }
427                 } else {
428                         // No, an error occurs while registering extension :-(
429                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currentExtension=' . getCurrentExtensionName());
430                         $ret = FALSE;
431                 }
432         } elseif ((isValidId($taskId)) && (getCurrentExtensionName() != '')) {
433                 // Remove task from system when id and extension's name is valid
434                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName());
435                 sqlQueryEscaped("DELETE LOW_PRIORITY FROM `{?_MYSQL_PREFIX?}_task_system` WHERE `id`=%s AND `status`='NEW' LIMIT 1",
436                         array(bigintval($taskId)), __FUNCTION__, __LINE__);
437         }
438
439         // @TODO This redirect is still needed to register sql_patches! Please try to avoid it
440         if (($ret === TRUE) && ($isDryRun === FALSE) && ($ext_name == 'sql_patches') && (!isInstaller())) {
441                 /*
442                  * This is a really dirty hack to prevent an error about a missing
443                  * configuration entry which should be there after registration of
444                  * ext-sql_patches.
445                  */
446                 redirectToRequestUri();
447         } // END - if
448
449         // Return status code
450         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',currName=' . getCurrentExtensionName() . ',processResult=' . intval($processResult) . ',ret=' . intval($ret) . ' - EXIT!');
451         return $ret;
452 }
453
454 // Run SQL queries for given extension id
455 // @TODO Change from ext_id to ext_name (not just even the variable! ;-) )
456 function doExtensionSqls ($ext_id, $load_mode) {
457         // This shall never do a non-admin user but installation phase is okay
458         if ((!isAdmin()) && (!isInstaller())) {
459                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_id=' . $ext_id. ',load_mode=' . $load_mode . ',isAdmin()=' . intval(isAdmin()) . ',isInstaller()=' . intval(isInstaller()) . ' - ABORT!');
460                 return FALSE;
461         } // END - if
462
463         // Get extension's name
464         $ext_name = getExtensionName($ext_id);
465
466         // Set current SQL name
467         setCurrentExtensionName($ext_name);
468
469         // Init EXT_UPDATE_DEPENDS
470         if (!isExtensionUpdateDependenciesInitialized()) {
471                 // Init here...
472                 initExtensionUpdateDependencies();
473         } // END - if
474
475         // Init array
476         initExtensionSqls(TRUE);
477
478         // By default no SQL has been executed
479         $sqlRan = FALSE;
480
481         // Load extension in detected mode
482         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name[' . $ext_id . ']=' . getCurrentExtensionName() . ',load_mode=' . $load_mode);
483         loadExtension(getCurrentExtensionName(), $load_mode, '0.0.0', FALSE);
484
485         // Init these SQLs
486         initSqls();
487         setSqlsArray(getExtensionSqls());
488
489         // Debug message
490         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'SQLs::count=' . countSqls());
491
492         // Are there entries?
493         if (ifSqlsRegistered()) {
494                 // Run SQL commands...
495                 runFilterChain('run_sqls');
496         } // END - if
497
498         // Run any filters depending on the action here
499         runFilterChain('extension_' . $load_mode);
500
501         // Remove cache file(s) if extension is active
502         if (((isExtensionActive('cache')) && ((!ifSqlHasZeroAffectedRows()) || ($sqlRan === TRUE) || ($load_mode == 'activate') || ($load_mode == 'deactivate')))) {
503                 // Run filters
504                 runFilterChain('post_extension_run_sql', getCurrentExtensionName());
505         } // END - if
506
507         // Is this the sql_patches?
508         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'id=' . $ext_id . ',currName=' . getCurrentExtensionName() . ',loadMode=' . $load_mode);
509         if ((getCurrentExtensionName() == 'sql_patches') && (($load_mode == 'setup') || ($load_mode == 'remove'))) {
510                 // Then redirect to logout
511                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, ': LOAD!');
512                 redirectToUrl('modules.php?module=admin&amp;logout=1&amp;' . $load_mode . '=sql_patches');
513         } // END - if
514 }
515
516 // Check whether the given extension is installed
517 function isExtensionInstalled ($ext_name) {
518         // We don't like empty extension names here
519         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ' - ENTERED!');
520         if (empty($ext_name)) {
521                 // Please fix them all
522                 reportBug(__FUNCTION__, __LINE__, 'ext_name is empty.');
523         } // END - if
524
525         // By default non is installed
526         $isInstalled = FALSE;
527
528         // Check if there is a cache entry
529         if (isset($GLOBALS['ext_is_installed'][$ext_name])) {
530                 // Use cache built from below queries
531                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ' - CACHE!');
532                 $isInstalled = $GLOBALS['ext_is_installed'][$ext_name];
533         } elseif (isset($GLOBALS['cache_array']['extension']['ext_id'][$ext_name])) {
534                 // Found!
535                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ' - FOUND!');
536                 $isInstalled = TRUE;
537
538                 // Count cache hits
539                 incrementStatsEntry('cache_hits');
540         } elseif ((isInstaller()) && (!isSqlLinkUp())) {
541                 // Extensions are all inactive/not installed during installation
542                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ' - installation phase detected.');
543         } else {
544                 // Look in database
545                 $ext_id = getExtensionId($ext_name);
546
547                 // Is there a record?
548                 $isInstalled = isValidId($ext_id);
549
550                 // Log debug message
551                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',ext_id=' . $ext_id . ',isInstalled=' . intval($isInstalled));
552
553                 // Is it installed, then cache the entry
554                 if ($isInstalled === TRUE) {
555                         // Dummy call (get is okay here)
556                         getExtensionId($ext_name, TRUE);
557                 } // END - if
558
559                 // Remember the status
560                 $GLOBALS['ext_is_installed'][$ext_name] = $isInstalled;
561         }
562
563         // Return status
564         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',isInstalled=' . intval($isInstalled) . ' - EXIT!');
565         return $isInstalled;
566 }
567
568 // Check if given extension is active
569 function isExtensionActive ($ext_name) {
570         if ((isInstaller()) && (!isSqlLinkUp())) {
571                 // Extensions are all inactive during installation
572                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Extensions are always inactive while installation phase. ext_name=' . $ext_name);
573                 return FALSE;
574         } elseif (empty($ext_name)) {
575                 // Empty extension names must befixed
576                 reportBug(__FUNCTION__, __LINE__, 'Empty extension name provided.');
577         } elseif (!isExtensionInstalled($ext_name)) {
578                 // Not installed extensions are always inactive
579                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Not installed extensions are always inactive. ext_name=' . $ext_name);
580                 return FALSE;
581         }
582
583         // Not active is the default
584         $data['ext_active'] = 'N';
585
586         // Check cache
587         if (isset($GLOBALS['cache_array']['extension']['ext_active'][$ext_name])) {
588                 // Load from cache
589                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'CACHE! ext_name=' . $ext_name);
590                 $data['ext_active'] = $GLOBALS['cache_array']['extension']['ext_active'][$ext_name];
591
592                 // Count cache hits
593                 incrementStatsEntry('cache_hits');
594         } elseif (isExtensionLoaded($ext_name)) {
595                 // @TODO Extension is loaded, what next?
596                 reportBug(__FUNCTION__, __LINE__, 'LOADED:' . $ext_name);
597         } elseif (($ext_name == 'cache') || (!isExtensionInstalled('cache'))) {
598                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'DB! ext_name=' . $ext_name);
599                 // Load from database
600                 $result = sqlQueryEscaped("SELECT * FROM `{?_MYSQL_PREFIX?}_extensions` WHERE `ext_name`='%s' LIMIT 1",
601                         array($ext_name), __FUNCTION__, __LINE__);
602
603                 // Entry found?
604                 if (sqlNumRows($result) == 1) {
605                         // Load entry
606                         $data = sqlFetchArray($result);
607
608                         // Set cache
609                         setExtensionCacheRow($ext_name, $data);
610                 } // END - if
611
612                 // Free result
613                 sqlFreeResult($result);
614         } else {
615                 // Extension not active!
616                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ': Not active!');
617                 $GLOBALS['cache_array']['extension']['ext_active'][$ext_name] = 'N';
618         }
619
620         // Debug message
621         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',active=' . $data['ext_active']);
622
623         // Is this extension activated? (For admins we always have active extensions...)
624         return ($data['ext_active'] == 'Y');
625 }
626
627 // Sets extension cache row
628 function setExtensionCacheRow ($ext_name, &$data) {
629         // Add all
630         foreach ($data as $key => $value) {
631                 // Is key=id?
632                 if ($key == 'id') {
633                         $data['ext_id'] = $value;
634                         $key == 'ext_id';
635                 } // END - if
636
637                 // Is key=ext_has_css?
638                 if ($key == 'ext_has_css') {
639                         $data['ext_css'] = $value;
640                         $key == 'ext_css';
641                 } // END - if
642
643                 // Set all entries
644                 if ($key == 'ext_name') {
645                         $GLOBALS['cache_array']['extension']['ext_name'][$data['id']] = $value;
646                 } else {
647                         // Add ordinary entry
648                         $GLOBALS['cache_array']['extension'][$key][$ext_name] = $value;
649                 }
650         } // END - foreach
651 }
652
653 // Get version from extensions
654 function getExtensionVersion ($ext_name, $force = FALSE) {
655         // By default no extension is found
656         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ' - ENTERED!');
657         $data['ext_version'] = 'false';
658
659         // Empty extension name should be fixed!
660         if (empty($ext_name)) {
661                 // Please report this bug!
662                 reportBug(__FUNCTION__, __LINE__, 'ext_name is empty which is not allowed here.');
663         } // END - if
664
665         // Extensions are all inactive during installation
666         if ((isInstaller()) && (!isSqlLinkUp())) {
667                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',force=' . intval($force) . ' - Installation phase detected, returning empty version.');
668                 return '';
669         } // END - if
670
671         // Is the cache written?
672         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ' - Checking cache ...');
673         if (isset($GLOBALS['cache_array']['extension']['ext_version'][$ext_name])) {
674                 // Load data from cache
675                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ' - CACHE!');
676                 $data['ext_version'] = $GLOBALS['cache_array']['extension']['ext_version'][$ext_name];
677
678                 // Count cache hits
679                 incrementStatsEntry('cache_hits');
680         } elseif ((!isValidCacheInstance()) || (isset($GLOBALS['cache_array']['extension'])) || (!isHtmlOutputMode())) {
681                 // Load from database
682                 $result = sqlQueryEscaped("SELECT * FROM `{?_MYSQL_PREFIX?}_extensions` WHERE `ext_name`='%s' LIMIT 1",
683                         array($ext_name), __FUNCTION__, __LINE__);
684                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ': DB - '.sqlNumRows($result).'');
685
686                 // Is the extension there?
687                 if (sqlNumRows($result) == 1) {
688                         // Load entry
689                         $data = sqlFetchArray($result);
690
691                         // Set cache
692                         setExtensionCacheRow($ext_name, $data);
693                 } elseif (isDebugModeEnabled()) {
694                         // Not found, may happen while an extension is uninstalled
695                         logDebugMessage(__FUNCTION__, __LINE__, sprintf('Cannot find extension %s in database!', $ext_name));
696                 }
697
698                 // Free result
699                 sqlFreeResult($result);
700         }
701
702         // Extension version should not be invalid
703         if (($data['ext_version'] == 'false') && ($force === FALSE)) {
704                 // Please report this trouble
705                 reportBug(__FUNCTION__, __LINE__, sprintf('Extension <span class="data">%s</span> has empty version!', $ext_name));
706         } // END - if
707
708         // Return result
709         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_version=' . $data['ext_version']);
710         return $data['ext_version'];
711 }
712
713 // Updates a given extension with current extension version to latest version
714 function updateExtension ($ext_name, $ext_ver, $isDryRun = FALSE, $ignoreDependencies = FALSE) {
715         // Only admins are allowed to update extensions
716         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',ext_ver=' . $ext_ver . ',isDryRun=' . intval($isDryRun) . ',ignoreDependencies=' . intval($ignoreDependencies) . ' - ENTERED!');
717         if ((!isAdmin()) || (empty($ext_name))) {
718                 // Called as non-admin or empty extension
719                 reportBug(__FUNCTION__, __LINE__, 'Called as non-admin (isAdmin()=' . intval(isAdmin()) . '), or empty extension name. ext_name=' . $ext_name);
720         } // END - if
721
722         // Set current SQL name
723         setCurrentExtensionName($ext_name);
724
725         // Is this extension update already running?
726         if ((isExtensionUpdateRunning($ext_name, $ignoreDependencies)) && ($isDryRun === FALSE)) {
727                 // This is fine but needs logging ATM
728                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ' - already in update phase, all fine.');
729                 //* BUG: */ reportBug(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ' - already in update phase, please investigate!');
730                 return TRUE;
731         } // END - if
732
733         // Init arrays
734         initExtensionSqls();
735         initExtensionNotes();
736         initIncludePool('extension');
737
738         // Load extension in test mode
739         loadExtension($ext_name, 'test', $ext_ver, isExtensionDryRun());
740
741         // Save version history
742         $history = getExtensionVersionHistory();
743
744         // Remove old SQLs array to prevent possible bugs
745         initExtensionSqls();
746
747         // Check if version is updated
748         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, getCurrentExtensionName() . '/' . $ext_name . ':' . getThisExtensionVersion() . '/' . $ext_ver . '/' . intval(is_array($history)));
749         if (((getThisExtensionVersion() != $ext_ver) || (isExtensionDryRun())) && (is_array($history))) {
750                 // Search for starting point (-1 for making 0.0 -> 0.0.0 switch work)
751                 $start = -1;
752                 if ($ext_ver != '0.0') {
753                         $start = array_search($ext_ver, $history);
754                 } // END - if
755
756                 // And load SQL queries in order of version history
757                 for ($idx = ($start + 1); $idx < count($history); $idx++) {
758                         // Set extension version
759                         $GLOBALS['update_ver'][getCurrentExtensionName()] = $history[$idx];
760
761                         // Load again...
762                         loadExtension(getCurrentExtensionName(), 'update', $GLOBALS['update_ver'][getCurrentExtensionName()], isExtensionDryRun());
763
764                         // Get all depencies
765                         $depencies = getExtensionUpdateDependencies();
766
767                         // Nothing to apply?
768                         if (isFilledArray($depencies)) {
769                                 // Apply all extension depencies
770                                 foreach ($depencies as $ext_depend) {
771                                         // Did we already update/register this?
772                                         if (!isset($GLOBALS['ext_updated'][$ext_depend])) {
773                                                 // Set it as current
774                                                 setCurrentExtensionName($ext_depend);
775
776                                                 // Mark it as already updated before we update it
777                                                 $GLOBALS['ext_updated'][$ext_depend] = TRUE;
778
779                                                 // Is the extension there?
780                                                 if (isExtensionInstalled($ext_depend)) {
781                                                         // Update another extension first!
782                                                         $processResult = updateExtension($ext_depend, getExtensionVersion($ext_depend), isExtensionDryRun(), TRUE);
783                                                 } else {
784                                                         // Register new extension
785                                                         $processResult = registerExtension($ext_depend, NULL, isExtensionDryRun());
786                                                 }
787                                         } // END - if
788                                 } // END - foreach
789
790                                 // Set name back
791                                 setCurrentExtensionName($ext_name);
792
793                                 // Set extension version here
794                                 setCurrentExtensionVersion($ext_ver);
795                         } // END - if
796
797                         // Add notes
798                         addExtensionNotes($history[$idx]);
799                 } // END - for
800
801                 // In real-mode execute any existing includes
802                 if (isExtensionDryRun() === FALSE) {
803                         $GLOBALS['ext_inc_pool'][getCurrentExtensionName()] = getIncludePool('extension');
804                         runFilterChain('load_includes', 'extension');
805                         setIncludePool('extension', $GLOBALS['ext_inc_pool'][getCurrentExtensionName()]);
806                         unset($GLOBALS['ext_inc_pool'][getCurrentExtensionName()]);
807                 } // END - if
808
809                 // Init these SQLs
810                 initSqls();
811                 setSqlsArray(getExtensionSqls());
812
813                 // Run SQLs
814                 runFilterChain('run_sqls', array('dry_run' => isExtensionDryRun(), 'ext_installing' => TRUE, 'enable_codes' => FALSE));
815
816                 if (isExtensionDryRun() === FALSE) {
817                         // Run filters on success extension update
818                         runFilterChain('extension_update', getCurrentExtensionName());
819                 } // END - if
820         } // END - if
821
822         //* DEBUG: */logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',ext_ver=' . $ext_ver . ',isDryRun=' . intval($isDryRun) . ',ignoreDependencies=' . intval($ignoreDependencies) . ' - EXIT!');
823 }
824
825 // Output verbose SQL table for extension
826 function addExtensionVerboseSqlTable ($title = '{--ADMIN_SQLS_EXECUTED_ON_REMOVAL--}') {
827         // Empty title?
828         if (empty($title)) {
829                 // Then abort here
830                 reportBug(__FUNCTION__, __LINE__, 'title is empty.');
831         } // END - if
832
833         // Init variables
834         $OUT = '';
835
836         // Is there queries?
837         if (isVerboseSqlEnabled()) {
838                 // Are there entries?
839                 if (countExtensionSqls() > 0) {
840                         // Init counter
841                         $idx = 0;
842                         // Get all SQLs
843                         foreach (getExtensionSqls() as $sqls) {
844                                 // New array format is recursive
845                                 foreach ($sqls as $sql) {
846                                         // Trim out spaces
847                                         $sql = trim($sql);
848
849                                         // Output command if set
850                                         if (!empty($sql)) {
851                                                 // Prepare output for template
852                                                 $content = array(
853                                                         'i'   => ($idx + 1),
854                                                         'sql' => str_replace(array('{', '}'), array('&#123;', '&#125;'), encodeEntities($sql))
855                                                 );
856
857                                                 // Load row template
858                                                 $OUT .= loadTemplate('admin_extension_sql_row', TRUE, $content);
859
860                                                 // Count up
861                                                 $idx++;
862                                         } // END - if
863                                 } // END - foreach
864                         } // END - foreach
865
866                         // Prepare content for template
867                         $content = array(
868                                 'title'  => $title,
869                                 'rows'   => $OUT
870                         );
871
872                         // Load main template
873                         $OUT = loadTemplate('admin_extension_sql_table', TRUE, $content);
874                 } else {
875                         // No addional SQL commands to run
876                         $OUT = displayMessage('{--ADMIN_EXTENSION_VERBOSE_SQLS_404--}', TRUE);
877                 }
878         } // END - if
879
880         // Return output
881         return $OUT;
882 }
883
884 // Get extension name from id
885 function getExtensionName ($ext_id) {
886         // Init extension name
887         $data['ext_name'] = '';
888
889         // Is cache there?
890         if (isset($GLOBALS['cache_array']['extension']['ext_name'][$ext_id])) {
891                 // Load from cache
892                 $data['ext_name'] = $GLOBALS['cache_array']['extension']['ext_name'][$ext_id];
893
894                 // Count cache hits
895                 incrementStatsEntry('cache_hits');
896         } elseif (!isExtensionActive('cache')) {
897                 // Load from database
898                 $result = sqlQueryEscaped("SELECT `ext_name` FROM `{?_MYSQL_PREFIX?}_extensions` WHERE `id`=%s LIMIT 1",
899                         array(bigintval($ext_id)), __FUNCTION__, __LINE__);
900
901                 // Is the entry there?
902                 if (sqlNumRows($result) == 1) {
903                         // Get the extension's name from database
904                         $data = sqlFetchArray($result);
905                 } // END - if
906
907                 // Free result
908                 sqlFreeResult($result);
909         }
910
911         // Did we find some extension?
912         if (empty($data['ext_name'])) {
913                 // We should fix these all!
914                 reportBug(__FUNCTION__, __LINE__, 'ext_name is empty. ext_id=' . $ext_id);
915         } // END - if
916
917         // Return the extension name
918         return $data['ext_name'];
919 }
920
921 // Get extension id from name
922 function getExtensionId ($ext_name) {
923         // Init id number
924         $data['ext_id'] = '0';
925
926         // Is there cache?
927         if (isset($GLOBALS['cache_array']['extension']['ext_id'][$ext_name])) {
928                 // Load from cache
929                 $data['ext_id'] = $GLOBALS['cache_array']['extension']['ext_id'][$ext_name];
930
931                 // Count cache hits
932                 incrementStatsEntry('cache_hits');
933         } else {
934                 // Load from database
935                 $result = sqlQueryEscaped("SELECT * FROM `{?_MYSQL_PREFIX?}_extensions` WHERE `ext_name`='%s' LIMIT 1",
936                         array($ext_name), __FUNCTION__, __LINE__);
937
938                 // Is the entry there?
939                 if (sqlNumRows($result) == 1) {
940                         // Get the extension's id from database
941                         $data = sqlFetchArray($result);
942
943                         // Set cache
944                         setExtensionCacheRow($ext_name, $data);
945                 } // END - if
946
947                 // Free result
948                 sqlFreeResult($result);
949         }
950
951         // Return value
952         return $data['ext_id'];
953 }
954
955 // Determines whether the given extension name is valid
956 function isExtensionNameValid ($ext_name) {
957         // Is there cache?
958         if (!isset($GLOBALS['ext_name_valid'][$ext_name])) {
959                 // Generate include file name
960                 $INC = sprintf("inc/extensions/ext-%s.php", $ext_name);
961
962                 // Is there a file in inc/extensions/ ?
963                 $GLOBALS['ext_name_valid'][$ext_name] = isIncludeReadable($INC);
964         } // END - if
965
966         // Return result
967         return $GLOBALS['ext_name_valid'][$ext_name];
968 }
969
970 // Determines whether the given extension id is valid
971 function isExtensionIdValid ($ext_id) {
972         // Default is nothing valid
973         $isValid = FALSE;
974
975         // Check in cache then in database
976         if (isset($GLOBALS['cache_array']['extension']['ext_name'][$ext_id])) {
977                 // Valid!
978                 $isValid = TRUE;
979
980                 // Count cache hits
981                 incrementStatsEntry('cache_hits');
982         } else {
983                 // Query database
984                 $isValid = (countSumTotalData($ext_id, 'extensions', 'id', 'id', TRUE) == 1);
985         }
986
987         // Return result
988         return $isValid;
989 }
990
991 // Activate given extension
992 function doActivateExtension ($ext_name) {
993         // Is the extension installed?
994         if (!isExtensionInstalled($ext_name)) {
995                 // Non-installed extensions cannot be activated
996                 reportBug(__FUNCTION__, __LINE__, 'Tried to activate non-installed extension ' . $ext_name);
997         } // END - if
998
999         // Activate the extension
1000         sqlQueryEscaped("UPDATE `{?_MYSQL_PREFIX?}_extensions` SET `ext_active`='Y' WHERE `ext_name`='%s' LIMIT 1",
1001                 array($ext_name), __FUNCTION__, __LINE__);
1002
1003         // Then run all queries
1004         doExtensionSqls(getExtensionId($ext_name), 'activate');
1005 }
1006
1007 // Deactivate given extension
1008 function doDeactivateExtension ($ext_name, $inRebuild = FALSE) {
1009         // Is the extension installed?
1010         if (!isExtensionInstalled($ext_name)) {
1011                 // Non-installed extensions cannot be activated
1012                 reportBug(__FUNCTION__, __LINE__, 'Tried to deactivate non-installed extension ' . $ext_name . ',getExtensionMode()=' . getExtensionMode());
1013         } // END - if
1014
1015         // Activate the extension
1016         sqlQueryEscaped("UPDATE `{?_MYSQL_PREFIX?}_extensions` SET `ext_active`='N' WHERE `ext_name`='%s' LIMIT 1",
1017                 array($ext_name), __FUNCTION__, __LINE__);
1018
1019         // Then run all queries
1020         doExtensionSqls(getExtensionId($ext_name), 'deactivate');
1021
1022         // Create new task (we ignore the task id here)
1023         createExtensionDeactivationTask($ext_name);
1024
1025         // Do not rebuild cache if it is already been rebuild
1026         if ($inRebuild === FALSE) {
1027                 // Rebuild cache
1028                 rebuildCache('extension', 'extension');
1029         } // END - if
1030
1031         // Notify the admin
1032         sendAdminNotification(
1033                 '{--ADMIN_EXTENSION_DEACTIVATED_SUBJECT--}',
1034                 'admin_extension_deactivated',
1035                 array('ext_name' => $ext_name)
1036         );
1037 }
1038
1039 // Creates a new task for updated extension
1040 function createExtensionUpdateTask ($adminId, $ext_name, $ext_ver, $notes) {
1041         // Create subject line
1042         $subject = '[UPDATE-' . $ext_name . '-' . $ext_ver . ':] {--ADMIN_UPDATE_EXTENSION_SUBJECT--}';
1043
1044         // Get task id
1045         $taskId = determineTaskIdBySubject($subject);
1046
1047         // Is the extension there?
1048         if (isExtensionInstalled($ext_name)) {
1049                 // Check if task is not there
1050                 if (!isValidId($taskId)) {
1051                         // Create extension update-task
1052                         $taskId = createNewTask($subject, $notes, 'EXTENSION_UPDATE', 0, $adminId);
1053                 } // END - if
1054         } else {
1055                 // Extension not there! :-(
1056                 reportBug(__FUNCTION__, __LINE__, sprintf("Extension <span class=\"data\">%s</span> not found but should be updated?", $ext_name));
1057         }
1058
1059         // Return task id
1060         return $taskId;
1061 }
1062
1063 // Creates a new task for newly installed extension
1064 function createNewExtensionTask ($ext_name) {
1065         // Generate subject line
1066         $subject = sprintf("[%s:]", $ext_name);
1067
1068         // Get task id
1069         $taskId = determineTaskIdBySubject($subject);
1070
1071         // Not installed and do we have created a task for the admin?
1072         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',taskId[' . gettype($taskId) . ']=' . $taskId);
1073         if ((!isValidId($taskId)) && (!isExtensionInstalled($ext_name))) {
1074                 // Set default message if ext-foo is missing
1075                 $message = '{%message,ADMIN_EXTENSION_TEXT_FILE_MISSING=' . $ext_name . '%}';
1076
1077                 // Template file
1078                 $FQFN = sprintf('%s/ext/ext_%s.tpl',
1079                         getTemplateBasePath('html'),
1080                         $ext_name
1081                 );
1082
1083                 // Load text for task if found
1084                 if (isFileReadable($FQFN)) {
1085                         // Load extension's description template (but do not compile the code)
1086                         $message = '{OPEN_TEMPLATE}template,LoadTemplate=ext_' . $ext_name . '{CLOSE_TEMPLATE}';
1087                 } else {
1088                         // Write this in debug.log as well
1089                         logDebugMessage(__FUNCTION__, __LINE__, $message);
1090                 }
1091
1092                 // Task not created so it's a brand-new extension which we need to register and create a task for!
1093                 $taskId = createNewTask($subject, $message, 'EXTENSION', 0, getCurrentAdminId(), FALSE);
1094         } // END - if
1095
1096         // Return task id
1097         return $taskId;
1098 }
1099
1100 // Creates a task for automatically deactivated (deprecated) extension
1101 function createExtensionDeactivationTask ($ext_name) {
1102         // Create subject line
1103         $subject = sprintf("[%s:] %s", $ext_name, '{--ADMIN_TASK_EXTENSION_DEACTIVATED_SUBJECT--}');
1104
1105         // Get task id
1106         $taskId = determineTaskIdBySubject($subject);
1107
1108         // Not installed and do we have created a task for the admin?
1109         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',taskId[' . gettype($taskId) . ']=' . $taskId);
1110         if ((!isValidId($taskId)) && (isExtensionInstalled($ext_name))) {
1111                 // Task not created so add it
1112                 $taskId = createNewTask($subject, sqlEscapeString(loadTemplate('task_EXTENSION_deactivated', TRUE, $ext_name)), 'EXTENSION_DEACTIVATION');
1113         } // END - if
1114
1115         // Return task id
1116         return $taskId;
1117 }
1118
1119 // Determines the task id for given extension
1120 function determineExtensionTaskId ($ext_name) {
1121         // Is it installation phase and table task_system is not found?
1122         if ((isInstaller()) && (!ifSqlTableExists('task_system'))) {
1123                 // Then return NULL (not found)
1124                 return NULL;
1125         } // END - if
1126
1127         // Default is not found
1128         $data['task_id'] = NULL;
1129
1130         // Search for extension task's id
1131         $result = sqlQueryEscaped("SELECT `id` AS `task_id` FROM `{?_MYSQL_PREFIX?}_task_system` WHERE `task_type`='EXTENSION' AND `subject`='[%s:]' LIMIT 1",
1132                 array($ext_name), __FUNCTION__, __LINE__);
1133
1134         // Entry found?
1135         if (sqlNumRows($result) == 1) {
1136                 // Task found so load task's id and register extension...
1137                 $data = sqlFetchArray($result);
1138         } // END - if
1139
1140         // Free result
1141         sqlFreeResult($result);
1142
1143         // Return it
1144         return $data['task_id'];
1145 }
1146
1147 // Determines the task id for given subject
1148 function determineTaskIdBySubject ($subject) {
1149         // Default is not found
1150         $data['task_id'] = '0';
1151
1152         // Search for task id
1153         $result = sqlQueryEscaped("SELECT `id` AS `task_id` FROM `{?_MYSQL_PREFIX?}_task_system` WHERE `subject` LIKE '%s%%' LIMIT 1",
1154                 array($subject), __FUNCTION__, __LINE__);
1155
1156         // Entry found?
1157         if (sqlNumRows($result) == 1) {
1158                 // Task found so load task's id and register extension...
1159                 $data = sqlFetchArray($result);
1160         } // END - if
1161
1162         // Free result
1163         sqlFreeResult($result);
1164
1165         // Return it
1166         return $data['task_id'];
1167 }
1168
1169 // Add updates notes for given version
1170 function addExtensionNotes ($ext_ver) {
1171         // Init notes/content
1172         $out = '';
1173         $content = array();
1174
1175         // Is do we have verbose output enabled?
1176         if ((!isExtensionActive('sql_patches')) || (isVerboseSqlEnabled())) {
1177                 // Update notes found?
1178                 if ((isExtensionUpdateNoteSet($ext_ver)) && ($ext_ver != '0.0.0')) {
1179                         // Update notes found
1180                         $content = array(
1181                                 'ver'   => $ext_ver,
1182                                 'notes' => getExtensionUpdateNotes($ext_ver)
1183                         );
1184
1185                         // Reset them
1186                         setExtensionUpdateNotes('', $ext_ver);
1187                 } elseif ($ext_ver == '0.0.0') {
1188                         // Is the extension productive?
1189                         if (isExtensionProductive(getCurrentExtensionName())) {
1190                                 // Initial release
1191                                 $content = array(
1192                                         'ver'   => $ext_ver,
1193                                         'notes' => '{--ADMIN_EXTENSION_INITIAL_RELEASE--}'
1194                                 );
1195                         } else {
1196                                 // Not productive
1197                                 $content = array(
1198                                         'ver'   => $ext_ver,
1199                                         'notes' => '{--ADMIN_EXTENSION_DEVELOPER_RELEASE--}'
1200                                 );
1201                         }
1202                 } else {
1203                         // No update notes found
1204                         $content = array(
1205                                 'ver'   => $ext_ver,
1206                                 'notes' => '{--ADMIN_EXTENSION_UPDATE_NOTICES_404--}'
1207                         );
1208                 }
1209
1210                 // Load template
1211                 $out = loadTemplate('admin_extension_notes', TRUE, $content);
1212         } // END - if
1213
1214         // Add the notes
1215         appendExtensionNotes($out);
1216 }
1217
1218 // Getter for CSS files array
1219 function getExtensionCssFiles () {
1220         // By default no additional CSS files are found
1221         $cssFiles = array();
1222
1223         // Is the array there?
1224         if (isset($GLOBALS['css_files'])) {
1225                 // Then use it
1226                 $cssFiles = $GLOBALS['css_files'];
1227         } // END - if
1228
1229         // Return array
1230         return $cssFiles;
1231 }
1232
1233 // Init CSS files array
1234 function initExtensionCssFiles () {
1235         // Simply init it
1236         $GLOBALS['css_files'] = array();
1237 }
1238
1239 // Add new entry
1240 function addExtensionCssFile ($file) {
1241         // Is the array there?
1242         if (!isset($GLOBALS['css_files'])) {
1243                 // Then auto-init them
1244                 initExtensionCssFiles();
1245         } // END - if
1246
1247         // Add the entry
1248         array_push($GLOBALS['css_files'], $file);
1249 }
1250
1251 // Setter for EXT_ALWAYS_ACTIVE flag
1252 function setExtensionAlwaysActive ($active) {
1253         $GLOBALS['ext_always_active'][getCurrentExtensionName()] = (string) $active;
1254 }
1255
1256 // Getter for EXT_ALWAYS_ACTIVE flag
1257 function getThisExtensionAlwaysActive () {
1258         return $GLOBALS['ext_always_active'][getCurrentExtensionName()];
1259 }
1260
1261 // Checks whether the current extension is always active
1262 function isThisExtensionAlwaysActive () {
1263         return (getThisExtensionAlwaysActive() == 'Y');
1264 }
1265
1266 // Setter for EXT_VERSION flag
1267 function setThisExtensionVersion ($ext_version) {
1268         $GLOBALS['ext_version'][getCurrentExtensionName()] = (string) $ext_version;
1269 }
1270
1271 // Getter for EXT_VERSION flag
1272 function getThisExtensionVersion () {
1273         return $GLOBALS['ext_version'][getCurrentExtensionName()];
1274 }
1275
1276 // Setter for EXT_DEPRECATED flag
1277 function setExtensionDeprecated ($deprecated) {
1278         $GLOBALS['ext_deprecated'][getCurrentExtensionName()] = (string) $deprecated;
1279 }
1280
1281 // Getter for EXT_DEPRECATED flag
1282 function isExtensionDeprecated ($ext_name = NULL) {
1283         // Default is from current (NULL) extension
1284         $isDeprecated = ($GLOBALS['ext_deprecated'][getCurrentExtensionName()] == 'Y');
1285
1286         // Is ext_name set?
1287         if (!is_null($ext_name)) {
1288                 // Then use it instead
1289                 $isDeprecated = ((isset($GLOBALS['ext_deprecated'][$ext_name])) && ($GLOBALS['ext_deprecated'][$ext_name] == 'Y'));
1290         } // END - if
1291
1292         // Return it
1293         return $isDeprecated;
1294 }
1295
1296 // Setter for EXT_UPDATE_DEPENDS flag
1297 function addExtensionDependency ($updateDepends) {
1298         // Is the update depency empty? (NEED TO BE FIXED!)
1299         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . '/' . $updateDepends . ',extensionMode=' . getExtensionMode() . ' - ENTERED!');
1300         if (empty($updateDepends)) {
1301                 // Please report this bug!
1302                 reportBug(__FUNCTION__, __LINE__, 'updateDepends is empty: currentExtension=' . getCurrentExtensionName());
1303         } // END - if
1304
1305         // Is it not yet added?
1306         if ((isset($updateDepends, $GLOBALS['ext_running_updates'][getCurrentExtensionName()])) && (in_array($updateDepends, getExtensionUpdatesRunning()))) {
1307                 /*
1308                  * Double-adding happens when the extension and an update of the same
1309                  * extension requires the same other extension again.
1310                  */
1311                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'updateDepends=' . $updateDepends . ',extensionMode=' . getExtensionMode() . ',currentExtension=' . getCurrentExtensionName() . ' - called twice.');
1312                 return;
1313         } // END - if
1314
1315         // Add it to the list of extension update depencies map
1316         array_push($GLOBALS['ext_update_depends'][getCurrentExtensionName()], $updateDepends);
1317
1318         // Init array
1319         if ((!isset($GLOBALS['ext_running_updates'][getCurrentExtensionName()])) || (!is_array($GLOBALS['ext_running_updates'][getCurrentExtensionName()]))) {
1320                 $GLOBALS['ext_running_updates'][getCurrentExtensionName()] = array();
1321         } // END - if
1322
1323         // Remember it in the list of running updates
1324         array_push($GLOBALS['ext_running_updates'][getCurrentExtensionName()], $updateDepends);
1325         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . '/' . $updateDepends . ',extensionMode=' . getExtensionMode() . ' - EXIT!');
1326 }
1327
1328 // Getter for running updates
1329 function getExtensionUpdatesRunning () {
1330         return $GLOBALS['ext_running_updates'][getCurrentExtensionName()];
1331 }
1332
1333 // Checks whether the given extension registration is in progress
1334 function isExtensionRegistrationRunning ($ext_name) {
1335         // Simply check it
1336         $isRunning = ((isset($GLOBALS['ext_register_running'])) && (in_array($ext_name, $GLOBALS['ext_register_running'])));
1337
1338         // Return it
1339         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ', isRunning=' . intval($isRunning));
1340         return $isRunning;
1341 }
1342
1343 // Init EXT_UPDATE_DEPENDS flag
1344 function initExtensionUpdateDependencies () {
1345         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . ' - ENTERED!');
1346
1347         // Init update depency map automatically if not found
1348         if (isExtensionUpdateDependenciesInitialized()) {
1349                 // We need these bug reports as well...
1350                 reportBug(__FUNCTION__, __LINE__, '() is called twice: currName=' . getCurrentExtensionName());
1351         } // END - if
1352
1353         $GLOBALS['ext_update_depends'][getCurrentExtensionName()] = array();
1354
1355         // Init running updates array
1356         initExtensionRuningUpdates();
1357
1358         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . ' - EXIT!');
1359 }
1360
1361 // Adds an extension as "registration in progress"
1362 function addExtensionRunningRegistration ($ext_name) {
1363         // Is it running?
1364         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Registration in progress: ext_name=' . $ext_name . ' - ENTERED!');
1365         if (isExtensionRegistrationRunning($ext_name)) {
1366                 // This is really bad and should not be quietly ignored
1367                 reportBug(__FUNCTION__, __LINE__, '() already called! ext_name=' . $ext_name);
1368         } // END - if
1369
1370         // Then add it!
1371         array_push($GLOBALS['ext_register_running'], $ext_name);
1372         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Registration in progress: ext_name=' . $ext_name . ' - EXIT!');
1373 }
1374
1375 // Checks whether EXT_UPDATE_DEPENDS is initialized
1376 function isExtensionUpdateDependenciesInitialized () {
1377         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName());
1378         return (isset($GLOBALS['ext_update_depends'][getCurrentExtensionName()]));
1379 }
1380
1381 // Checks whether an update is already running for given extension
1382 function isExtensionUpdateRunning ($ext_name, $ignoreDependencies = FALSE) {
1383         // 'ext_running_updates' must be there
1384         if ((!isset($GLOBALS['ext_running_updates'])) || (!is_array($GLOBALS['ext_running_updates']))) {
1385                 // Is not there
1386                 reportBug(__FUNCTION__, __LINE__, 'Required array ext_running_updates not found. ext_name=' . $ext_name . ',ignoreDependencies=' . intval($ignoreDependencies));
1387         } // END - if
1388
1389         // Current and given extensions means whole array
1390         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currentExtension=' . getCurrentExtensionName() . ',ext_name=' . $ext_name . ',ignoreDependencies=' . intval($ignoreDependencies) . ' - ENTERED!');
1391         if ($ext_name == getCurrentExtensionName()) {
1392                 // Default is not found
1393                 $isRunning = FALSE;
1394
1395                 // Walk through whole array
1396                 foreach ($GLOBALS['ext_running_updates'] as $ext1 => $depends) {
1397                         // Is it found?
1398                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext1=' . $ext1 . ',ext_name=' . $ext_name . ',depends=' . print_r($depends, TRUE));
1399                         if (($ext1 == $ext_name) || ((in_array($ext_name, $depends)) && ($ignoreDependencies === FALSE))) {
1400                                 // Found
1401                                 $isRunning = TRUE;
1402                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext1=' . $ext1 . ',ext_name=' . $ext_name . ',isRunning=true - FOUND!');
1403                                 break;
1404                         } // END - if
1405                 } // END - foreach
1406
1407                 // Return result
1408                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currentExtension=' . getCurrentExtensionName() . ',ext_name=' . $ext_name . ',ignoreDependencies=' . intval($ignoreDependencies) . ', isRunning=' . intval($isRunning) . ' - ALT-EXIT!');
1409                 return $isRunning;
1410         } // END - if
1411
1412         // Simply check it
1413         $isRunning = ((isExtensionUpdateDependenciesInitialized()) && (in_array($ext_name, getExtensionRunningUpdates())));
1414
1415         // Return it
1416         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currentExtension=' . getCurrentExtensionName() . ',ext_name=' . $ext_name . ',ignoreDependencies=' . intval($ignoreDependencies) . ', isRunning=' . intval($isRunning) . ' - EXIT!');
1417         return $isRunning;
1418 }
1419
1420 // Initializes the list of running updates
1421 function initExtensionRuningUpdates () {
1422         // Auto-init ext_running_updates
1423         if (!isset($GLOBALS['ext_running_updates'])) {
1424                 $GLOBALS['ext_running_updates'] = array();
1425                 $GLOBALS['ext_register_running'] = array();
1426         } // END - if
1427 }
1428
1429 // Getter for EXT_UPDATE_DEPENDS flag
1430 function getExtensionUpdateDependencies () {
1431         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName());
1432         return $GLOBALS['ext_update_depends'][getCurrentExtensionName()];
1433 }
1434
1435 // Getter for next iterator depency
1436 function getExtensionUpdateDependenciesIterator () {
1437         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName());
1438         return ($GLOBALS['ext_update_depends'][getCurrentExtensionName()][getExtensionUpdateIterator()]);
1439 }
1440
1441 // Counter for extension update depencies
1442 function countExtensionUpdateDependencies () {
1443         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . '=' . count($GLOBALS['ext_update_depends'][getCurrentExtensionName()]));
1444         return count($GLOBALS['ext_update_depends'][getCurrentExtensionName()]);
1445 }
1446
1447 // Removes given extension from update denpency list
1448 function removeExtensionDependency ($ext_name) {
1449         // Look it up
1450         $key = array_search($ext_name, getExtensionUpdateDependencies());
1451
1452         // Debug message
1453         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',key[' . gettype($key) . ']=' . $key);
1454
1455         // Is it valid?
1456         if ($key !== FALSE) {
1457                 // Then remove it
1458                 unset($GLOBALS['ext_update_depends'][getCurrentExtensionName()][$key]);
1459
1460                 // And sort the array
1461                 ksort($GLOBALS['ext_update_depends'][getCurrentExtensionName()]);
1462         } // END - if
1463 }
1464
1465 // Init iterator for update depencies
1466 function initExtensionUpdateIterator () {
1467         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName());
1468         $GLOBALS['ext_depend_iterator'][getCurrentExtensionName()] = '0';
1469 }
1470
1471 // Getter for depency iterator
1472 function getExtensionUpdateIterator () {
1473         // Auto-init iterator
1474         if (!isset($GLOBALS['ext_depend_iterator'][getCurrentExtensionName()])) {
1475                 // Initialize update iterator
1476                 initExtensionUpdateIterator();
1477         } // END - if
1478
1479         // Return it
1480         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . '=' . $GLOBALS['ext_depend_iterator'][getCurrentExtensionName()]);
1481         return $GLOBALS['ext_depend_iterator'][getCurrentExtensionName()];
1482 }
1483
1484 // Increments the update iterator
1485 function incrementExtensionUpdateIterator () {
1486         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName());
1487         $GLOBALS['ext_depend_iterator'][getCurrentExtensionName()]++;
1488 }
1489
1490 // Setter for EXT_REPORTS_FAILURE flag
1491 function enableExtensionReportingFailure ($reportsFailure = FALSE) {
1492         $GLOBALS['ext_reports_failure'] = (bool) $reportsFailure;
1493 }
1494
1495 // Getter for EXT_REPORTS_FAILURE flag
1496 function isExtensionReportingFailure () {
1497         return $GLOBALS['ext_reports_failure'];
1498 }
1499
1500 // Setter for EXT_VER_HISTORY flag
1501 function setExtensionVersionHistory ($versionHistory) {
1502         $GLOBALS['ext_ver_history'][getCurrentExtensionName()] = (array) $versionHistory;
1503 }
1504
1505 // Getter for EXT_VER_HISTORY array
1506 function getExtensionVersionHistory () {
1507         // Is it set?
1508         if (!isset($GLOBALS['ext_ver_history'][getCurrentExtensionName()])) {
1509                 // Then abort here to a avoid an ugly "Undefined index" error
1510                 reportBug(__FUNCTION__, __LINE__, 'Extension ext-' . getCurrentExtensionName() . ' has no history set! Is this extension empty?');
1511         } // END - if
1512
1513         // Return the history
1514         return $GLOBALS['ext_ver_history'][getCurrentExtensionName()];
1515 }
1516
1517 // Setter for EXT_UPDATE_NOTICES
1518 function setExtensionUpdateNotes ($updateNotes, $ext_ver = '') {
1519         //
1520         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'getCurrentExtensionName()=' . getCurrentExtensionName() . ',getExtensionMode()=' . getExtensionMode() . ',ext_ver=' . $ext_ver . '/' . getCurrentExtensionVersion() . ',updateNotes(length)=' . strlen($updateNotes));
1521         if (empty($ext_ver)) {
1522                 $GLOBALS['ext_update_notes'][getCurrentExtensionName()][getCurrentExtensionVersion()] = (string) $updateNotes;
1523         } else {
1524                 $GLOBALS['ext_update_notes'][getCurrentExtensionName()][$ext_ver] = (string) $updateNotes;
1525         }
1526 }
1527
1528 // Getter for EXT_UPDATE_NOTICES
1529 function getExtensionUpdateNotes ($ext_ver) {
1530         return $GLOBALS['ext_update_notes'][getCurrentExtensionName()][$ext_ver];
1531 }
1532
1533 // Checks if ext_update_notes is set
1534 function isExtensionUpdateNoteSet ($ext_ver) {
1535         return isset($GLOBALS['ext_update_notes'][getCurrentExtensionName()][$ext_ver]);
1536 }
1537
1538 // Init extension notice
1539 function initExtensionNotes ($force = FALSE) {
1540         // Is it already initialized?
1541         if (($force === FALSE) && (isset($GLOBALS['ext_notes'][getCurrentExtensionName()]))) {
1542                 // This is mostly not wanted, so please report it
1543                 reportBug(__FUNCTION__, __LINE__, 'ext_notes already set for extension ' . getCurrentExtensionName());
1544         } // END - if
1545
1546         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'getCurrentExtensionName()=' . getCurrentExtensionName());
1547         $GLOBALS['ext_notes'][getCurrentExtensionName()] = '';
1548 }
1549
1550 // Append extension notice
1551 function appendExtensionNotes ($notes) {
1552         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'getCurrentExtensionName()=' . getCurrentExtensionName() . ', notes(length)=' . strlen($notes));
1553         $GLOBALS['ext_notes'][getCurrentExtensionName()] .= (string) trim($notes);
1554 }
1555
1556 // Getter for extension notes
1557 function getExtensionNotes () {
1558         return $GLOBALS['ext_notes'][getCurrentExtensionName()];
1559 }
1560
1561 // Setter for current extension name
1562 function setCurrentExtensionName ($ext_name) {
1563         $GLOBALS['curr_extension_name'] = (string) trim($ext_name);
1564 }
1565
1566 // Getter for current extension name
1567 function getCurrentExtensionName () {
1568         if (!isset($GLOBALS['curr_extension_name'])) {
1569                 // Not set!
1570                 reportBug(__FUNCTION__, __LINE__, 'curr_extension_name not initialized. Please execute initExtensionSqls() before calling this function.');
1571         } // END - if
1572
1573         // Return it
1574         return $GLOBALS['curr_extension_name'];
1575 }
1576
1577 // Init SQLs array for current extension
1578 function initExtensionSqls ($force = FALSE) {
1579         // Auto-init the array or if forced
1580         if (($force === TRUE) || (!isset($GLOBALS['ext_sqls'][getCurrentExtensionName()]))) {
1581                 // Set the array
1582                 $GLOBALS['ext_sqls'][getCurrentExtensionName()] = array();
1583
1584                 // Initialize the generic array
1585                 initSqls();
1586         } // END - if
1587 }
1588
1589 // Adds SQLs to the SQLs array but "assigns" it with current extension name
1590 function addExtensionSql ($sql) {
1591         // Copy current name/version to local variable
1592         $currentName    = getCurrentExtensionName();
1593         $currentVersion = getCurrentExtensionVersion();
1594
1595         // Is is the array there?
1596         if ((!isset($GLOBALS['ext_sqls'][$currentName][$currentVersion])) || (!is_array($GLOBALS['ext_sqls'][$currentName][$currentVersion]))) {
1597                 // Init array
1598                 $GLOBALS['ext_sqls'][$currentName][$currentVersion] = array();
1599         } // END - if
1600
1601         // Is the SQL statement empty?
1602         if (empty($sql)) {
1603                 /*
1604                  * Abort here as this may happen if getExtensionMode() is 'activate' or
1605                  * 'deactivate'. This means that for 'mode' are no SQL statements
1606                  * specified.
1607                  */
1608                 return;
1609         } // END - if
1610
1611         // Add it
1612         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $currentName . ',ext_version=' . $currentVersion . ',sql=' . $sql);
1613         array_push($GLOBALS['ext_sqls'][$currentName][$currentVersion], $sql);
1614 }
1615
1616 // Getter for SQLs array for current extension
1617 function getExtensionSqls () {
1618         // Output debug backtrace if not found (SHOULD NOT HAPPEN!)
1619         if (!isset($GLOBALS['ext_sqls'][getCurrentExtensionName()])) {
1620                 // Not found, should not happen
1621                 reportBug(__FUNCTION__, __LINE__, sprintf("ext_sqls is empty, current extension: %s",
1622                         getCurrentExtensionName()
1623                 ));
1624         } // END - if
1625
1626         // Return the array
1627         return $GLOBALS['ext_sqls'][getCurrentExtensionName()];
1628 }
1629
1630 // Count SQLs for current extension
1631 function countExtensionSqls () {
1632         // Output debug backtrace if not found (SHOULD NOT HAPPEN!)
1633         if (!isset($GLOBALS['ext_sqls'][getCurrentExtensionName()])) {
1634                 // Not found, should not happen
1635                 reportBug(__FUNCTION__, __LINE__, sprintf("ext_sqls is empty, current extension: %s",
1636                         getCurrentExtensionName()
1637                 ));
1638         } // END - if
1639
1640         // Count them all
1641         return count($GLOBALS['ext_sqls'][getCurrentExtensionName()]);
1642 }
1643
1644 // Removes SQLs for current extension
1645 function unsetExtensionSqls () {
1646         unset($GLOBALS['ext_sqls'][getCurrentExtensionName()]);
1647 }
1648
1649 // Auto-initializes the removal list
1650 function initExtensionRemovalList () {
1651         // Is the remove list there?
1652         if (!isset($GLOBALS['ext_update_remove'])) {
1653                 // Then create it
1654                 $GLOBALS['ext_update_remove'] = array();
1655         } // END - if
1656 }
1657
1658 // Checks whether the current extension is on the removal list
1659 function isExtensionOnRemovalList () {
1660         // Init removal list
1661         initExtensionRemovalList();
1662
1663         // Is it there?
1664         return (in_array(getCurrentExtensionName(), $GLOBALS['ext_update_remove']));
1665 }
1666
1667 // Adds the current extension to the removal list
1668 function addCurrentExtensionToRemovalList () {
1669         // Simply add it
1670         array_push($GLOBALS['ext_update_remove'], getCurrentExtensionName());
1671 }
1672
1673 // Getter for removal list
1674 function getExtensionRemovalList () {
1675         // Return the removal list
1676         return $GLOBALS['ext_update_remove'];
1677 }
1678
1679 // Redirects if the provided extension is not installed
1680 function redirectOnUninstalledExtension ($ext_name) {
1681         // So is the extension there?
1682         if ((!isExtensionInstalled($ext_name)) || (!isExtensionActive($ext_name))) {
1683                 // Redirect to index
1684                 redirectToUrl('modules.php?module=index&amp;code=' . getCode('EXTENSION_PROBLEM') . '&amp;ext=' . $ext_name);
1685         } // END - if
1686 }
1687
1688 // Filter for initialization of all extensions by loading them in 'init' mode
1689 function FILTER_INIT_EXTENSIONS () {
1690         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ENTERED!');
1691         // Init notification pool
1692         initIncludePool('notify');
1693
1694         // Are there some entries?
1695         if (isset($GLOBALS['cache_array']['extension']['ext_name'])) {
1696                 // Load all found extensions if found
1697                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'CACHE - START!');
1698                 foreach ($GLOBALS['cache_array']['extension']['ext_name'] as $key => $ext_name) {
1699                         // Load it
1700                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ' - START');
1701                         loadExtension($ext_name, 'init', getExtensionVersion($ext_name));
1702                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ' - END');
1703                 } // END - foreach
1704                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'CACHE - END!');
1705         } // END - if
1706
1707         // Run any notifications
1708         runFilterChain('load_includes', 'notify');
1709
1710         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'EXIT!');
1711 }
1712
1713 // Setter for extension mode
1714 function setExtensionMode ($ext_mode) {
1715         $GLOBALS['ext_mode'] = (string) $ext_mode;
1716 }
1717
1718 // Getter for extension mode
1719 function getExtensionMode () {
1720         return $GLOBALS['ext_mode'];
1721 }
1722
1723 // Setter for dry-run
1724 function enableExtensionDryRun ($isDryRun = TRUE) {
1725         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'getCurrentExtensionName()='.getCurrentExtensionName().',isDryRun='.intval($isDryRun));
1726         $GLOBALS['ext_isDryRun'] = (bool) $isDryRun;
1727 }
1728
1729 // Getter for dry-run
1730 function isExtensionDryRun () {
1731         return $GLOBALS['ext_isDryRun'];
1732 }
1733
1734 // Setter for current extension version
1735 function setCurrentExtensionVersion ($ext_ver) {
1736         // ext_ver should never be empty in other modes than 'test'
1737         if ((empty($ext_ver)) && (getExtensionMode() != 'test')) {
1738                 // Please report all these messages
1739                 reportBug(__FUNCTION__, __LINE__, 'ext_ver is empty. Current extension name: ' . getCurrentExtensionName() . ', mode=' . getExtensionMode());
1740         } // END - if
1741
1742         // Add version
1743         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . getCurrentExtensionName() . ', ext_ver[' . gettype($ext_ver) . ']=' . $ext_ver);
1744         $GLOBALS['ext_current_version'][getCurrentExtensionName()] = (string) $ext_ver;
1745 }
1746
1747 // Getter for current extension version
1748 function getCurrentExtensionVersion () {
1749         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . getCurrentExtensionName() . ', ext_ver=' . $GLOBALS['ext_current_version'][getCurrentExtensionName()]);
1750         return $GLOBALS['ext_current_version'][getCurrentExtensionName()];
1751 }
1752
1753 // Remove the extension from cache array
1754 function removeExtensionFromArray () {
1755         // "Cache" this name
1756         $ext_name = getCurrentExtensionName();
1757
1758         // Now loop through the whole cache
1759         foreach ($GLOBALS['cache_array']['extension'] as $cacheName => $cacheArray) {
1760                 // Is it an element?
1761                 if (isset($cacheArray[$ext_name])) {
1762                         // Array element
1763                         unset($cacheArray[$ext_name]);
1764                         $GLOBALS['cache_array']['extension'][$cacheName] = $cacheArray;
1765                 } else {
1766                         // Maybe in array?
1767                         $key = array_search($ext_name, $cacheArray);
1768
1769                         // Is it there?
1770                         if ($key !== FALSE) {
1771                                 // Found, so remove it
1772                                 unset($cacheArray[$key]);
1773                                 $GLOBALS['cache_array']['extension'][$cacheName] = $cacheArray;
1774                         } // END - if
1775                 }
1776         } // END - foreach
1777
1778         // Remove from other caches as well
1779         unset($GLOBALS['ext_is_installed'][$ext_name]);
1780         unset($GLOBALS['loaded_extension'][$ext_name]);
1781 }
1782
1783 // "Getter" for 'extension has a CSS file' (with same name, of course)
1784 function getExtensionHasCss () {
1785         // Is there cache?
1786         if (!isset($GLOBALS[__FUNCTION__][getCurrentExtensionName()][getCurrentTheme()])) {
1787                 // Construct FQFN for check
1788                 $FQFN = sprintf('%s%s.css',
1789                         getBasePathFromTheme(getCurrentTheme()),
1790                         getCurrentExtensionName()
1791                 );
1792
1793                 // Is it there?
1794                 $GLOBALS[__FUNCTION__][getCurrentExtensionName()][getCurrentTheme()] = convertBooleanToYesNo(isFileReadable($FQFN));
1795         } // END - if
1796
1797         // Return it
1798         return $GLOBALS[__FUNCTION__][getCurrentExtensionName()][getCurrentTheme()];
1799 }
1800
1801 // Checks whether the given extension's language file is readable
1802 function isExtensionLanguageFileReadable ($ext_name) {
1803         // Is there cache?
1804         if (isset($GLOBALS['cache_array']['extension']['ext_lang'][$ext_name])) {
1805                 // Count cache hits
1806                 incrementStatsEntry('cache_hits');
1807         } else {
1808                 // Determine it and put it in cache
1809                 $GLOBALS['cache_array']['extension']['ext_lang'][$ext_name] = convertBooleanToYesNo(isLanguageIncludeReadable($ext_name));
1810         }
1811
1812         // Return result
1813         return ($GLOBALS['cache_array']['extension']['ext_lang'][$ext_name] == 'Y');
1814 }
1815
1816 // Load current extension's include file
1817 function loadCurrentExtensionInclude () {
1818         // Is it readable?
1819         if (!isExtensionIncludeReadable()) {
1820                 // Not readable
1821                 reportBug(__FUNCTION__, __LINE__, 'Extension ' . getCurrentExtensionName() . ' should be loaded, but is not readable.');
1822         } // END - if
1823
1824         // Generate INC name
1825         $INC = sprintf("inc/extensions/ext-%s.php", getCurrentExtensionName());
1826
1827         // Load it
1828         loadInclude($INC);
1829 }
1830
1831 // Load current extension's mode include file
1832 function loadCurrentExtensionModeInclude () {
1833         // Generate INC name
1834         $INC = sprintf("inc/extensions/%s/mode-%s.php", getCurrentExtensionName(), getExtensionMode());
1835
1836         // Is the include readable?
1837         if (isIncludeReadable($INC)) {
1838                 // Load it as it is optional
1839                 loadInclude($INC);
1840         } // END - if
1841 }
1842
1843 // Checks whether an extension is readable
1844 function isExtensionIncludeReadable ($ext_name = '') {
1845         // If empty, use current
1846         if (empty($ext_name)) {
1847                 $ext_name = getCurrentExtensionName();
1848         } // END - if
1849
1850         // Array found?
1851         if (!isset($GLOBALS['ext_inc_readable'][$ext_name])) {
1852                 // Generate INC name
1853                 $INC = sprintf("inc/extensions/ext-%s.php", getCurrentExtensionName());
1854
1855                 // Is it readable?
1856                 $GLOBALS['ext_inc_readable'][$ext_name] = isIncludeReadable($INC);
1857         } // END - if
1858
1859         // Return result
1860         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',realable='.intval($GLOBALS['ext_inc_readable'][$ext_name]));
1861         return $GLOBALS['ext_inc_readable'][$ext_name];
1862 }
1863
1864 // Checks if an extension's function file is readable
1865 function isExtensionFunctionFileReadable ($ext_name) {
1866         // Is cache there?
1867         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name);
1868         if (isset($GLOBALS['cache_array']['extension']['ext_func'][$ext_name])) {
1869                 // Just count cache hits
1870                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',ext_func=' . $GLOBALS['cache_array']['extension']['ext_func'][$ext_name] .' - CACHE!');
1871                 incrementStatsEntry('cache_hits');
1872         } else {
1873                 // Construct IFN for functions file
1874                 $funcsInclude = sprintf("inc/libs/%s_functions.php", $ext_name);
1875
1876                 // Is this include there?
1877                 $isIncludeFound = ((isFileReadable($funcsInclude)) && (!isExtensionLibraryLoaded($ext_name)) && (getExtensionMode() == 'test'));
1878
1879                 // And put in cache, converted
1880                 $GLOBALS['cache_array']['extension']['ext_func'][$ext_name] = convertBooleanToYesNo($isIncludeFound);
1881         }
1882
1883         // Return result
1884         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',ext_func=' . $GLOBALS['cache_array']['extension']['ext_func'][$ext_name]);
1885         return ($GLOBALS['cache_array']['extension']['ext_func'][$ext_name] == 'Y');
1886 }
1887
1888 // Adds a CREATE TABLE statement if the requested table is not there
1889 function addCreateTableSql ($tableName, $sql, $comment) {
1890         // Is the table not there?
1891         if (!ifSqlTableExists($tableName)) {
1892                 // Is not found, so add it
1893                 addExtensionSql('CREATE TABLE
1894         `{?_MYSQL_PREFIX?}_' . $tableName . '` (' . $sql . ')
1895 ENGINE = {?_TABLE_TYPE?}
1896 CHARACTER SET utf8
1897 COLLATE utf8_general_ci
1898 COMMENT ' . chr(39) . $comment . chr(39));
1899         } else {
1900                 // Is already there
1901                 logDebugMessage(__FUNCTION__, __LINE__, 'The table ' . $tableName . ' is already created.');
1902         }
1903 }
1904
1905 // Adds a DROP TABLE statement if the requested tabled is there
1906 function addDropTableSql ($tableName) {
1907         // Is the table there?
1908         if (ifSqlTableExists($tableName)) {
1909                 /*
1910                  * Then add it, non-existing tables can be ignored because it will
1911                  * happen with every newly installed extension.
1912                  */
1913                 addExtensionSql('DROP TABLE `{?_MYSQL_PREFIX?}_' . $tableName . '`');
1914
1915                 // Mark it as gone
1916                 $GLOBALS['ifSqlTableExists'][$tableName] = FALSE;
1917         } // END - if
1918 }
1919
1920 // Adds a RENAME TABLE stament if 'from' table exist and 'to' table not
1921 function addRenameTableSql ($fromTable, $toTable) {
1922         // Make sure both are not the same
1923         assert($fromTable != $toTable);
1924
1925         // Is renaming required?
1926         if ((ifSqlTableExists($fromTable)) && (!ifSqlTableExists($toTable))) {
1927                 // Add it
1928                 addExtensionSql('RENAME TABLE `{?_MYSQL_PREFIX?}_' . $fromTable . '` TO `{?_MYSQL_PREFIX?}_' . $toTable . '`');
1929
1930                 // Mark both tables
1931                 $GLOBALS['ifSqlTableExists'][$fromTable] = FALSE;
1932                 $GLOBALS['ifSqlTableExists'][$toTable]   = TRUE;
1933         } // END - if
1934 }
1935
1936 // Adds an admin menu to the SQL queue of the menu entry is not found
1937 function addAdminMenuSql ($action, $what, $title, $descr, $sort) {
1938         // Now check if this menu is there
1939         if (!isMenuActionValid('admin', $action, $what)) {
1940                 // Is what null?
1941                 if (is_null($what)) {
1942                         // Add main menu
1943                         $sql = sprintf("INSERT INTO `{?_MYSQL_PREFIX?}_admin_menu` (`action`, `what`, `title`, `descr`, `sort`) VALUES ('%s',NULL,'%s','%s',%s)",
1944                                 $action,
1945                                 $title,
1946                                 $descr,
1947                                 bigintval($sort)
1948                         );
1949                 } else {
1950                         // Add sub menu
1951                         $sql = sprintf("INSERT INTO `{?_MYSQL_PREFIX?}_admin_menu` (`action`, `what`, `title`, `descr`, `sort`) VALUES ('%s','%s','%s','%s',%s)",
1952                                 $action,
1953                                 $what,
1954                                 $title,
1955                                 $descr,
1956                                 bigintval($sort)
1957                         );
1958                 }
1959
1960                 // Add it to the queue
1961                 addExtensionSql($sql);
1962         } elseif (isDebugModeEnabled()) {
1963                 // Double menus should be located and fixed!
1964                 logDebugMessage(__FUNCTION__, __LINE__, sprintf("Double admin menu action=%s,what=%s,title=%s detected.", $action, $what, $title));
1965         }
1966 }
1967
1968 // Adds a guest menu to the SQL queue if the menu entry is not found
1969 function addGuestMenuSql ($action, $what, $title, $sort) {
1970         // Now check if this menu is there
1971         if (!isMenuActionValid('guest', $action, $what)) {
1972                 // Is what null?
1973                 if (is_null($what)) {
1974                         // Add main menu
1975                         $sql = sprintf("INSERT INTO `{?_MYSQL_PREFIX?}_guest_menu` (`action`, `what`, `title`, `visible`, `locked`, `sort`) VALUES ('%s',NULL,'%s','N','Y',%s)",
1976                                 $action,
1977                                 $title,
1978                                 bigintval($sort)
1979                         );
1980                 } else {
1981                         // Add sub menu
1982                         $sql = sprintf("INSERT INTO `{?_MYSQL_PREFIX?}_guest_menu` (`action`, `what`, `title`, `visible`, `locked`, `sort`) VALUES ('%s','%s','%s','N','Y',%s)",
1983                                 $action,
1984                                 $what,
1985                                 $title,
1986                                 bigintval($sort)
1987                         );
1988                 }
1989
1990                 // Add it to the queue
1991                 addExtensionSql($sql);
1992         } elseif (isDebugModeEnabled()) {
1993                 // Double menus should be located and fixed!
1994                 logDebugMessage(__FUNCTION__, __LINE__, sprintf("Double guest menu action=%s,what=%s,title=%s detected.", $action, $what, $title));
1995         }
1996 }
1997
1998 // Adds a member menu to the SQL queue if the menu entry is not found
1999 function addMemberMenuSql ($action, $what, $title, $sort) {
2000         // Now check if this menu is there
2001         if (!isMenuActionValid('member', $action, $what)) {
2002                 // Is what null?
2003                 if (is_null($what)) {
2004                         // Add main menu
2005                         $sql = sprintf("INSERT INTO `{?_MYSQL_PREFIX?}_member_menu` (`action`, `what`, `title`, `visible`, `locked`, `sort`) VALUES ('%s',NULL,'%s','N','Y',%s)",
2006                                 $action,
2007                                 $title,
2008                                 bigintval($sort)
2009                         );
2010                 } else {
2011                         // Add sub menu
2012                         $sql = sprintf("INSERT INTO `{?_MYSQL_PREFIX?}_member_menu` (`action`, `what`, `title`, `visible`, `locked`, `sort`) VALUES ('%s','%s','%s','N','Y',%s)",
2013                                 $action,
2014                                 $what,
2015                                 $title,
2016                                 bigintval($sort)
2017                         );
2018                 }
2019
2020                 // Add it to the queue
2021                 addExtensionSql($sql);
2022         } elseif (isDebugModeEnabled()) {
2023                 // Double menus should be located and fixed!
2024                 logDebugMessage(__FUNCTION__, __LINE__, sprintf("Double member menu action=%s,what=%s,title=%s detected.", $action, $what, $title));
2025         }
2026 }
2027
2028 // Adds a sponsor menu to the SQL queue if the menu entry is not found
2029 function addSponsorMenuSql ($action, $what, $title, $active, $sort) {
2030         // Now check if this menu is there, if no ext-sponsor is installed all is not yet added
2031         if ((!isExtensionInstalled('sponsor')) || (!isMenuActionValid('sponsor', $action, $what))) {
2032                 // Is what null?
2033                 if (is_null($what)) {
2034                         // Add main menu
2035                         $sql = sprintf("INSERT INTO `{?_MYSQL_PREFIX?}_sponsor_menu` (`action`, `what`, `title`, `active`, `sort`) VALUES ('%s',NULL,'%s','%s',%s)",
2036                                 $action,
2037                                 $title,
2038                                 $active,
2039                                 bigintval($sort)
2040                         );
2041                 } else {
2042                         // Add sub menu
2043                         $sql = sprintf("INSERT INTO `{?_MYSQL_PREFIX?}_sponsor_menu` (`action`, `what`, `title`, `active`, `sort`) VALUES ('%s','%s','%s','%s',%s)",
2044                                 $action,
2045                                 $what,
2046                                 $title,
2047                                 $active,
2048                                 bigintval($sort)
2049                         );
2050                 }
2051
2052                 // Add it to the queue
2053                 addExtensionSql($sql);
2054         } elseif (isDebugModeEnabled()) {
2055                 // Double menus should be located and fixed!
2056                 logDebugMessage(__FUNCTION__, __LINE__, sprintf("Double sponsor menu action=%s,what=%s,title=%s,active=%s detected.", $action, $what, $title, $active));
2057         }
2058 }
2059
2060 // Add ALTER TABLE `foo` ADD sql if not found
2061 function addExtensionAddTableColumnSql ($tableName, $columnName, $columnSql) {
2062         // Assert on all
2063         assert((!empty($tableName)) && (!empty($columnName)) && (!empty($columnSql)));
2064         assert($columnName != $columnSql);
2065
2066         // Is the column there?
2067         if (!ifSqlTableColumnExists('{?_MYSQL_PREFIX?}_' . $tableName, $columnName, isInstaller())) {
2068                 // Debug message
2069                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'tableName=' . $tableName . ',columnName=' . $columnName . ',columnSql=' . $columnSql);
2070
2071                 // Then add it
2072                 addExtensionSql('ALTER TABLE `{?_MYSQL_PREFIX?}_' . $tableName . '` ADD `' . $columnName . '` ' . $columnSql);
2073         } elseif (isDebugModeEnabled()) {
2074                 // Add debug line
2075                 logDebugMessage(__FUNCTION__, __LINE__, 'tableName=' . $tableName . ',columnName=' . $columnName . ',columnSql=' . $columnSql . ': does already exist.');
2076         }
2077 }
2078
2079 // Add ALTER TABLE `foo` ADD INDEX sql if not found
2080 function addExtensionAddTableIndexSql ($tableName, $indexName, $columnSql) {
2081         // Assert on all
2082         assert((!empty($tableName)) && (!empty($indexName)) && (!empty($columnSql)));
2083         assert($indexName != $columnSql);
2084
2085         // Is the column there?
2086         if (!ifSqlTableIndexExist('{?_MYSQL_PREFIX?}_' . $tableName, $indexName, isInstaller())) {
2087                 // Debug message
2088                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'tableName=' . $tableName . ',indexName=' . $indexName . ',columnSql=' . $columnSql);
2089
2090                 // Then add it
2091                 addExtensionSql('ALTER TABLE `{?_MYSQL_PREFIX?}_' . $tableName . '` ADD INDEX `' . $indexName . '` ' . $columnSql);
2092         } elseif (isDebugModeEnabled()) {
2093                 // Add debug line
2094                 logDebugMessage(__FUNCTION__, __LINE__, 'tableName=' . $tableName . ',indexName=' . $indexName . ',columnSql=' . $columnSql . ': does already exist.');
2095         }
2096 }
2097
2098 // Add ALTER TABLE `foo` ADD UNIQUE INDEX sql if not found
2099 function addExtensionAddTableUniqueSql ($tableName, $indexName, $columnSql) {
2100         // Assert on all
2101         assert((!empty($tableName)) && (!empty($indexName)) && (!empty($columnSql)));
2102         assert($indexName != $columnSql);
2103
2104         // Is the column there?
2105         if (!ifSqlTableIndexExist('{?_MYSQL_PREFIX?}_' . $tableName, $indexName, isInstaller())) {
2106                 // Debug message
2107                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'tableName=' . $tableName . ',indexName=' . $indexName . ',columnSql=' . $columnSql);
2108
2109                 // Then add it
2110                 addExtensionSql('ALTER TABLE `{?_MYSQL_PREFIX?}_' . $tableName . '` ADD UNIQUE INDEX `' . $indexName . '` ' . $columnSql);
2111         } elseif (isDebugModeEnabled()) {
2112                 // Add debug line
2113                 logDebugMessage(__FUNCTION__, __LINE__, 'tableName=' . $tableName . ',indexName=' . $indexName . ',columnSql=' . $columnSql . ': does already exist.');
2114         }
2115 }
2116
2117 // Add ALTER TABLE `foo` ADD FULLTEXT sql if not found
2118 function addExtensionAddTableFulltextSql ($tableName, $indexName, $columnSql) {
2119         // Assert on all
2120         assert((!empty($tableName)) && (!empty($indexName)) && (!empty($columnSql)));
2121         assert($indexName != $columnSql);
2122
2123         // Is the column there and MyISAM engine? (InnoDB doesn't support FULLTEXT)
2124         if ((getTableType() == 'MyISAM') && (!ifSqlTableIndexExist('{?_MYSQL_PREFIX?}_' . $tableName, $indexName, isInstaller()))) {
2125                 // Debug message
2126                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'tableName=' . $tableName . ',indexName=' . $indexName . ',columnSql=' . $columnSql);
2127
2128                 // Then add it
2129                 addExtensionSql('ALTER TABLE `{?_MYSQL_PREFIX?}_' . $tableName . '` ADD FULLTEXT `' . $indexName . '` ' . $columnSql);
2130         } elseif (isDebugModeEnabled()) {
2131                 // Add debug line
2132                 logDebugMessage(__FUNCTION__, __LINE__, 'tableName=' . $tableName . ',indexName=' . $indexName . ',columnSql=' . $columnSql . ': does already exist.');
2133         }
2134 }
2135
2136 // Add ALTER TABLE `foo` CHANGE sql if not found
2137 function addExtensionChangeTableColumnSql ($tableName, $fromColumnName, $toColumnName, $columnSql) {
2138         // Assert on all
2139         assert((!empty($tableName)) && (!empty($fromColumnName)) && (!empty($toColumnName)) && (!empty($columnSql)));
2140         assert(($fromColumnName != $columnSql) && ($toColumnName != $columnSql));
2141
2142         // Is the column there?
2143         if ((ifSqlTableColumnExists('{?_MYSQL_PREFIX?}_' . $tableName, $fromColumnName)) && (($fromColumnName == $toColumnName) || (!ifSqlTableColumnExists('{?_MYSQL_PREFIX?}_' . $tableName, $toColumnName, isInstaller())))) {
2144                 // Debug message
2145                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'tableName=' . $tableName . ',fromColumnName=' . $fromColumnName . ',toColumnName=' . $toColumnName . ',columnSql=' . $columnSql);
2146
2147                 // Then add it
2148                 addExtensionSql('ALTER TABLE `{?_MYSQL_PREFIX?}_' . $tableName . '` CHANGE `' . $fromColumnName . '` `' . $toColumnName . '` ' . $columnSql);
2149         } elseif (isDebugModeEnabled()) {
2150                 // Add debug line
2151                 logDebugMessage(__FUNCTION__, __LINE__, 'tableName=' . $tableName . ',fromColumnName=' . $fromColumnName . ',toColumnName=' . $toColumnName . ',columnSql=' . $columnSql . ': Cannot be changed.');
2152         }
2153 }
2154
2155 // Add ALTER TABLE `foo` DROP sql if not found
2156 function addExtensionDropTableColumnSql ($tableName, $columnName) {
2157         // Assert on all
2158         assert((!empty($tableName)) && (!empty($columnName)));
2159
2160         // Is the column there?
2161         if (ifSqlTableColumnExists('{?_MYSQL_PREFIX?}_' . $tableName, $columnName, isInstaller())) {
2162                 // Debug message
2163                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'tableName=' . $tableName . ',columnName=' . $columnName);
2164
2165                 // Then add it
2166                 addExtensionSql('ALTER TABLE `{?_MYSQL_PREFIX?}_' . $tableName . '` DROP `' . $columnName . '`');
2167         } elseif (isDebugModeEnabled()) {
2168                 // Add debug line
2169                 logDebugMessage(__FUNCTION__, __LINE__, 'tableName=' . $tableName . ',columnName=' . $columnName . ': does not exist.');
2170         }
2171 }
2172
2173 // Add ALTER TABLE `foo` DROP INDEX sql if not found
2174 function addExtensionDropTableIndexSql ($tableName, $indexName) {
2175         // Assert on all
2176         assert((!empty($tableName)) && (!empty($indexName)));
2177
2178         // Is the column there?
2179         if (ifSqlTableColumnExists('{?_MYSQL_PREFIX?}_' . $tableName, $indexName, isInstaller())) {
2180                 // Debug message
2181                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'tableName=' . $tableName . ',indexName=' . $indexName);
2182
2183                 // Then add it
2184                 addExtensionSql('ALTER TABLE `{?_MYSQL_PREFIX?}_' . $tableName . '` DROP INDEX `' . $indexName . '`');
2185         } elseif (isDebugModeEnabled()) {
2186                 // Add debug line
2187                 logDebugMessage(__FUNCTION__, __LINE__, 'tableName=' . $tableName . ',indexName=' . $indexName . ': does not exist.');
2188         }
2189 }
2190
2191 // Add configuration entry if not found for actual extension
2192 function addConfigAddSql ($columnName, $columnSql) {
2193         // Call inner function
2194         addExtensionAddTableColumnSql('config', $columnName, $columnSql);
2195 }
2196
2197 // Drop configuration entry if found for actual extension
2198 function addConfigDropSql ($columnName) {
2199         // Call inner function
2200         addExtensionDropTableColumnSql('config', $columnName);
2201 }
2202
2203 // Change configuration entry for actual extension
2204 function addConfigChangeSql ($oldColumnName, $newColumnName, $columnSql) {
2205         // Add the SQL statement
2206         addExtensionChangeTableColumnSql('config', $oldColumnName, $newColumnName, $columnSql);
2207 }
2208
2209 /**
2210  * Checks if given subject is found and if not, adds an SQL query to the
2211  * extension registration queue.
2212  */
2213 function registerExtensionPointsData ($subject, $columnName, $lockedMode, $paymentMethod) {
2214         // Assert on all
2215         assert((!empty($subject)) && (!empty($columnName)) && (!empty($lockedMode)) && (!empty($paymentMethod)));
2216         assert((in_array($lockedMode, array('LOCKED', 'UNLOCKED'))) && (in_array($paymentMethod, array('DIRECT', 'REFERRAL'))));
2217
2218         // Is the suffix '_ref' not set?
2219         if (!ifSubjectHasReferralSuffix($subject)) {
2220                 // Register this first
2221                 registerExtensionPointsData($subject . '_ref', $columnName, $lockedMode, $paymentMethod);
2222         } // END - if
2223
2224         // Default is old extension version
2225         $add = '';
2226
2227         // Is the extension equal or newer 0.8.9?
2228         if (((isInstaller()) && ((getExtensionMode() == 'setup') || (getExtensionMode() == 'update'))) || (isExtensionInstalledAndNewer('sql_patches', '0.8.9'))) {
2229                 // Then add provider
2230                 $add = " AND `account_provider`='EXTENSION'";
2231         } // END - if
2232
2233         // Is the 'subject' there?
2234         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ifSqlTableExists(points_data)=' . ifSqlTableExists('points_data') . ',getExtensionMode()=' . getExtensionMode() . ',add=' . $add);
2235         if (((!ifSqlTableExists('points_data')) && ((getExtensionMode() == 'setup') || (getExtensionMode() == 'update'))) || (countSumTotalData($subject, 'points_data', 'id', 'subject', TRUE, $add) == 0)) {
2236                 // Not found so:
2237                 if ((!isInstaller()) && (isset($GLOBALS['previous_extension'][getCurrentExtensionName()])) && (!ifSqlTableExists('points_data'))) {
2238                         // This may happen (but when?)
2239                         // @TODO Is this really neccessary?
2240                         $dummy = $GLOBALS['previous_extension'][getCurrentExtensionName()];
2241                         reportBug(__FUNCTION__, __LINE__, 'dummy[' . gettype($dummy) . ']=' . $dummy . ',getCurrentExtensionName()=' . getCurrentExtensionName() . ' - Under development, please report this!');
2242                 } // END - if
2243
2244                 // With or without account_provider?
2245                 if (((isInstaller()) && ((getExtensionMode() == 'setup') || (getExtensionMode() == 'update'))) || (isExtensionInstalledAndNewer('sql_patches', '0.8.9'))) {
2246                         // Add account_provider
2247                         addExtensionSql(sprintf("INSERT INTO `{?_MYSQL_PREFIX?}_points_data` (`subject`, `column_name`, `locked_mode`, `payment_method`, `account_provider`) VALUES ('%s','%s','%s','%s','EXTENSION')",
2248                                 $subject,
2249                                 $columnName,
2250                                 $lockedMode,
2251                                 $paymentMethod
2252                         ));
2253                 } else {
2254                         // ... add an SQL query
2255                         addExtensionSql(sprintf("INSERT INTO `{?_MYSQL_PREFIX?}_points_data` (`subject`, `column_name`, `locked_mode`, `payment_method`) VALUES ('%s','%s','%s','%s')",
2256                                 $subject,
2257                                 $columnName,
2258                                 $lockedMode,
2259                                 $paymentMethod
2260                         ));
2261                 }
2262         } // END - if
2263 }
2264
2265 /**
2266  * Checks if given subject is found and if so, adds an SQL query to the
2267  * extension unregistration queue.
2268  */
2269 function unregisterExtensionPointsData ($subject) {
2270         // Is the suffix '_ref' not set?
2271         if (!ifSubjectHasReferralSuffix($subject)) {
2272                 // Unregister this first
2273                 unregisterExtensionPointsData($subject . '_ref');
2274         } // END - if
2275
2276         // Default is old extension version
2277         $add = '';
2278
2279         // Is the extension equal or newer 0.8.9?
2280         if (isExtensionInstalledAndNewer('sql_patches', '0.8.9')) {
2281                 // Then add provider
2282                 $add = " AND `account_provider`='EXTENSION'";
2283         } // END - if
2284
2285         // Is the 'subject' there?
2286         if (countSumTotalData($subject, 'points_data', 'id', 'subject', TRUE, $add) == 1) {
2287                 // Found one or more, so add an SQL query
2288                 addExtensionSql(sprintf("DELETE LOW_PRIORITY FROM `{?_MYSQL_PREFIX?}_points_data` WHERE `subject`='%s'" . $add . " LIMIT 1",
2289                         $subject
2290                 ));
2291         } // END - if
2292 }
2293
2294 // Enables/disables productive mode for current extension (used only while
2295 // registration).
2296 // @TODO This should be rewrittten to allow, more development states, e.g. 'planing','alpha','beta','beta2','stable'
2297 function enableExtensionProductive ($isProductive = TRUE) {
2298         // Log debug message
2299         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . getCurrentExtensionName() . ',isProductive=', intval($isProductive));
2300
2301         // Set it
2302         $GLOBALS['ext_productive'][getCurrentExtensionName()] = (bool) $isProductive;
2303 }
2304
2305 // Checks whether the extension is in productive phase. If not set, development
2306 // phase (=false) is assumed.
2307 function isExtensionProductive ($ext_name = '') {
2308         // Is the extension name empty? Then use current
2309         if (empty($ext_name)) {
2310                 // Get current extension name
2311                 $ext_name = getCurrentExtensionName();
2312         } // END - if
2313         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ' - ENTERED!');
2314
2315         // Is there cache?
2316         if (!isset($GLOBALS[__FUNCTION__][$ext_name])) {
2317                 // Load extension only if not yet loaded
2318                 if (!isset($GLOBALS['ext_productive'][$ext_name])) {
2319                         // Load extension in test mode
2320                         loadExtension($ext_name, 'test');
2321                 } // END - if
2322
2323                 // Determine it
2324                 $GLOBALS[__FUNCTION__][$ext_name] = ((isset($GLOBALS['ext_productive'][$ext_name])) && ($GLOBALS['ext_productive'][$ext_name] === TRUE));
2325         } // END - if
2326
2327         // Return result
2328         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',isProductive=', intval($GLOBALS[__FUNCTION__][$ext_name]) . ' - EXIT!');
2329         return $GLOBALS[__FUNCTION__][$ext_name];
2330 }
2331
2332 // Mark extension file as loaded
2333 function markExtensionAsLoaded ($ext_name) {
2334         // Is it already loaded?
2335         if (isExtensionLoaded($ext_name)) {
2336                 // Then abort here
2337                 reportBug(__FUNCTION__, __LINE__, 'Extension ' . $ext_name . ' is already marked as loaded!');
2338         } // END - if
2339
2340         // Mark it
2341         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',ext_loaded=true');
2342         $GLOBALS['ext_loaded']['ext_name'][$ext_name] = TRUE;
2343 }
2344
2345 // Determine whether the given extension is already loaded
2346 function isExtensionLoaded ($ext_name) {
2347         // Is it there?
2348         return ((isset($GLOBALS['ext_loaded']['ext_name'][$ext_name])) && ($GLOBALS['ext_loaded']['ext_name'][$ext_name] === TRUE));
2349 }
2350
2351 // Mark extension's library file as loaded
2352 function markExtensionLibraryAsLoaded ($ext_name) {
2353         // Is it already loaded?
2354         if (isExtensionLibraryLoaded($ext_name)) {
2355                 // Then abort here
2356                 reportBug(__FUNCTION__, __LINE__, 'Extension library ' . $ext_name . ' is already marked as loaded!');
2357         } // END - if
2358
2359         // Mark it
2360         $GLOBALS['ext_loaded']['library'][$ext_name] = TRUE;
2361 }
2362
2363 // Determine whether the given extension's library is already loaded
2364 function isExtensionLibraryLoaded ($ext_name) {
2365         // Is it there?
2366         return ((isset($GLOBALS['ext_loaded']['library'][$ext_name])) && ($GLOBALS['ext_loaded']['library'][$ext_name] === TRUE));
2367 }
2368
2369 // Copies the given extension's data to cache_array (USE THIS ONLY IN REGISTRATION PHASE!)
2370 function copyExtensionDataToCacheArray ($ext_name, $ext_id) {
2371         // Copy all data
2372         $GLOBALS['cache_array']['extension']['ext_id'][$ext_name]         = $ext_id;
2373         $GLOBALS['cache_array']['extension']['ext_name'][$ext_id]         = $ext_name;
2374         $GLOBALS['cache_array']['extension']['ext_version'][$ext_name]    = getCurrentExtensionVersion();
2375         $GLOBALS['cache_array']['extension']['ext_active'][$ext_name]     = getThisExtensionAlwaysActive();
2376         $GLOBALS['cache_array']['extension']['ext_lang'][$ext_name]       = convertBooleanToYesNo(isExtensionLanguageFileReadable($ext_name));
2377         $GLOBALS['cache_array']['extension']['ext_func'][$ext_name]       = convertBooleanToYesNo(isExtensionFunctionFileReadable($ext_name));
2378         $GLOBALS['cache_array']['extension']['ext_menu'][$ext_name]       = convertBooleanToYesNo(ifModuleHasMenu($ext_name, isInstaller()));
2379         $GLOBALS['cache_array']['extension']['ext_css'][$ext_name]        = convertBooleanToYesNo(getExtensionHasCss());
2380         $GLOBALS['cache_array']['extension']['ext_deprecated'][$ext_name] = 'N';
2381 }
2382
2383 // "Getter" for "checked="checked" from given session data
2384 function getExtensionSelectedFromSession ($ext_name, $sessionName, $separator = ':') {
2385         // Get the data and explode it
2386         $selections = explode($separator, getSession($sessionName));
2387
2388         // Default is not checked
2389         $checked = '';
2390
2391         // Is it there?
2392         if (in_array($ext_name, $selections)) {
2393                 // It is, so mark it
2394                 $checked = ' checked="checked"';
2395         } // END - if
2396
2397         // Return result
2398         return $checked;
2399 }
2400
2401 // [EOF]
2402 ?>