Filters should be executed even when sql_patches is out-dated
[mailer.git] / inc / load_extensions.php
1 <?php
2 /************************************************************************
3  * MXChange v0.2.1                                    Start: 06/26/2004 *
4  * ===============                              Last change: 07/01/2005 *
5  *                                                                      *
6  * -------------------------------------------------------------------- *
7  * File              : load_extensions.php                              *
8  * -------------------------------------------------------------------- *
9  * Short description : Load all extensions                              *
10  * -------------------------------------------------------------------- *
11  * Kurzbeschreibung  : Alle Erweiterungen laden                         *
12  * -------------------------------------------------------------------- *
13  * @TODO Rewrite this whole file to load_cache-extensions.php           *
14  * -------------------------------------------------------------------- *
15  * $Revision::                                                        $ *
16  * $Date::                                                            $ *
17  * $Tag:: 0.2.1-FINAL                                                 $ *
18  * $Author::                                                          $ *
19  * Needs to be in all Files and every File needs "svn propset           *
20  * svn:keywords Date Revision" (autoprobset!) at least!!!!!!            *
21  * -------------------------------------------------------------------- *
22  * Copyright (c) 2003 - 2008 by Roland Haeder                           *
23  * For more information visit: http://www.mxchange.org                  *
24  *                                                                      *
25  * This program is free software; you can redistribute it and/or modify *
26  * it under the terms of the GNU General Public License as published by *
27  * the Free Software Foundation; either version 2 of the License, or    *
28  * (at your option) any later version.                                  *
29  *                                                                      *
30  * This program is distributed in the hope that it will be useful,      *
31  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
32  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
33  * GNU General Public License for more details.                         *
34  *                                                                      *
35  * You should have received a copy of the GNU General Public License    *
36  * along with this program; if not, write to the Free Software          *
37  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,               *
38  * MA  02110-1301  USA                                                  *
39  ************************************************************************/
40
41 // Some security stuff...
42 if (!defined('__SECURITY')) {
43         $INC = substr(dirname(__FILE__), 0, strpos(dirname(__FILE__), '/inc') + 4) . '/security.php';
44         require($INC);
45 } // END - if
46
47 // Init variables
48 EXT_INIT_CSS_FILES();
49 $add = '';
50
51 // Init cache instance and array
52 $GLOBALS['cache_instance'] = null;
53 $GLOBALS['cache_array'] = array();
54
55 // Skip loading extensions
56 if ((!isInstalled()) || (isInstalling())) {
57         // Init filter system here
58         initFilterSystem();
59
60         // Skip loading
61         return;
62 } // END - if
63
64 // Initialize array for "always keep active extensions"
65 $GLOBALS['cache_array']['active_extensions'] = array();
66
67 // By default no cache is set
68 $GLOBALS['cache_mode'] = 'no';
69
70 // Load sql_patchrs extension alone
71 if (!LOAD_EXTENSION('sql_patches')) {
72         // Could not load sql_patches! ARGH!!!
73         trigger_error('Cannot load extension sql_patches.');
74 } // END - if
75
76 // Init inc pool array
77 INIT_INC_POOL();
78
79 //
80 // Load extensions
81 //
82 if (EXT_IS_ACTIVE('cache')) {
83         // Load cache extension alone
84         if (!LOAD_EXTENSION('cache')) {
85                 // Extension 'cache' was not loaded
86                 trigger_error('Cannot load extension cache.');
87         } // END - if
88
89         // Check extension cache
90         switch (($GLOBALS['cache_instance']->loadCacheFile('extensions', true)) && ($GLOBALS['cache_instance']->extensionVersionMatches('sql_patches'))) {
91                 case true : $GLOBALS['cache_mode'] = 'load'; break;
92                 case false: $GLOBALS['cache_mode'] = 'init'; break;
93         } // END - switch
94
95         // Do we need to init the cache? But not in "CSS mode".
96         if (($GLOBALS['cache_mode'] == 'init') && (getConfig('cache_exts') == 'Y') && (getOutputMode() == '0')) {
97                 // Init cache file
98                 $GLOBALS['cache_instance']->init('EXTENSIONS');
99                 $GLOBALS['cache_instance']->storeExtensionVersion('sql_patches');
100         } elseif (getConfig('cache_exts') != 'Y') {
101                 // Cache will not be created for extensions
102                 $GLOBALS['cache_mode'] = 'skip';
103         }
104 } // END - if
105
106 // Load cache?
107 if ($GLOBALS['cache_mode'] == 'load') {
108         // Init include array
109         $EXT_POOL = array();
110
111         // Re-initialize handler
112         $GLOBALS['cache_instance']->loadCacheFile('extensions', true);
113
114         // Load extension data from cache file
115         $EXT_DUMMY = $GLOBALS['cache_instance']->getArrayFromCache();
116
117         // Is the cache file fine?
118         if (!isset($EXT_DUMMY['ext_name'])) {
119                 // Cache file is damaged so kill it
120                 $GLOBALS['cache_instance']->destroyCacheFile();
121
122                 // Retry it
123                 require(__FILE__);
124                 return;
125         } // END -  if
126
127         // Begin with the cache preparation of extensions
128         $EXT_NAMES = array();
129         foreach ($EXT_DUMMY['ext_name'] as $k => $name) {
130                 // Load CSS file
131                 if ($EXT_DUMMY['ext_css'][$k] == 'Y') EXT_ADD_CSS_FILE($name . '.css');
132
133                 // Load extension file itself
134                 if ((($EXT_DUMMY['ext_active'][$k] == 'Y') || ($EXT_DUMMY['ext_keep'][$k] == 'Y') || (IS_ADMIN())) && (!in_array($name, array('sql_patches', 'cache')))) {
135                         $EXT_POOL[] = $name;
136                 } // END - if
137
138                 // Version number
139                 $EXT_DUMMY['ext_version'][$name] = $EXT_DUMMY['ext_version'][$k];
140                 unset($EXT_DUMMY['ext_version'][$k]);
141
142                 // Extension is active
143                 $EXT_DUMMY['ext_active'][$name] = $EXT_DUMMY['ext_active'][$k];
144                 unset($EXT_DUMMY['ext_active'][$k]);
145
146                 // Ext menu
147                 $EXT_DUMMY['ext_menu'][$name] = $EXT_DUMMY['ext_menu'][$k];
148                 unset($EXT_DUMMY['ext_menu'][$k]);
149
150                 // Extension id
151                 $EXT_DUMMY['ext_id'][$name] = $EXT_DUMMY['ext_id'][$k];
152                 $id = $EXT_DUMMY['ext_id'][$name];
153                 unset($EXT_DUMMY['ext_id'][$k]);
154
155                 // Add ext name
156                 $EXT_NAMES[$id] = $name;
157
158                 // Add deprecated flag (defaults to 'not deprecated')
159                 $EXT_DUMMY['ext_deprecated'][$name] = 'N';
160
161                 // Mark it as active extension
162                 $GLOBALS['cache_array']['active_extensions'][$name] = $EXT_DUMMY['ext_keep'][$k];
163                 unset($EXT_DUMMY['ext_keep'][$k]);
164
165                 // Remove unneccessary data from memory
166                 unset($EXT_DUMMY['ext_css'][$k]);
167         } // END - foreach
168
169         // Write dummy array back
170         $EXT_DUMMY['ext_name'] = $EXT_NAMES;
171         unset($EXT_NAMES);
172
173         // Loading cache is done so let's free some memory!
174         unset($EXT_DUMMY['ext_keep']);
175         unset($EXT_DUMMY['ext_css']);
176         $GLOBALS['cache_array']['extensions'] = $EXT_DUMMY;
177         unset($EXT_DUMMY);
178
179         // No database load needed
180         $res_ext_crt = false;
181
182         // Load all extension files
183         foreach ($EXT_POOL as $ext) {
184                 LOAD_EXTENSION($ext);
185         } // END - foreach
186
187         // Load more cache files (like admins)
188         loadIncludeOnce('inc/load_cache.php');
189
190         // Remove array
191         unset($EXT_POOL);
192 } else {
193         // If current user is not admin load only activated extensions. But load
194         // them all if we are going to init the cache files. The admin shall use
195         // every available extension for testing purposes.
196         if ((!IS_ADMIN()) && ($GLOBALS['cache_mode'] != 'init')) $add = " WHERE `ext_active`='Y'";
197
198         if (GET_EXT_VERSION('sql_patches') >= '0.0.6') {
199                 // Query with CSS file from DB
200                 $res_ext_crt = SQL_QUERY("SELECT id AS ext_id, ext_name, ext_has_css AS ext_css, ext_active, ext_version
201 FROM `{!_MYSQL_PREFIX!}_extensions`" . $add . "
202 ORDER BY ext_name", __FILE__, __LINE__);
203         } else {
204                 // Old obsolete query string
205                 $res_ext_crt = SQL_QUERY("SELECT id AS ext_id, ext_name, ext_name, ext_active, ext_version
206 FROM `{!_MYSQL_PREFIX!}_extensions`" . $add . "
207 ORDER BY ext_name", __FILE__, __LINE__);
208         }
209 }
210
211 // Array for removed but not uninstalled extensions
212 $DEL = array();
213
214 // At least one found?
215 if ((SQL_NUMROWS($res_ext_crt) > 0) && ((($GLOBALS['cache_mode'] == 'init') && (getOutputMode() != '1') && (getOutputMode() != '-1')) || ($GLOBALS['cache_mode'] == 'no'))) {
216         // Extensions are registered so we load them
217         while ($content = SQL_FETCHARRAY($res_ext_crt)) {
218                 // Get menu entry
219                 $content['ext_menu'] = 'N';
220                 if (MODULE_HAS_MENU($content['ext_name'], true)) {
221                         $content['ext_menu'] = 'Y';
222                 } // END - if
223
224                 // Generate FQFN for extension
225                 $FQFN = sprintf("%sinc/extensions/ext-%s.php", constant('PATH'), $content['ext_name']);
226
227                 // Does the extension file exists?
228                 if (isFileReadable($FQFN)) {
229                         // By default no extension is always active, except sql_patches
230                         EXT_SET_ALWAYS_ACTIVE('N');
231
232                         // Load extension
233                         if (($content['ext_name'] != 'sql_patches') && (($content['ext_name'] != 'cache') || (!EXT_IS_ACTIVE('cache')))) {
234                                 // Load extension
235                                 LOAD_EXTENSION($content['ext_name']);
236                         } else {
237                                 // Keep sql_patches always active
238                                 EXT_SET_ALWAYS_ACTIVE('Y');
239                         }
240
241                         // Transfer EXT_ALWAYS_ACTIVE flag
242                         $content['ext_keep'] = EXT_GET_ALWAYS_ACTIVE();
243
244                         // CSS file handling:
245                         if ((!isset($content['ext_css'])) || ($content['ext_css'] == 'Y')) {
246                                 // Create FQFN for the CSS file
247                                 $FQFN = sprintf("%stheme/%s/css/%s.css", constant('PATH'), getCurrentTheme(), $content['ext_name']);
248
249                                 // Is the file there?
250                                 if (isFileReadable($FQFN)) {
251                                         // CSS file for extension was found (use only relative path for now!)
252                                         EXT_ADD_CSS_FILE($content['ext_name'] . '.css');
253                                         $content['ext_css'] = 'Y';
254                                 } else {
255                                         // Don't load CSS file
256                                         $content['ext_css'] = 'N';
257                                 }
258                         } // END - if
259
260                         // Shall we cache?
261                         if ($GLOBALS['cache_mode'] == 'init') {
262                                 // Add cache row
263                                 $GLOBALS['cache_instance']->addRow($content);
264                         } elseif ($GLOBALS['cache_mode'] == 'no') {
265                                 // Remember this value for later usage
266                                 $GLOBALS['cache_array']['active_extensions'][$content['ext_name']] = EXT_GET_ALWAYS_ACTIVE();
267                         }
268                 } elseif (!isFileReadable($FQFN)) {
269                         // Deleted extension file so we mark it for removal from DB
270                         $DEL[] = $content['ext_name'];
271                 }
272         } // END - while
273
274         if ($GLOBALS['cache_mode'] == 'init') {
275                 // Close cache file
276                 $GLOBALS['cache_instance']->finalize();
277
278                 // Load more cache files (like admins)
279                 loadIncludeOnce('inc/load_cache.php');
280         } else {
281                 // Init filter system for non-init mode
282                 initFilterSystem();
283         }
284
285         // Free memory
286         SQL_FREERESULT($res_ext_crt);
287 } elseif ((!EXT_IS_ACTIVE('cache')) || (($GLOBALS['cache_mode'] == 'init') && (getOutputMode() != 0))) {
288         // Init filter system even when there are no extensions installed. #16
289         initFilterSystem();
290 } elseif ($GLOBALS['cache_mode'] != 'load') {
291         // Something unexpected!
292         debug_report_bug('Unexpected state in '.basename(__FILE__).': cache_mode='.$GLOBALS['cache_mode'].', numRows='.SQL_NUMROWS($res_ext_crt));
293 }
294
295 // Run the filter
296 runFilterChain('load_includes');
297
298 // Uninstall extensions that are no longer in our system
299 if (!empty($DEL[0])) {
300         // Remove extensions from two tables: extension registry and tasks table
301         foreach ($DEL as $del_ext) {
302                 // First remove entry from extensions table
303                 SQL_QUERY_ESC("DELETE LOW_PRIORITY FROM `{!_MYSQL_PREFIX!}_extensions` WHERE `ext_name`='%s' LIMIT 1",
304                         array($del_ext), __FILE__, __LINE__);
305
306                 // Remove (maybe?) found tasks (main task and possible updates
307                 SQL_QUERY_ESC("DELETE LOW_PRIORITY FROM `{!_MYSQL_PREFIX!}_task_system` WHERE `subject`='[%s:]' AND (`task_type`='EXTENSION' OR `task_type`='EXTENSION_UPDATE')",
308                         array($del_ext), __FILE__, __LINE__);
309         } // END - foreach
310
311         // I think it's not neccessary to run the optimization function here
312         // because we didn't delete so much data from database. Can you aggree?
313 } // END - if
314
315 //
316 ?>