source: trunk/includes/System.php@ 860

Last change on this file since 860 was 860, checked in by chronos, 9 years ago
  • Modified: Now application modules are started according configuration file.
  • Added: Each module which want to show something in main page bars needs to register its callback.
  • Property svn:executable set to *
File size: 19.5 KB
Line 
1<?php
2
3class Core extends Application
4{
5 var $Config;
6 var $PathItems;
7 var $Menu;
8 var $DoNotShowPage;
9 var $OnPageNotFound;
10 var $Pages;
11 /* @var LocaleManager */
12 var $LocaleManager;
13 var $Bars;
14
15 function __construct()
16 {
17 parent::__construct();
18 $this->Config = array();
19 $this->Menu = array();
20 $this->RSSChannels = array();
21 $this->DoNotShowPage = false;
22 $this->OnPageNotFound = array();
23 $this->Pages = array();
24 $this->Bars = array();
25 }
26
27 function Init()
28 {
29 global $GlobalLocaleManager, $Config;
30
31 $this->Config = $Config;
32 if(isset($this->Config['Web']['Timezone']))
33 date_default_timezone_set($this->Config['Web']['Timezone']);
34 mb_internal_encoding("UTF-8");
35
36 if(isset($this->Config['Database']))
37 {
38 $this->Database->Connect($this->Config['Database']['Host'],
39 $this->Config['Database']['User'], $this->Config['Database']['Password'],
40 $this->Config['Database']['Database']);
41 $this->Database->charset($this->Config['Database']['Charset']);
42 $this->Database->ShowSQLQuery = $this->Config['Web']['ShowSQLQuery'];
43 $this->Database->ShowSQLError = $this->Config['Web']['ShowSQLError'];
44 $this->Database->LogSQLQuery = $this->Config['Web']['LogSQLQuery'];
45 }
46
47 $this->LocaleManager = new LocaleManager($this);
48 $this->LocaleManager->Dir = dirname(dirname(__FILE__)).'/locale';
49 $this->LocaleManager->Available = array(
50 'cs' => array('Code' => 'cs', 'Title' => 'Česky'),
51 'en' => array('Code' => 'en', 'Title' => 'English'),
52 );
53 $GlobalLocaleManager = $this->LocaleManager;
54 $this->LinkLocaleExceptions = array('images', 'style', 'tmp', 'files', 'aowow',
55 'banners'
56 );
57
58 $this->PathItems = ProcessURL();
59
60 // Detect interface locale
61 $this->LocaleManager->DefaultLangCode = $this->Config['Web']['Locale'];
62 $this->LocaleManager->LangCode = $this->LocaleManager->DefaultLangCode;
63 if(count($this->PathItems) > 0)
64 {
65 $NewLangCode = $this->PathItems[0];
66 if(array_key_exists($NewLangCode, $this->LocaleManager->Available)) {
67 array_shift($this->PathItems);
68 $this->LocaleManager->LangCode = $NewLangCode;
69 }
70 }
71 if(array_key_exists($this->LocaleManager->LangCode, $this->LocaleManager->Available))
72 $this->LocaleManager->LoadLocale($this->LocaleManager->LangCode);
73
74 $this->Menu = array
75 (
76 /* array(
77 'Title' => T('Files'),
78 'Hint' => 'Stahování různých pomocných souborů a programů',
79 'Link' => $this->Link('/download.php'),
80 'Permission' => LICENCE_ANONYMOUS,
81 'Icon' => '',
82 ),
83
84 array(
85 'Title' => T('IRC chat'),
86 'Hint' => 'IRC chat pro překladatele',
87 'Link' => 'http://embed.mibbit.com/?server=game.zdechov.net%3A6667&amp;channel=%23wowpreklad&amp;forcePrompt=true&amp;charset=utf-8',
88 'Permission' => LICENCE_ANONYMOUS,
89 'Icon' => '',
90 ),
91 */
92 );
93 }
94
95 function Run()
96 {
97 global $ScriptStartTime, $StopAfterUpdateManager,
98 $UpdateManager;
99
100 $ScriptStartTime = GetMicrotime();
101 if(GetRemoteAddress() != '') session_start();
102
103 // SQL injection hack protection
104 foreach($_POST as $Index => $Item)
105 {
106 if(is_array($_POST[$Index]))
107 foreach($_POST[$Index] as $Index2 => $Item2) $_POST[$Index][$Index2] = addslashes($Item2);
108 else $_POST[$Index] = addslashes($_POST[$Index]);
109 }
110 foreach($_GET as $Index => $Item) $_GET[$Index] = addslashes($_GET[$Index]);
111
112 $this->RegisterPageBar('Top');
113 $this->RegisterPageBar('Left');
114 $this->RegisterPageBar('Right');
115 $this->Init();
116
117 // Register and start existing modules
118 $this->Setup = new Setup($this);
119 $this->Setup->Start();
120 $this->Setup->UpdateManager->VersionTable = 'DbVersion';
121 if($this->Setup->CheckState())
122 {
123 $this->ModuleManager->Start();
124 }
125
126 $this->BaseView = new BaseView($this);
127 if($this->DoNotShowPage == false)
128 {
129 $this->ShowPage();
130 }
131 }
132
133 function GetMicrotime()
134 {
135 list($Usec, $Sec) = explode(' ', microtime());
136 return ((float)$Usec + (float)$Sec);
137 }
138
139 function Link($Target)
140 {
141 $Remaining = substr($Target, count($this->Config['Web']['BaseURL']));
142 $TargetParts = explode('/', $Remaining);
143 if(count($TargetParts) > 0)
144 {
145 if(in_array($TargetParts[0], $this->LinkLocaleExceptions))
146 {
147 return($this->Config['Web']['BaseURL'].$Target);
148 }
149 }
150 return($this->LinkLocale($Target));
151 }
152
153 function TranslateURL($URL, $Locale)
154 {
155 // Try translate URL directory parts from current locale to target locale
156 $Remaining = $URL;
157 $RemainingParts = explode('?', $Remaining);
158 $Directory = $RemainingParts[0];
159 if(count($RemainingParts) > 1)
160 {
161 $Params = $RemainingParts[1];
162 } else {
163 $Params = '';
164 }
165 $TargetLocaleManager = new LocaleManager($this);
166 $TargetLocaleManager->Dir = $this->LocaleManager->Dir;
167 $TargetLocaleManager->Available = $this->LocaleManager->Available;
168 $TargetLocaleManager->LoadLocale($Locale);
169
170 $DirectoryParts = explode('/', $Directory);
171 foreach($DirectoryParts as $Index => $Item)
172 {
173 $NewText = $TargetLocaleManager->CurrentLocale->Texts->Translate($Item, 'URL');
174 $DirectoryParts[$Index] = $NewText;
175 }
176 $Directory = implode('/', $DirectoryParts);
177 $Remaining = $Directory;
178 if($Params != '') $Remaining .= '?'.$Params;
179
180 return($Remaining);
181 }
182
183 function TranslateReverseURL($URL, $Locale)
184 {
185 // Try translate URL directory parts from current locale to target locale
186 $Remaining = $URL;
187 $RemainingParts = explode('?', $Remaining);
188 $Directory = $RemainingParts[0];
189 if(count($RemainingParts) > 1)
190 {
191 $Params = $RemainingParts[1];
192 } else {
193 $Params = '';
194 }
195 $TargetLocaleManager = new LocaleManager($this);
196 $TargetLocaleManager->Dir = $this->LocaleManager->Dir;
197 $TargetLocaleManager->Available = $this->LocaleManager->Available;
198 $TargetLocaleManager->LoadLocale($Locale);
199
200 $DirectoryParts = explode('/', $Directory);
201 foreach($DirectoryParts as $Index => $Item)
202 {
203 $NewText = $TargetLocaleManager->CurrentLocale->Texts->TranslateReverse($Item, 'URL');
204 $DirectoryParts[$Index] = $NewText;
205 }
206 $Directory = implode('/', $DirectoryParts);
207 $Remaining = $Directory;
208 if($Params != '') $Remaining .= '?'.$Params;
209
210 return($Remaining);
211 }
212
213 function LinkLocale($Target, $Locale = '')
214 {
215 if($Locale == '') $Locale = $this->LocaleManager->LangCode;
216
217 $Target = $this->TranslateURL($Target, $Locale);
218
219 if($Locale == $this->LocaleManager->DefaultLangCode)
220 return($this->Config['Web']['BaseURL'].$Target);
221 return($this->Config['Web']['BaseURL'].'/'.$Locale.$Target);
222 }
223
224 function RegisterPage($Path, $Handler)
225 {
226 if(is_array($Path))
227 {
228 $Page = &$this->Pages;
229 $LastKey = array_pop($Path);
230 foreach($Path as $PathItem)
231 {
232 $Page = &$Page[$PathItem];
233 }
234 if(!is_array($Page)) $Page = array('' => $Page);
235 $Page[$LastKey] = $Handler;
236 } else $this->Pages[$Path] = $Handler;
237 }
238
239 function RegisterMenuItem($MenuItem, $Pos = NULL)
240 {
241 if(is_null($Pos)) $this->Menu[] = $MenuItem;
242 else {
243 array_splice($this->Menu, $Pos, 0, array($MenuItem));
244 }
245 }
246
247 function SearchPage($PathItems, $Pages)
248 {
249 if(count($PathItems) == 0) $PathItems = array('');
250 $PathItem = $PathItems[0];
251 $PathItem = $this->LocaleManager->CurrentLocale->Texts->TranslateReverse($PathItem, 'URL');
252
253 if(array_key_exists($PathItem, $Pages))
254 {
255 if(is_array($Pages[$PathItem]))
256 {
257 array_shift($PathItems);
258 return($this->SearchPage($PathItems, $Pages[$PathItem]));
259 } else
260 {
261 if(count($PathItems) == 1) return($Pages[$PathItem]);
262 else return(''); // Unexpected subpages
263 }
264 } else return('');
265 }
266
267 function PageNotFound()
268 {
269 // Send correct HTTP status code to signal unknown page
270 if(array_key_exists('SERVER_PROTOCOL', $_SERVER))
271 Header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found');
272 if(array_key_exists('HTTP_REFERER', $_SERVER)) $Referer = ' Referer: '.$_SERVER['HTTP_REFERER'];
273 else $Referer = '';
274 if(isset($this->ModuleManager->Modules['Log']))
275 $this->ModuleManager->Modules['Log']->WriteLog('Stránka "'.
276 implode('/', $this->PathItems).'" nenalezena'.$Referer, LOG_TYPE_PAGE_NOT_FOUND);
277 return(ShowMessage(sprintf(T('Page "%s" not found'), implode('/', $this->PathItems)), MESSAGE_CRITICAL));
278 }
279
280 function ShowPage()
281 {
282 $Output = '';
283
284 /* @var $Page Page */
285 $ClassName = $this->SearchPage($this->PathItems, $this->Pages);
286 if(($ClassName != '') and (class_exists($ClassName)))
287 {
288 $Page = new $ClassName($this);
289 $Output = $Page->GetOutput();
290 $this->BaseView->Title = $Page->Title;
291 if($Page->RawPage == false) $Output = $this->BaseView->ShowPage($Output);
292 } else {
293 $Output2 = '';
294 if((count($this->OnPageNotFound) == 2)
295 and method_exists($this->OnPageNotFound[0], $this->OnPageNotFound[1]))
296 $Output2 = call_user_func_array($this->OnPageNotFound, array());
297 if($Output2 != '') $Output .= $this->BaseView->ShowPage($Output2);
298 else {
299 $Output = $this->PageNotFound();
300 $this->BaseView->Title = T('Page not found');
301 $Output = $this->BaseView->ShowPage($Output);
302 }
303 }
304 echo($Output);
305 }
306
307 function RegisterPageBar($Name)
308 {
309 $this->Bars[$Name] = array();
310 }
311
312 function UnregisterPageBar($Name)
313 {
314 unset($this->Bars[$Name]);
315 }
316
317 function RegisterPageBarItem($BarName, $ItemName, $Callback)
318 {
319 $this->Bars[$BarName][$ItemName] = $Callback;
320 }
321}
322
323class BaseView extends View
324{
325 var $Title;
326
327 function ShowLocaleSelector()
328 {
329 //$Output .= ' <form action="?setlocale" method="get">';
330 $Output = ' <select onchange="window.location=this.value">';
331 foreach($this->System->LocaleManager->Available as $Locale)
332 {
333 $Remaining = substr($_SERVER["REQUEST_URI"], strlen($this->System->Config['Web']['BaseURL']));
334 if(substr($Remaining, 1, strlen($Locale['Code'].'/')) == $this->System->LocaleManager->LangCode.'/')
335 $Remaining = substr($Remaining, strlen('/'.$Locale['Code']));
336 if($Locale['Code'] == $this->System->LocaleManager->CurrentLocale->Texts->Code) $Selected = ' selected="selected"';
337 else $Selected = '';
338 $Remaining = $this->System->TranslateReverseURL($Remaining, $this->System->LocaleManager->LangCode);
339
340 $URL = $this->System->LinkLocale($Remaining, $Locale['Code']);
341 $Output .= '<option title="" value="'.$URL.'"'.$Selected.' onchange="this.form.submit()">'.$Locale['Title'].'</option>';
342 }
343 $Output .= '</select><noscript><span><input type="submit" value="Submit"/></span></noscript>';
344
345 return($Output);
346 }
347
348 function ShowTopBar()
349 {
350 $Output = '<div class="Menu">';
351 if(isset($this->System->User))
352 {
353 if(!$this->System->User->Licence(LICENCE_USER))
354 $Output .= '<div class="advert">'.$this->System->Config['Web']['Advertisement'].'</div>';
355 }
356 $Output .= '<span class="MenuItem"></span><span class="MenuItem2">';
357
358 // Show bars items
359 $Bar = '';
360 foreach($this->System->Bars['Top'] as $BarItem)
361 $Bar .= call_user_func($BarItem);
362 if(trim($Bar) != '') $Output .= $Bar;
363 else $Output .= '&nbsp;';
364
365 $Output .= $this->ShowLocaleSelector();
366 //$Output .= '</form>';
367 $Output .= '</span></div>';
368 return($Output);
369 }
370
371 function ShowLoginBox()
372 {
373 $Output = '';
374 if($this->System->User->Licence(LICENCE_USER))
375 {
376 // $Output .= 'Jste přihlášen jako: <b>'.$tUser->Id.'</b> <a href="index.php?Logout">Odhlásit</a>';
377 } else
378 {
379 $Output .= '<strong>'.T('Login').':</strong>
380 <form action="" method="post">
381 <table>
382 <tr>
383 <td><input type="text" name="LoginUser" size="13" /></td>
384 </tr>
385 <tr>
386 <td><input type="password" name="LoginPass" size="13" /></td>
387 </tr>
388 <tr>
389 <th><input type="submit" value="'.T('Do login').'" /></th>
390 </tr>
391 </table>
392 </form>';
393 }
394 return($Output);
395 }
396
397 function ShowSearchBox()
398 {
399 $Output = '<strong>'.T('Search').':</strong>'.
400 '<form action="'.$this->System->Link('/search/').'" method="get"><div>'.
401 '<table>'.
402 '<tr>'.
403 '<td><input type="text" name="text" size="13" /></td>'.
404 '</tr>'.
405 '<tr>'.
406 '<th><input type="submit" value="'.T('Do search').'" /></th>'.
407 '</tr>'.
408 '</table></div>'.
409 '</form>';
410 return($Output);
411 }
412
413 function ShowMainMenu()
414 {
415 $Output = '<strong>'.T('Menu').':</strong>'.
416 '<div class="verticalmenu"><ul>';
417 foreach($this->System->Menu as $MenuItem)
418 if(!isset($this->System->User) or $this->System->User->Licence($MenuItem['Permission']))
419 {
420 if(isset($MenuItem['Click'])) $OnClick = ' onclick="'.$MenuItem['Click'].'"';
421 else $OnClick = '';
422 if($MenuItem['Icon'] != '') $Icon = '<img src="'.$this->System->Link('/images/menu/'.$MenuItem['Icon']).'"/>';
423 else $Icon = '';
424 $Output .= '<li>'.$Icon.'<a class="verticalmenua" title="'.$MenuItem['Hint'].'" href="'.
425 $MenuItem['Link'].'"'.$OnClick.'>'.$MenuItem['Title'].'</a></li>';
426 }
427 $Output .= '</ul></div>';
428 return($Output);
429 }
430
431 function ShowTranslatedMenu()
432 {
433 $TranslationTree = $this->System->ModuleManager->Modules['Translation']->GetTranslationTree();
434
435 $Output = '<strong>'.T('Translate groups').':</strong><br /><div id="TranslationMenu">';
436 $DbResult = $this->System->Database->select('Group', '`Id`, `Name`', '1 ORDER BY `Name`');
437 while($Group = $DbResult->fetch_assoc())
438 {
439 $Groups[T($Group['Name'])] = $Group;
440 }
441 ksort($Groups);
442 foreach($Groups as $Group)
443 {
444 $Output .= '<div id="menuitem-group'.$Group['Id'].'" onmouseover="show(\'group'.$Group['Id'].'\')" onmouseout="hide(\'group'.$Group['Id'].'\')">'.
445 '<a href="'.$this->System->Link('/TranslationList.php?group='.$Group['Id'].
446 '&amp;action=filter').'">'.str_replace(' ','&nbsp;', T($Group['Name'])).'</a></div>'.
447 '<div id="group'.$Group['Id'].'" class="hidden-menu-item" onmouseover="show(\'group'.$Group['Id'].'\')" onmouseout="hide(\'group'.$Group['Id'].'\')">';
448 $Output .= '&nbsp;<a title="Zde můžete začít překládat" href="'.
449 $this->System->Link('/TranslationList.php?group='.$Group['Id'].'&amp;state=1&amp;user=0&amp;entry=&amp;text=').'">'.T('Untranslated').'</a><br />'.
450 '&nbsp;<a title="Přeložené texty, můžete zde hlasovat, nebo opravovat překlady" href="'.
451 $this->System->Link('/TranslationList.php?group='.$Group['Id'].'&amp;state=2&amp;user=0&amp;entry=&amp;text=').'">'.T('Translated').'</a><br />';
452 if(isset($this->System->User) and $this->System->User->Licence(LICENCE_USER))
453 {
454 $Output .= '&nbsp;<a title="'.T('Unfinished translations').'" href="'.$this->System->Link('/TranslationList.php?group='.$Group['Id'].'&amp;state=3').'">'.T('Unfinished').'</a><br />'.
455 '&nbsp;<a title="Všechny překlady, které jste přeložil" href="'.
456 $this->System->Link('/TranslationList.php?group='.$Group['Id'].'&amp;state=1&amp;user='.
457 $this->System->User->Id).'&amp;entry=&amp;text=">'.T('Own').'</a><br />';
458 }
459 $Output .= '&nbsp;<a title="'.T('Compose special filter').'" href="'.
460 $this->System->Link('/TranslationList.php?group='.$Group['Id'].'&amp;action=filter').
461 '">'.T('Filter').'</a><br />';
462 $Output .= '</div>';
463 }
464 $Output .= '</div>';
465 return($Output);
466 }
467
468 function ShowHeader()
469 {
470 $Output = ''.
471 '<!DOCTYPE html>'.
472 '<html>'.
473 '<head>'.
474 '<meta http-equiv="content-type" content="text/html; charset='.$this->System->Config['Web']['Charset'].'" />'.
475 '<meta name="keywords" content="'.$this->System->Config['Web']['Keywords'].'" />'.
476 '<meta name="description" content="'.$this->System->Config['Web']['Description'].'" />'.
477 '<meta name="robots" content="all" />'.
478 '<link rel="stylesheet" href="'.$this->System->Link('/style/style.css').'" type="text/css" media="all" />'.
479 '<script type="text/javascript" src="'.$this->System->Link('/style/global.js').'"></script>'.
480 '<link rel="shortcut icon" href="'.$this->System->Link('/images/favicon.ico').'" />';
481 $Output .= $this->System->ModuleManager->Modules['News']->ShowRSSHeader();
482 $Title = $this->System->Config['Web']['Title'];
483 if($this->Title != '') $Title = $this->Title.' - '.$Title;
484 $Output .= '<title>'.$Title.'</title>'.
485 '<script src="'.$this->System->Link('/style/respond.js').'"></script>'.
486 '</head><body>';
487
488 $Output .= $this->ShowTopBar();
489 $Output .= '<table class="page"><tr><td class="menu">';
490 $Output .= $this->ShowMainMenu();
491 $Output .= $this->System->ModuleManager->Modules['User']->ShowOnlineList();
492 $Output .= '<br />';
493 $Output .= $this->ShowSearchBox();
494
495 $Output .= '</td><td id="border-left"></td><td class="content">';
496 return($Output);
497 }
498
499 function ShowFooter()
500 {
501 global $ScriptStartTime, $Revision, $ReleaseTime, $Version;
502
503 $ScriptGenerateDuration = round(GetMicrotime() - $ScriptStartTime, 2);
504
505 $Output = '</td>';
506 if($this->System->ModuleManager->ModulePresent('Translation'))
507 {
508 $Output .= '<td class="menu2">';
509 $Output .= $this->ShowTranslatedMenu();
510 $Output .= '</td>';
511 }
512 $Output .= '</tr><tr>'.
513 '<td colspan="4" class="page-bottom">'.T('Version').': '.$Version.' '.T('Revision').': '.$Revision.' ('.HumanDate($ReleaseTime).')'.
514 ' &nbsp; <a href="http://svn.zdechov.net/trac/wowpreklad/browser/trunk">'.T('Source code').'</a> &nbsp; '.
515 '<a href="http://svn.zdechov.net/trac/wowpreklad/log/trunk?verbose=on">'.T('Changelog').'</a> &nbsp; '.
516 $this->System->Config['Web']['WebCounter'];
517
518 $Output .= '</td></tr>';
519 if($this->System->Config['Web']['ShowRuntimeInfo'] == true)
520 $Output .= '<tr><td colspan="3" style="text-align: center;">'.T('Generating duration').': '.
521 $ScriptGenerateDuration.' s / '.ini_get('max_execution_time').' s &nbsp;&nbsp; '.T('Used memory').': '.
522 HumanSize(memory_get_peak_usage(FALSE)).' / '.ini_get('memory_limit').'B &nbsp;&nbsp; <a href="http://validator.w3.org/check?uri='.
523 htmlentities('http://'.$_SERVER['HTTP_HOST'].GetRequestURI().'?'.$_SERVER['QUERY_STRING']).'">HTML validator</a></td></tr>';
524 $Output .= '</table>'.
525 '</body>'.
526 '</html>';
527 return($Output);
528 }
529
530 function ShowPage($Content)
531 {
532 $Output = $this->ShowHeader().$Content.$this->ShowFooter();
533 if($this->System->Config['Web']['FormatOutput'])
534 $Output = $this->FormatOutput($Output);
535 return($Output);
536 }
537
538 function FormatOutput($s)
539 {
540 $out = '';
541 $nn = 0;
542 $n = 0;
543 while($s != '')
544 {
545 $start = strpos($s, '<');
546 $end = strpos($s, '>');
547 if($start != 0)
548 {
549 $end = $start - 1;
550 $start = 0;
551 }
552 $line = trim(substr($s, $start, $end + 1));
553 if(strlen($line) > 0)
554 if($line[0] == '<')
555 {
556 if($s[$start + 1] == '/')
557 {
558 $n = $n - 2;
559 $nn = $n;
560 } else
561 {
562 if(strpos($line, ' ')) $cmd = substr($line, 1, strpos($line, ' ') - 1);
563 else $cmd = substr($line, 1, strlen($line) - 2);
564 //echo('['.$cmd.']');
565 if(strpos($s, '</'.$cmd.'>')) $n = $n + 2;
566 }
567 }// else $line = '['.$line.']';
568 //if($line != '') echo(htmlspecialchars(str_repeat(' ',$nn).$line."\n"));
569 if($nn < 0) $nn = 0;
570 if($line != '') $out .= (str_repeat(' ', $nn).$line."\n");
571 $s = substr($s, $end + 1, strlen($s));
572 $nn = $n;
573 }
574 return($out);
575 }
576}
Note: See TracBrowser for help on using the repository browser.