Some more encapulation of global array elements for extensions
[mailer.git] / inc / extensions-functions.php
index 9abe929fef108e1fa1aa0f1dfcda87d1347488a0..d918bc5fd96efb9590aaed0e0a800ccab98075be 100644 (file)
  * $Date::                                                            $ *
  * $Tag:: 0.2.1-FINAL                                                 $ *
  * $Author::                                                          $ *
- * Needs to be in all Files and every File needs "svn propset           *
- * svn:keywords Date Revision" (autoprobset!) at least!!!!!!            *
  * -------------------------------------------------------------------- *
  * Copyright (c) 2003 - 2009 by Roland Haeder                           *
- * Copyright (c) 2009, 2010 by Mailer Developer Team                    *
+ * Copyright (c) 2009 - 2011 by Mailer Developer Team                   *
  * For more information visit: http://www.mxchange.org                  *
  *                                                                      *
  * This program is free software; you can redistribute it and/or modify *
@@ -43,9 +41,11 @@ if (!defined('__SECURITY')) {
 } // END - if
 
 // Load the extension and maybe found language and function files.
-function loadExtension ($ext_name, $ext_mode, $ext_ver = '', $dry_run = false) {
-       // If this happens twice, we need the bug report from you, except for updates/tests
+function loadExtension ($ext_name, $ext_mode, $ext_ver = '0.0', $dry_run = false) {
+       // Loading an extension in same mode, but not test/update, twice is not
+       // good, so is the extension $ext_name already loaded in mode $ext_mode?
        if ((isset($GLOBALS['loaded_extension'][$ext_name][$ext_mode])) && (!in_array($ext_mode, array('update', 'test')))) {
+               // If this happens twice, we need the bug report from you, except for updates/tests
                debug_report_bug(__FUNCTION__, __LINE__, '() is called twice: ext_name=' . $ext_name . ', ext_mode='. $ext_mode . ',ext_sqls=' . print_r(getExtensionSqls(), true) . ', ext_register_running=' . print_r($GLOBALS['ext_register_running'], true) . ', ext_running_updates=' . print_r($GLOBALS['ext_running_updates'], true));
        } // END - if
 
@@ -65,13 +65,19 @@ function loadExtension ($ext_name, $ext_mode, $ext_ver = '', $dry_run = false) {
                // Set current extension version
                setCurrentExtensionVersion($ext_ver);
        } else {
-               // Set it to 0.0
+               // Set it to 0.0 by default
                setCurrentExtensionVersion('0.0');
 
+               // Is the extension installed?
+               if ((isExtensionInstalled($ext_name)) && ($ext_mode != 'register')) {
+                       // Get extension's version
+                       setCurrentExtensionVersion(getExtensionVersion($ext_name));
+               } // END - if
+
                // In all but test-mode we need these messages to debug! Please report all (together, e.g.)
-               if ($ext_mode != 'test') {
-                       // Log empty versions not in test-mode, but maybe it is fine...
-                       logDebugMessage(__FUNCTION__, __LINE__, 'Extension version is empty, setting to 0.0. ext_name=' . $ext_name . ', ext_mode=' . $ext_mode . ', dry_run=' . intval($dry_run));
+               if (($ext_mode != 'test') && (getCurrentExtensionVersion() == '0.0')) {
+                       // Abort here, this must now always be set!
+                       debug_report_bug(__FUNCTION__, __LINE__, 'Extension version is empty, setting to 0.0. ext_name=' . $ext_name . ', ext_mode=' . $ext_mode . ', dry_run=' . intval($dry_run));
                } // END - if
        }
 
@@ -92,7 +98,7 @@ function loadExtension ($ext_name, $ext_mode, $ext_ver = '', $dry_run = false) {
 
        // Is the extension already loaded?
        //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Loading extension ' . $ext_name . ', mode=' . getExtensionMode() . ', ver=' . getCurrentExtensionVersion());
-       if ((isset($GLOBALS['ext_loaded']['ext'][$ext_name])) && (getExtensionMode() == 'init')) {
+       if ((isExtensionLoaded($ext_name)) && (getExtensionMode() == 'init')) {
                // Debug message
                logDebugMessage(__FUNCTION__, __LINE__, sprintf("Extension %s already loaded.", $ext_name));
 
@@ -118,12 +124,12 @@ function loadExtension ($ext_name, $ext_mode, $ext_ver = '', $dry_run = false) {
        // Do we have cache?
        if (isExtensionFunctionFileReadable($ext_name)) {
                // Not yet loaded?
-               if ((($GLOBALS['cache_array']['extension']['ext_func'][$ext_name] == 'Y') || (!isset($GLOBALS['cache_array']['extension']['ext_func'][$ext_name]))) && (!isset($GLOBALS['ext_loaded']['funcs'][$ext_name]))) {
+               if ((($GLOBALS['cache_array']['extension']['ext_func'][$ext_name] == 'Y') || (!isset($GLOBALS['cache_array']['extension']['ext_func'][$ext_name]))) && (!isExtensionLibraryLoaded($ext_name))) {
                        // Construct IFN for functions file
                        $funcsInclude = sprintf("inc/libs/%s_functions.php", $ext_name);
 
                        // Mark it as loaded
-                       $GLOBALS['ext_loaded']['funcs'][$ext_name] = true;
+                       markExtensionLibraryAsLoaded($ext_name);
 
                        // Download functions file
                        loadIncludeOnce($funcsInclude);
@@ -136,6 +142,9 @@ function loadExtension ($ext_name, $ext_mode, $ext_ver = '', $dry_run = false) {
                ));
        }
 
+       // Load extension's filter library if present
+       loadExtensionFilters($ext_name);
+
        // Extensions are not deprecated by default
        setExtensionDeprecated('N');
 
@@ -161,7 +170,7 @@ function loadExtension ($ext_name, $ext_mode, $ext_ver = '', $dry_run = false) {
        // Mark it as loaded in normal mode
        if (getExtensionMode() == '') {
                // Mark it now...
-               $GLOBALS['ext_loaded']['ext'][$ext_name] = true;
+               markExtensionAsLoaded($ext_name);
        } // END - if
 
        // All fine!
@@ -237,7 +246,7 @@ function registerExtension ($ext_name, $taskId, $dry_run = false, $logout = true
 
        // Does this extension exists?
        //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName());
-       if (loadExtension(getCurrentExtensionName(), 'register', '', isExtensionDryRun())) {
+       if (loadExtension(getCurrentExtensionName(), 'register', '0.0', isExtensionDryRun())) {
                // Set current extension name again
                setCurrentExtensionName($ext_name);
 
@@ -335,8 +344,8 @@ function registerExtension ($ext_name, $taskId, $dry_run = false, $logout = true
                if ($test === true) {
                        // "Dry-run-mode" activated?
                        if ((isExtensionDryRun() === false) && (!isExtensionOnRemovalList())) {
-                               //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . getCurrentExtensionName());
                                // Init SQLs and transfer ext->generic
+                               //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . getCurrentExtensionName());
                                initSqls();
                                setSqlsArray(getExtensionSqls());
 
@@ -346,8 +355,8 @@ function registerExtension ($ext_name, $taskId, $dry_run = false, $logout = true
                                // Register extension
                                //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'insert=' . getCurrentExtensionName() . '/' . getCurrentExtensionVersion() . ' - INSERT!');
                                if (isExtensionInstalledAndNewer('sql_patches', '0.0.6')) {
-                                       //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . getCurrentExtensionName() . ',always_active=' . getExtensionAlwaysActive() . ', ext_ver=' . getCurrentExtensionVersion() . 'ext_css=' . getExtensionHasCss());
                                        // New way, with CSS
+                                       //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . getCurrentExtensionName() . ',always_active=' . getExtensionAlwaysActive() . ', ext_ver=' . getCurrentExtensionVersion() . 'ext_css=' . getExtensionHasCss());
                                        SQL_QUERY_ESC("INSERT INTO `{?_MYSQL_PREFIX?}_extensions` (`ext_name`, `ext_active`, `ext_version`,`ext_has_css`) VALUES ('%s','%s','%s','%s')",
                                                array(
                                                        getCurrentExtensionName(),
@@ -356,8 +365,8 @@ function registerExtension ($ext_name, $taskId, $dry_run = false, $logout = true
                                                        getExtensionHasCss()
                                                ), __FUNCTION__, __LINE__);
                                } else {
-                                       //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . getCurrentExtensionName() . ',always_active=' . getExtensionAlwaysActive() . ', ext_ver=' . getCurrentExtensionVersion());
                                        // Old way, no CSS
+                                       //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . getCurrentExtensionName() . ',always_active=' . getExtensionAlwaysActive() . ', ext_ver=' . getCurrentExtensionVersion());
                                        SQL_QUERY_ESC("INSERT INTO `{?_MYSQL_PREFIX?}_extensions` (`ext_name`, `ext_active`, `ext_version`) VALUES ('%s','%s','%s')",
                                                array(
                                                        getCurrentExtensionName(),
@@ -368,6 +377,10 @@ function registerExtension ($ext_name, $taskId, $dry_run = false, $logout = true
 
                                // Use the insert id as extension id and cache it for early usage
                                $GLOBALS['cache_array']['extension']['ext_id'][getCurrentExtensionName()] = SQL_INSERTID();
+                               $GLOBALS['cache_array']['extension']['ext_name'][SQL_INSERTID()] = getCurrentExtensionName();
+
+                               // Mark it as installed
+                               $GLOBALS['ext_is_installed'][getCurrentExtensionName()] = true;
 
                                // Remove cache file(s) if extension is active
                                runFilterChain('post_extension_installed', array(
@@ -380,9 +393,6 @@ function registerExtension ($ext_name, $taskId, $dry_run = false, $logout = true
                                initExtensionSqls(true);
                                initExtensionNotes(true);
 
-                               // Mark it as installed
-                               $GLOBALS['ext_is_installed'][getCurrentExtensionName()] = true;
-
                                // In normal mode return a true on success
                                $ret = true;
                        } elseif (isExtensionDryRun() === true) {
@@ -442,20 +452,23 @@ function doExtensionSqls ($ext_id, $load_mode) {
        } // END - if
 
        // Init array
-       initExtensionSqls();
+       initExtensionSqls(true);
 
        // By default no SQL has been executed
        $sqlRan = false;
 
        // Load extension in detected mode
-       //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name[' . $ext_id . ']=' . getCurrentExtensionName());
-       loadExtension(getCurrentExtensionName(), $load_mode, '', false);
+       //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name[' . $ext_id . ']=' . getCurrentExtensionName() . ',load_mode=' . $load_mode);
+       loadExtension(getCurrentExtensionName(), $load_mode, '0.0', false);
 
        // Init these SQLs
        initSqls();
        setSqlsArray(getExtensionSqls());
 
+       // Debug message
        //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'SQLs::count=' . countSqls());
+
+       // Do we have entries?
        if (isSqlsValid()) {
                // Run SQL commands...
                runFilterChain('run_sqls');
@@ -465,7 +478,7 @@ function doExtensionSqls ($ext_id, $load_mode) {
        runFilterChain('extension_' . $load_mode);
 
        // Remove cache file(s) if extension is active
-       if (((isExtensionActive('cache')) && ((SQL_AFFECTEDROWS() == 1)) || ($sqlRan === true) || ($load_mode == 'activate') || ($load_mode == 'deactivate'))) {
+       if (((isExtensionActive('cache')) && ((!SQL_HASZEROAFFECTED())) || ($sqlRan === true) || ($load_mode == 'activate') || ($load_mode == 'deactivate'))) {
                // Run filters
                runFilterChain('post_extension_run_sql', getCurrentExtensionName());
        } // END - if
@@ -506,6 +519,9 @@ function isExtensionInstalled ($ext_name) {
                // Look in database
                $ext_id = getExtensionId($ext_name);
 
+               // Log debug message
+               //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Extension ' . $ext_name . ' has ext_id=' . $ext_id);
+
                // Do we have a record?
                $isInstalled = ($ext_id > 0);
 
@@ -547,7 +563,7 @@ function isExtensionActive ($ext_name) {
 
                // Count cache hits
                incrementStatsEntry('cache_hits');
-       } elseif (isset($GLOBALS['ext_loaded'][$ext_name])) {
+       } elseif (isExtensionLoaded($ext_name)) {
                // @TODO Extension is loaded, what next?
                debug_report_bug(__FUNCTION__, __LINE__, 'LOADED:' . $ext_name);
        } elseif (($ext_name == 'cache') || (!isExtensionInstalled('cache'))) {
@@ -640,7 +656,9 @@ function getExtensionVersion ($ext_name, $force = false) {
 // Updates a given extension with current extension version to latest version
 function updateExtension ($ext_name, $ext_ver, $dry_run = false) {
        // Only admins are allowed to update extensions
-       if ((!isAdmin()) || (empty($ext_name))) return false;
+       if ((!isAdmin()) || (empty($ext_name))) {
+               return false;
+       } // END - if
 
        // Set current SQL name
        setCurrentExtensionName($ext_name);
@@ -660,7 +678,7 @@ function updateExtension ($ext_name, $ext_ver, $dry_run = false) {
        initExtensionSqls();
 
        // Check if version is updated
-       //* DEBUG: */ debugOutput(getCurrentExtensionName().'/'.$ext_name.':'.getThisExtensionVersion().'/'.$ext_ver.'/'.intval(is_array($history)));
+       //* DEBUG: */ debugOutput(getCurrentExtensionName() . '/' . $ext_name . ':' . getThisExtensionVersion() . '/' . $ext_ver . '/' . intval(is_array($history)));
        if (((getThisExtensionVersion() != $ext_ver) || (isExtensionDryRun())) && (is_array($history))) {
                // Search for starting point
                $start = array_search($ext_ver, $history);
@@ -785,7 +803,7 @@ function addExtensionVerboseSqlTable ($title = '', $dashed = '', $switch = false
                        $OUT = loadTemplate('admin_extension_sql_table', true, $content);
                } else {
                        // No addional SQL commands to run
-                       $OUT = loadTemplate('admin_settings_saved', true, '{--ADMIN_NO_ADDITIONAL_SQLS--}');
+                       $OUT = displayMessage('{--ADMIN_NO_ADDITIONAL_SQLS--}', true);
                }
        } // END - if
 
@@ -902,38 +920,44 @@ function isExtensionIdValid ($ext_id) {
 
 // Activate given extension
 function doActivateExtension ($ext_name) {
+       // Is the extension installed?
+       if (!isExtensionInstalled($ext_name)) {
+               // Non-installed extensions cannot be activated
+               debug_report_bug(__FUNCTION__, __LINE__, 'Tried to activate non-installed extension ' . $ext_name);
+       } // END - if
+
        // Activate the extension
        SQL_QUERY_ESC("UPDATE `{?_MYSQL_PREFIX?}_extensions` SET `ext_active`='Y' WHERE `ext_name`='%s' LIMIT 1",
                array($ext_name), __FUNCTION__, __LINE__);
 
-       // Extension has been activated?
-       if (SQL_AFFECTEDROWS() == 1) {
-               // Then run all queries
-               doExtensionSqls(getExtensionId($ext_name), 'activate');
-       } // END - if
+       // Then run all queries
+       doExtensionSqls(getExtensionId($ext_name), 'activate');
 }
 
 // Deactivate given extension
-function doDeactivateExtension($ext_name) {
+function doDeactivateExtension ($ext_name) {
+       // Is the extension installed?
+       if (!isExtensionInstalled($ext_name)) {
+               // Non-installed extensions cannot be activated
+               debug_report_bug(__FUNCTION__, __LINE__, 'Tried to deactivate non-installed extension ' . $ext_name);
+       } // END - if
+
        // Activate the extension
        SQL_QUERY_ESC("UPDATE `{?_MYSQL_PREFIX?}_extensions` SET `ext_active`='N' WHERE `ext_name`='%s' LIMIT 1",
                array($ext_name), __FUNCTION__, __LINE__);
 
-       // Extension has been activated?
-       if (SQL_AFFECTEDROWS() == 1) {
-               // Then run all queries
-               doExtensionSqls(getExtensionId($ext_name), 'deactivate');
+       // Then run all queries
+       doExtensionSqls(getExtensionId($ext_name), 'deactivate');
 
-               // Create new task (we ignore the task id here)
-               createExtensionDeactivationTask($ext_name);
+       // Create new task (we ignore the task id here)
+       createExtensionDeactivationTask($ext_name);
 
-               // Notify the admin
-               sendAdminNotification(
-                       '{--ADMIN_EXTENSION_DEACTIVATED_SUBJECT--}',
-                       'admin_extension_deactivated',
-                       array('ext_name' => $ext_name)
-               );
-       } // END - if
+       // Notify the admin
+       sendAdminNotification(
+               '{--ADMIN_EXTENSION_DEACTIVATED_SUBJECT--}',
+               'admin_extension_deactivated',
+               array('ext_name' => $ext_name)
+       );
 }
 
 // Checks wether the extension is older than given
@@ -987,16 +1011,16 @@ function createNewExtensionTask ($ext_name) {
                $message = getMaskedMessage('ADMIN_EXTENSION_TEXT_FILE_MISSING', $ext_name);
 
                // Template file
-               $tpl = sprintf("%stemplates/%s/html/ext/ext_%s.tpl",
+               $FQFN = sprintf("%stemplates/%s/html/ext/ext_%s.tpl",
                        getPath(),
                        getLanguage(),
                        $ext_name
                );
 
                // Load text for task if found
-               if (isFileReadable($tpl)) {
-                       // Load extension's own text template (HTML!)
-                       $message = loadTemplate('ext_' . $ext_name, true);
+               if (isFileReadable($FQFN)) {
+                       // Load extension's description template (but do not compile the code)
+                       $message = loadTemplate('ext_' . $ext_name, true, array(), false);
                } else {
                        // Write this in debug.log as well
                        logDebugMessage(__FUNCTION__, __LINE__, $message);
@@ -1097,7 +1121,7 @@ function addExtensionNotes ($ext_ver) {
                                'notes' => '{--INITIAL_RELEASE--}'
                        );
                } else {
-                       // No update notes found!
+                       // No update notes found
                        $content = array(
                                'ver'   => $ext_ver,
                                'notes' => '{--NO_UPDATE_NOTES--}'
@@ -1181,8 +1205,8 @@ function isExtensionDeprecated () {
 }
 
 // Setter for EXT_UPDATE_DEPENDS flag
-function addExtensionUpdateDependency ($updateDepends) {
-       //* DEBUG */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . '/' . $updateDepends . ' - ENTERED!');
+function addExtensionDependency ($updateDepends) {
+       //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . '/' . $updateDepends . ' - ENTERED!');
        // Is the update depency empty? (NEED TO BE FIXED!)
        if (empty($updateDepends)) {
                // Please report this bug!
@@ -1202,7 +1226,7 @@ function addExtensionUpdateDependency ($updateDepends) {
 
        // Remember it in the list of running updates
        $GLOBALS['ext_running_updates'][getCurrentExtensionName()][] = $updateDepends;
-       //* DEBUG */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . '/' . $updateDepends . ' - EXIT!');
+       //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'currName=' . getCurrentExtensionName() . '/' . $updateDepends . ' - EXIT!');
 }
 
 // Getter for running updates
@@ -1269,7 +1293,7 @@ function isExtensionUpdateRunning ($ext_name) {
                foreach ($GLOBALS['ext_running_updates'] as $ext1=>$depends) {
                        // Is it found?
                        if (($ext1 == $ext_name) || ($isRunning === true)) {
-                               // Found!
+                               // found
                                logDebugMessage(__FUNCTION__, __LINE__, 'ext1=' . $ext1 . ',ext_name=' . $ext_name . ',isRunning=' . intval($isRunning));
                                $isRunning = true;
                                break;
@@ -1317,7 +1341,7 @@ function countExtensionUpdateDependencies () {
 }
 
 // Removes given extension from update denpency list
-function removeExtensionUpdateDependency ($ext_name) {
+function removeExtensionDependency ($ext_name) {
        // Look it up
        $key = array_search($ext_name, getExtensionUpdateDependencies());
 
@@ -1448,6 +1472,7 @@ function initExtensionSqls ($force = false) {
 // Adds SQLs to the SQLs array but "assigns" it with current extension name
 function addExtensionSql ($sql) {
        // Add it
+       //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . getCurrentExtensionName() . ',ext_version=' . getCurrentExtensionVersion() . ',sql=' . $sql);
        $GLOBALS['ext_sqls'][getCurrentExtensionName()][getCurrentExtensionVersion()][] = $sql;
 }
 
@@ -1526,19 +1551,19 @@ function redirectOnUninstalledExtension ($ext_name) {
 // Filter for initialization of all extensions by loading them in 'init' mode
 function FILTER_INIT_EXTENSIONS () {
        // Do we have some entries?
-       //* DEBUG */ logDebugMessage(__FUNCTION__, __LINE__, 'ENTRY!');
+       //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ENTRY!');
        if (isset($GLOBALS['cache_array']['extension']['ext_name'])) {
                // Load all found extensions if found
-               //* DEBUG */ logDebugMessage(__FUNCTION__, __LINE__, 'CACHE - START!');
+               //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'CACHE - START!');
                foreach ($GLOBALS['cache_array']['extension']['ext_name'] as $key => $ext_name) {
                        // Load it
-                       //* DEBUG */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name='.$ext_name.' - START');
+                       //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name='.$ext_name.' - START');
                        loadExtension($ext_name, 'init', getExtensionVersion($ext_name));
-                       //* DEBUG */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name='.$ext_name.' - END');
+                       //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name='.$ext_name.' - END');
                } // END - foreach
-               //* DEBUG */ logDebugMessage(__FUNCTION__, __LINE__, 'CACHE - END!');
+               //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'CACHE - END!');
        } // END - if
-       //* DEBUG */ logDebugMessage(__FUNCTION__, __LINE__, 'EXIT!');
+       //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'EXIT!');
 }
 
 // Setter for extension mode
@@ -1631,14 +1656,8 @@ function getExtensionHasCss () {
 
 // Checks wether the given extension has a language file
 function ifExtensionHasLanguageFile ($ext_name) {
-       // Default is no language file
-       $hasLanguage = false;
-
        // Do we have cache?
        if (isset($GLOBALS['cache_array']['extension']['ext_lang'][$ext_name])) {
-               // Then use it
-               $hasLanguage = ($GLOBALS['cache_array']['extension']['ext_lang'][$ext_name] == 'Y');
-
                // Count cache hits
                incrementStatsEntry('cache_hits');
        } else {
@@ -1706,7 +1725,7 @@ function isExtensionFunctionFileReadable ($ext_name) {
                $funcsInclude = sprintf("inc/libs/%s_functions.php", $ext_name);
 
                // Is this include there?
-               if ((isFileReadable($funcsInclude)) && (!isset($GLOBALS['ext_loaded']['funcs'][$ext_name])) && (getExtensionMode() == 'test')) {
+               if ((isFileReadable($funcsInclude)) && (!isExtensionLibraryLoaded($ext_name)) && (getExtensionMode() == 'test')) {
                        // Cache it!
                        //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ext_name=' . $ext_name . ',ext_func=Y - FOUND!');
                        $GLOBALS['cache_array']['extension']['ext_func'][$ext_name] = 'Y';
@@ -1722,6 +1741,16 @@ function isExtensionFunctionFileReadable ($ext_name) {
        return ($GLOBALS['cache_array']['extension']['ext_func'][$ext_name] == 'Y');
 }
 
+// Adds a DROP TABLE statement if the requested tabled is there
+function addDropTableSql ($table) {
+       // Is the table there?
+       if (isSqlTableCreated($table)) {
+               // Then add it, non-existing tables can be ignored because it will
+               // happen with every newly installed extension.
+               addExtensionSql('DROP TABLE `{?_MYSQL_PREFIX?}_' . $table . '`');
+       } // END - if
+}
+
 // Adds an admin menu to the SQL queue of the menu entry is not found
 function addAdminMenuSql ($action, $what, $title, $descr, $sort) {
        // Now check if this menu is there
@@ -1750,7 +1779,7 @@ function addAdminMenuSql ($action, $what, $title, $descr, $sort) {
                addExtensionSql($sql);
        } elseif (isDebugModeEnabled()) {
                // Double menus should be located and fixed!
-               logDebugMessage(__FUNCTION__, __LINE__, sprintf("Double admin menu action=%s, what=%s detected.", $action, $what));
+               logDebugMessage(__FUNCTION__, __LINE__, sprintf("Double admin menu action=%s,what=%s,title=%s detected.", $action, $what, $title));
        }
 }
 
@@ -1784,7 +1813,7 @@ function addGuestMenuSql ($action, $what, $title, $visible, $locked, $sort) {
                addExtensionSql($sql);
        } elseif (isDebugModeEnabled()) {
                // Double menus should be located and fixed!
-               logDebugMessage(__FUNCTION__, __LINE__, sprintf("Double guest menu action=%s, what=%s detected.", $action, $what));
+               logDebugMessage(__FUNCTION__, __LINE__, sprintf("Double guest menu action=%s,what=%s,title=%s,locked=%s,visible=%s detected.", $action, $what, $title, $locked, $visible));
        }
 }
 
@@ -1818,7 +1847,7 @@ function addMemberMenuSql ($action, $what, $title, $visible, $locked, $sort) {
                addExtensionSql($sql);
        } elseif (isDebugModeEnabled()) {
                // Double menus should be located and fixed!
-               logDebugMessage(__FUNCTION__, __LINE__, sprintf("Double member menu action=%s, what=%s detected.", $action, $what));
+               logDebugMessage(__FUNCTION__, __LINE__, sprintf("Double member menu action=%s,what=%s,title=%s,visivle=%s,locked=%s detected.", $action, $what, $title, $visible, $locked));
        }
 }
 
@@ -1850,7 +1879,7 @@ function addSponsorMenuSql ($action, $what, $title, $active, $sort) {
                addExtensionSql($sql);
        } elseif (isDebugModeEnabled()) {
                // Double menus should be located and fixed!
-               logDebugMessage(__FUNCTION__, __LINE__, sprintf("Double sponsor menu action=%s, what=%s detected.", $action, $what));
+               logDebugMessage(__FUNCTION__, __LINE__, sprintf("Double sponsor menu action=%s,what=%s,title=%s,active=%s detected.", $action, $what, $title, $active));
        }
 }
 
@@ -1874,7 +1903,7 @@ function isExtensionProductive ($ext_name = '') {
        } // END - if
 
        // Do we have cache?
-       if (!isset($GLOBALS['ext_is_productive'][$ext_name])) {
+       if (!isset($GLOBALS[__FUNCTION__][$ext_name])) {
                // Load extension only if not yet loaded
                if (!isset($GLOBALS['ext_productive'][$ext_name])) {
                        // Load extension in test mode
@@ -1882,15 +1911,50 @@ function isExtensionProductive ($ext_name = '') {
                } // END - if
 
                // Determine it
-               $GLOBALS['ext_is_productive'][$ext_name] = ((isset($GLOBALS['ext_productive'][$ext_name])) && ($GLOBALS['ext_productive'][$ext_name] === true));
+               $GLOBALS[__FUNCTION__][$ext_name] = ((isset($GLOBALS['ext_productive'][$ext_name])) && ($GLOBALS['ext_productive'][$ext_name] === true));
        } // END - if
 
        // Log debug message
-       //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, sprintf("ext_name=%s,isProductive=%s", $ext_name, intval($GLOBALS['ext_is_productive'][$ext_name])));
+       //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, sprintf("ext_name=%s,isProductive=%s", $ext_name, intval($GLOBALS[__FUNCTION__][$ext_name])));
 
        // Return result
-       return $GLOBALS['ext_is_productive'][$ext_name];
+       return $GLOBALS[__FUNCTION__][$ext_name];
+}
+
+// Mark extension file as loaded
+function markExtensionAsLoaded ($ext_name) {
+       // Is it already loaded?
+       if (isExtensionLoaded($ext_name)) {
+               // Then abort here
+               debug_report_bug(__FUNCTION__, __LINE__, 'Extension ' . $ext_name . ' is already marked as loaded!');
+       } // END - if
+
+       // Mark it
+       $GLOBALS['ext_loaded']['ext_name'][$ext_name] = true;
+}
+
+// Determine wether the given extension is already loaded
+function isExtensionLoaded ($ext_name) {
+       // Is it there?
+       return ((isset($GLOBALS['ext_loaded']['ext_name'][$ext_name])) && ($GLOBALS['ext_loaded']['ext_name'][$ext_name] === true));
 }
 
+// Mark extension's library file as loaded
+function markExtensionLibraryAsLoaded ($ext_name) {
+       // Is it already loaded?
+       if (isExtensionLibraryLoaded($ext_name)) {
+               // Then abort here
+               debug_report_bug(__FUNCTION__, __LINE__, 'Extension library ' . $ext_name . ' is already marked as loaded!');
+       } // END - if
+
+       // Mark it
+       $GLOBALS['ext_loaded']['library'][$ext_name] = true;
+}
+
+// Determine wether the given extension's library is already loaded
+function isExtensionLibraryLoaded ($ext_name) {
+       // Is it there?
+       return ((isset($GLOBALS['ext_loaded']['library'][$ext_name])) && ($GLOBALS['ext_loaded']['library'][$ext_name] === true));
+}
 // [EOF]
 ?>