EGroupware /
egroupware
| 1 | <?php |
||||||
| 2 | /** |
||||||
| 3 | * EGroupware API - framework baseclass |
||||||
| 4 | * |
||||||
| 5 | * @link http://www.egroupware.org |
||||||
| 6 | * @author Ralf Becker <RalfBecker-AT-outdoor-training.de> rewrite in 12/2006 |
||||||
| 7 | * @author Pim Snel <[email protected]> author of the idots template set |
||||||
| 8 | * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License |
||||||
| 9 | * @package api |
||||||
| 10 | * @subpackage framework |
||||||
| 11 | * @access public |
||||||
| 12 | * @version $Id$ |
||||||
| 13 | */ |
||||||
| 14 | |||||||
| 15 | namespace EGroupware\Api; |
||||||
| 16 | |||||||
| 17 | /** |
||||||
| 18 | * Framework: virtual base class for all template sets |
||||||
| 19 | * |
||||||
| 20 | * This class creates / renders the eGW framework: |
||||||
| 21 | * a) Html header |
||||||
| 22 | * b) navbar |
||||||
| 23 | * c) sidebox menu |
||||||
| 24 | * d) main application area |
||||||
| 25 | * e) footer |
||||||
| 26 | * It replaces several methods in the common class and the diverse templates. |
||||||
| 27 | * |
||||||
| 28 | * Existing apps either set $GLOBALS['egw_info']['flags']['noheader'] and call common::egw_header() and |
||||||
| 29 | * (if $GLOBALS['egw_info']['flags']['nonavbar'] is true) parse_navbar() or it's done by the header.inc.php include. |
||||||
| 30 | * The app's hook_sidebox then calls the public function display_sidebox(). |
||||||
| 31 | * And the app calls common::egw_footer(). |
||||||
| 32 | * |
||||||
| 33 | * This are the authors (and their copyrights) of the original egw_header, egw_footer methods of the common class: |
||||||
| 34 | * This file written by Dan Kuykendall <[email protected]> |
||||||
| 35 | * and Joseph Engo <[email protected]> |
||||||
| 36 | * and Mark Peters <[email protected]> |
||||||
| 37 | * and Lars Kneschke <[email protected]> |
||||||
| 38 | * Copyright (C) 2000, 2001 Dan Kuykendall |
||||||
| 39 | * Copyright (C) 2003 Lars Kneschke |
||||||
| 40 | */ |
||||||
| 41 | abstract class Framework extends Framework\Extra |
||||||
| 42 | { |
||||||
| 43 | /** |
||||||
| 44 | * Name of the template set, eg. 'idots' |
||||||
| 45 | * |
||||||
| 46 | * @var string |
||||||
| 47 | */ |
||||||
| 48 | var $template; |
||||||
| 49 | |||||||
| 50 | /** |
||||||
| 51 | * Path relative to EGW_SERVER_ROOT for the template directory |
||||||
| 52 | * |
||||||
| 53 | * @var string |
||||||
| 54 | */ |
||||||
| 55 | var $template_dir; |
||||||
| 56 | |||||||
| 57 | /** |
||||||
| 58 | * Application specific template directories to try in given order for CSS |
||||||
| 59 | * |
||||||
| 60 | * @var string |
||||||
| 61 | */ |
||||||
| 62 | var $template_dirs = array(); |
||||||
| 63 | |||||||
| 64 | /** |
||||||
| 65 | * true if $this->header() was called |
||||||
| 66 | * |
||||||
| 67 | * @var boolean |
||||||
| 68 | */ |
||||||
| 69 | static $header_done = false; |
||||||
| 70 | /** |
||||||
| 71 | * true if $this->navbar() was called |
||||||
| 72 | * |
||||||
| 73 | * @var boolean |
||||||
| 74 | */ |
||||||
| 75 | static $navbar_done = false; |
||||||
| 76 | |||||||
| 77 | /** |
||||||
| 78 | * Constructor |
||||||
| 79 | * |
||||||
| 80 | * The constructor instanciates the class in $GLOBALS['egw']->framework, from where it should be used |
||||||
| 81 | */ |
||||||
| 82 | function __construct($template) |
||||||
| 83 | { |
||||||
| 84 | $this->template = $template; |
||||||
| 85 | |||||||
| 86 | if (!isset($GLOBALS['egw']->framework)) |
||||||
| 87 | { |
||||||
| 88 | $GLOBALS['egw']->framework = $this; |
||||||
| 89 | } |
||||||
| 90 | $this->template_dir = '/api/templates/'.$template; |
||||||
| 91 | |||||||
| 92 | $this->template_dirs[] = $template; |
||||||
| 93 | $this->template_dirs[] = 'default'; |
||||||
| 94 | } |
||||||
| 95 | |||||||
| 96 | /** |
||||||
| 97 | * Factory method to instanciate framework object |
||||||
| 98 | * |
||||||
| 99 | * @return self |
||||||
| 100 | */ |
||||||
| 101 | public static function factory() |
||||||
| 102 | { |
||||||
| 103 | // we prefer Pixelegg template, if it is available |
||||||
| 104 | if (file_exists(EGW_SERVER_ROOT.'/pixelegg') && |
||||||
|
0 ignored issues
–
show
introduced
by
Loading history...
|
|||||||
| 105 | (empty($GLOBALS['egw_info']['flags']['deny_mobile']) && Header\UserAgent::mobile() || |
||||||
| 106 | $GLOBALS['egw_info']['user']['preferences']['common']['theme'] == 'mobile' || |
||||||
| 107 | empty($GLOBALS['egw_info']['server']['template_set'])) || |
||||||
| 108 | // change old idots and jerryr to our standard template (pixelegg) |
||||||
| 109 | in_array($GLOBALS['egw_info']['server']['template_set'], array('idots', 'jerryr'))) |
||||||
| 110 | { |
||||||
| 111 | $GLOBALS['egw_info']['server']['template_set'] = 'pixelegg'; |
||||||
| 112 | } |
||||||
| 113 | // then jdots aka Stylite template |
||||||
| 114 | if (file_exists(EGW_SERVER_ROOT.'/jdots') && empty($GLOBALS['egw_info']['server']['template_set'])) |
||||||
| 115 | { |
||||||
| 116 | $GLOBALS['egw_info']['server']['template_set'] = 'jdots'; |
||||||
| 117 | } |
||||||
| 118 | // eg. "default" is only used for login at the moment |
||||||
| 119 | if (!class_exists($class=$GLOBALS['egw_info']['server']['template_set'].'_framework')) |
||||||
| 120 | { |
||||||
| 121 | $class = __CLASS__.'\\Minimal'; |
||||||
| 122 | } |
||||||
| 123 | return new $class($GLOBALS['egw_info']['server']['template_set']); |
||||||
| 124 | } |
||||||
| 125 | |||||||
| 126 | /** |
||||||
| 127 | * Check if we have a valid and installed EGroupware template |
||||||
| 128 | * |
||||||
| 129 | * Templates are installed in their own directory and contain a setup/setup.inc.php file |
||||||
| 130 | * |
||||||
| 131 | * @param string $template |
||||||
| 132 | * @return boolean |
||||||
| 133 | */ |
||||||
| 134 | public static function validTemplate($template) |
||||||
| 135 | { |
||||||
| 136 | return preg_match('/^[A-Z0-9_-]+$/i', $template) && |
||||||
| 137 | file_exists(EGW_SERVER_ROOT.'/'.$template) && |
||||||
| 138 | file_exists($file=EGW_SERVER_ROOT.'/'.$template.'/setup/setup.inc.php') && |
||||||
| 139 | include_once($file) && !empty($GLOBALS['egw_info']['template'][$template]); |
||||||
| 140 | } |
||||||
| 141 | |||||||
| 142 | /** |
||||||
| 143 | * Send HTTP headers: Content-Type and Content-Security-Policy |
||||||
| 144 | */ |
||||||
| 145 | public function send_headers() |
||||||
| 146 | { |
||||||
| 147 | // add a content-type header to overwrite an existing default charset in apache (AddDefaultCharset directiv) |
||||||
| 148 | header('Content-type: text/html; charset='.Translation::charset()); |
||||||
| 149 | |||||||
| 150 | Header\ContentSecurityPolicy::send(); |
||||||
| 151 | |||||||
| 152 | // allow client-side to detect first load aka just logged in |
||||||
| 153 | $reload_count =& Cache::getSession(__CLASS__, 'framework-reload'); |
||||||
| 154 | self::$extra['framework-reload'] = (int)(bool)$reload_count++; |
||||||
| 155 | } |
||||||
| 156 | |||||||
| 157 | /** |
||||||
| 158 | * Constructor for static variables |
||||||
| 159 | */ |
||||||
| 160 | public static function init_static() |
||||||
| 161 | { |
||||||
| 162 | self::$js_include_mgr = new Framework\IncludeMgr(array( |
||||||
| 163 | // We need LABjs, but putting it through Framework\IncludeMgr causes it to re-load itself |
||||||
| 164 | //'/api/js/labjs/LAB.src.js', |
||||||
| 165 | |||||||
| 166 | // allways load jquery (not -ui) first |
||||||
| 167 | '/vendor/bower-asset/jquery/dist/jquery.js', |
||||||
| 168 | '/api/js/jquery/jquery.noconflict.js', |
||||||
| 169 | // always include javascript helper functions |
||||||
| 170 | '/api/js/jsapi/jsapi.js', |
||||||
| 171 | '/api/js/jsapi/egw.js', |
||||||
| 172 | )); |
||||||
| 173 | } |
||||||
| 174 | |||||||
| 175 | /** |
||||||
| 176 | * Link url generator |
||||||
| 177 | * |
||||||
| 178 | * @param string $url The url the link is for |
||||||
| 179 | * @param string|array $extravars Extra params to be passed to the url |
||||||
| 180 | * @param string $link_app =null if appname or true, some templates generate a special link-handler url |
||||||
| 181 | * @return string The full url after processing |
||||||
| 182 | */ |
||||||
| 183 | static function link($url, $extravars = '', $link_app=null) |
||||||
| 184 | { |
||||||
| 185 | unset($link_app); // not used by required by function signature |
||||||
| 186 | return $GLOBALS['egw']->session->link($url, $extravars); |
||||||
| 187 | } |
||||||
| 188 | |||||||
| 189 | /** |
||||||
| 190 | * Get a full / externally usable URL from an EGroupware link |
||||||
| 191 | * |
||||||
| 192 | * @param string $link |
||||||
| 193 | */ |
||||||
| 194 | static function getUrl($link) |
||||||
| 195 | { |
||||||
| 196 | return Header\Http::fullUrl($link); |
||||||
| 197 | } |
||||||
| 198 | |||||||
| 199 | /** |
||||||
| 200 | * Handles redirects under iis and apache, it does NOT return (calls exit) |
||||||
| 201 | * |
||||||
| 202 | * This function handles redirects under iis and apache it assumes that $phpgw->link() has already been called |
||||||
| 203 | * |
||||||
| 204 | * @param string $url url to redirect to |
||||||
| 205 | * @param string $link_app =null appname to redirect for, default currentapp |
||||||
| 206 | */ |
||||||
| 207 | static function redirect($url, $link_app=null) |
||||||
| 208 | { |
||||||
| 209 | // Determines whether the current output buffer should be flushed |
||||||
| 210 | $do_flush = true; |
||||||
| 211 | |||||||
| 212 | if (Json\Response::isJSONResponse() || Json\Request::isJSONRequest()) |
||||||
| 213 | { |
||||||
| 214 | Json\Response::get()->redirect($url, false, $link_app); |
||||||
| 215 | |||||||
| 216 | // check if we have a message, in which case send it along too |
||||||
| 217 | $extra = self::get_extra(); |
||||||
| 218 | if ($extra['message']) |
||||||
| 219 | { |
||||||
| 220 | Json\Response::get()->apply('egw.message', $extra['message']); |
||||||
| 221 | } |
||||||
| 222 | |||||||
| 223 | // If we are in a json request, we should not flush the current output! |
||||||
| 224 | $do_flush = false; |
||||||
| 225 | } |
||||||
| 226 | else |
||||||
| 227 | { |
||||||
| 228 | $file = $line = null; |
||||||
| 229 | if (headers_sent($file,$line)) |
||||||
| 230 | { |
||||||
| 231 | throw new Exception\AssertionFailed(__METHOD__."('".htmlspecialchars($url)."') can NOT redirect, output already started at $file line $line!"); |
||||||
| 232 | } |
||||||
| 233 | if ($GLOBALS['egw']->framework instanceof Framework\Ajax && !empty($link_app)) |
||||||
| 234 | { |
||||||
| 235 | self::set_extra('egw', 'redirect', array($url, $link_app)); |
||||||
| 236 | $GLOBALS['egw']->framework->render(''); |
||||||
| 237 | } |
||||||
| 238 | else |
||||||
| 239 | { |
||||||
| 240 | Header("Location: $url"); |
||||||
| 241 | print("\n\n"); |
||||||
| 242 | } |
||||||
| 243 | } |
||||||
| 244 | |||||||
| 245 | if ($do_flush) |
||||||
| 246 | { |
||||||
| 247 | @ob_flush(); flush(); |
||||||
|
0 ignored issues
–
show
Are you sure the usage of
ob_flush() is correct as it seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. Loading history...
It seems like you do not handle an error condition for
ob_flush(). This can introduce security issues, and is generally not recommended.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
|
|||||||
| 248 | } |
||||||
| 249 | |||||||
| 250 | // commit session (if existing), to fix timing problems sometimes preventing session creation ("Your session can not be verified") |
||||||
| 251 | if (isset($GLOBALS['egw']->session)) $GLOBALS['egw']->session->commit_session(); |
||||||
| 252 | |||||||
| 253 | exit; |
||||||
|
0 ignored issues
–
show
|
|||||||
| 254 | } |
||||||
| 255 | |||||||
| 256 | /** |
||||||
| 257 | * Redirects direct to a generated link |
||||||
| 258 | * |
||||||
| 259 | * @param string $url The url the link is for |
||||||
| 260 | * @param string|array $extravars Extra params to be passed to the url |
||||||
| 261 | * @param string $link_app =null if appname or true, some templates generate a special link-handler url |
||||||
| 262 | * @return string The full url after processing |
||||||
| 263 | */ |
||||||
| 264 | static function redirect_link($url, $extravars='', $link_app=null) |
||||||
| 265 | { |
||||||
| 266 | self::redirect(self::link($url, $extravars), $link_app); |
||||||
| 267 | } |
||||||
| 268 | |||||||
| 269 | /** |
||||||
| 270 | * Renders an applicaton page with the complete eGW framework (header, navigation and menu) |
||||||
| 271 | * |
||||||
| 272 | * This is the (new) prefered way to render a page in eGW! |
||||||
| 273 | * |
||||||
| 274 | * @param string $content Html of the main application area |
||||||
| 275 | * @param string $app_header =null application header, default what's set in $GLOBALS['egw_info']['flags']['app_header'] |
||||||
| 276 | * @param string $navbar =null show the navigation, default !$GLOBALS['egw_info']['flags']['nonavbar'], false gives a typical popu |
||||||
| 277 | * |
||||||
| 278 | */ |
||||||
| 279 | function render($content,$app_header=null,$navbar=null) |
||||||
| 280 | { |
||||||
| 281 | if (!is_null($app_header)) $GLOBALS['egw_info']['flags']['app_header'] = $app_header; |
||||||
| 282 | if (!is_null($navbar)) $GLOBALS['egw_info']['flags']['nonavbar'] = !$navbar; |
||||||
| 283 | |||||||
| 284 | echo $this->header(); |
||||||
| 285 | |||||||
| 286 | if (!isset($GLOBALS['egw_info']['flags']['nonavbar']) || !$GLOBALS['egw_info']['flags']['nonavbar']) |
||||||
| 287 | { |
||||||
| 288 | echo $this->navbar(); |
||||||
| 289 | } |
||||||
| 290 | echo $content; |
||||||
| 291 | |||||||
| 292 | echo $this->footer(); |
||||||
| 293 | } |
||||||
| 294 | |||||||
| 295 | /** |
||||||
| 296 | * Returns the html-header incl. the opening body tag |
||||||
| 297 | * |
||||||
| 298 | * @return string with Html |
||||||
| 299 | */ |
||||||
| 300 | abstract function header(array $extra=array()); |
||||||
| 301 | |||||||
| 302 | /** |
||||||
| 303 | * Returns the Html from the body-tag til the main application area (incl. opening div tag) |
||||||
| 304 | * |
||||||
| 305 | * If header has NOT been called, also return header content! |
||||||
| 306 | * No need to manually call header, this allows to postpone header so navbar / sidebox can include JS or CSS. |
||||||
| 307 | * |
||||||
| 308 | * @return string with Html |
||||||
| 309 | */ |
||||||
| 310 | abstract function navbar(); |
||||||
| 311 | |||||||
| 312 | /** |
||||||
| 313 | * Return true if we are rendering the top-level EGroupware window |
||||||
| 314 | * |
||||||
| 315 | * A top-level EGroupware window has a navbar: eg. no popup and for a framed template (jdots) only frameset itself |
||||||
| 316 | * |
||||||
| 317 | * @return boolean $consider_navbar_not_yet_called_as_true=true |
||||||
| 318 | * @return boolean |
||||||
| 319 | */ |
||||||
| 320 | abstract function isTop($consider_navbar_not_yet_called_as_true=true); |
||||||
| 321 | |||||||
| 322 | /** |
||||||
| 323 | * Returns the content of one sidebox |
||||||
| 324 | * |
||||||
| 325 | * @param string $appname |
||||||
| 326 | * @param string $menu_title |
||||||
| 327 | * @param array $file |
||||||
| 328 | * @param string $type =null 'admin', 'preferences', 'favorites', ... |
||||||
| 329 | */ |
||||||
| 330 | abstract function sidebox($appname,$menu_title,$file,$type=null); |
||||||
| 331 | |||||||
| 332 | /** |
||||||
| 333 | * Returns the Html from the closing div of the main application area to the closing html-tag |
||||||
| 334 | * |
||||||
| 335 | * @return string |
||||||
| 336 | */ |
||||||
| 337 | abstract function footer(); |
||||||
| 338 | |||||||
| 339 | /** |
||||||
| 340 | * Displays the login screen |
||||||
| 341 | * |
||||||
| 342 | * @param string $extra_vars for login url |
||||||
| 343 | * @param string $change_passwd =null string with message to render input fields for password change |
||||||
| 344 | */ |
||||||
| 345 | function login_screen($extra_vars, $change_passwd=null) |
||||||
| 346 | { |
||||||
| 347 | (new Framework\Login($this))->screen($extra_vars, $change_passwd); |
||||||
| 348 | } |
||||||
| 349 | |||||||
| 350 | /** |
||||||
| 351 | * displays a login denied message |
||||||
| 352 | */ |
||||||
| 353 | function denylogin_screen() |
||||||
| 354 | { |
||||||
| 355 | (new Framework\Login($this))->deny_screen(); |
||||||
|
0 ignored issues
–
show
The method
deny_screen() does not exist on EGroupware\Api\Framework\Login. Did you maybe mean screen()?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. Loading history...
|
|||||||
| 356 | } |
||||||
| 357 | |||||||
| 358 | /** |
||||||
| 359 | * Calculate page-generation- and session-restore times |
||||||
| 360 | * |
||||||
| 361 | * @return array values for keys 'page_generation_time' and 'session_restore_time', if display is an |
||||||
| 362 | */ |
||||||
| 363 | public static function get_page_generation_time() |
||||||
| 364 | { |
||||||
| 365 | $times = array( |
||||||
| 366 | 'page_generation_time' => sprintf('%4.2lf', microtime(true) - $GLOBALS['egw_info']['flags']['page_start_time']), |
||||||
| 367 | ); |
||||||
| 368 | if ($GLOBALS['egw_info']['flags']['session_restore_time']) |
||||||
| 369 | { |
||||||
| 370 | $times['session_restore_time'] = sprintf('%4.2lf', $GLOBALS['egw_info']['flags']['session_restore_time']); |
||||||
| 371 | } |
||||||
| 372 | return $times; |
||||||
| 373 | } |
||||||
| 374 | |||||||
| 375 | /** |
||||||
| 376 | * Get footer as array to eg. set as vars for a template (from idots' head.inc.php) |
||||||
| 377 | * |
||||||
| 378 | * @return array |
||||||
| 379 | */ |
||||||
| 380 | public function _get_footer() |
||||||
| 381 | { |
||||||
| 382 | $var = Array( |
||||||
| 383 | 'img_root' => $GLOBALS['egw_info']['server']['webserver_url'] . $this->template_dir.'/images', |
||||||
| 384 | 'version' => $GLOBALS['egw_info']['server']['versions']['api'] |
||||||
| 385 | ); |
||||||
| 386 | $var['page_generation_time'] = ''; |
||||||
| 387 | if($GLOBALS['egw_info']['user']['preferences']['common']['show_generation_time']) |
||||||
| 388 | { |
||||||
| 389 | $times = self::get_page_generation_time(); |
||||||
| 390 | |||||||
| 391 | $var['page_generation_time'] = '<div class="pageGenTime" id="divGenTime_'.$GLOBALS['egw_info']['flags']['currentapp'].'"><span>'. |
||||||
| 392 | lang('Page was generated in %1 seconds', $times['page_generation_time']); |
||||||
|
0 ignored issues
–
show
The call to
lang() has too many arguments starting with $times['page_generation_time'].
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. Loading history...
|
|||||||
| 393 | |||||||
| 394 | if (isset($times['session_restore_time'])) |
||||||
| 395 | { |
||||||
| 396 | $var['page_generation_time'] .= ' '.lang('(session restored in %1 seconds)', |
||||||
| 397 | $times['session_restore_time']); |
||||||
| 398 | } |
||||||
| 399 | $var['page_generation_time'] .= '</span></div>'; |
||||||
| 400 | } |
||||||
| 401 | if (empty($GLOBALS['egw_info']['server']['versions']['maintenance_release'])) |
||||||
| 402 | { |
||||||
| 403 | $GLOBALS['egw_info']['server']['versions']['maintenance_release'] = self::api_version(); |
||||||
| 404 | } |
||||||
| 405 | $var['powered_by'] = '<a href="http://www.egroupware.org/" class="powered_by" target="_blank">'. |
||||||
| 406 | lang('Powered by').' EGroupware '. |
||||||
| 407 | $GLOBALS['egw_info']['server']['versions']['maintenance_release'].'</a>'; |
||||||
| 408 | |||||||
| 409 | return $var; |
||||||
| 410 | } |
||||||
| 411 | |||||||
| 412 | /** |
||||||
| 413 | * Body tags for onLoad, onUnload and onResize |
||||||
| 414 | * |
||||||
| 415 | * @deprecated since 14.1 use app.js et2_ready method instead to execute code or bind a handler (CSP will stop onXXX attributes!) |
||||||
| 416 | * @var array |
||||||
| 417 | */ |
||||||
| 418 | protected static $body_tags = array(); |
||||||
| 419 | |||||||
| 420 | /** |
||||||
| 421 | * Adds on(Un)Load= attributes to the body tag of a page |
||||||
| 422 | * |
||||||
| 423 | * Can only be set via egw_framework::set_on* methods. |
||||||
| 424 | * |
||||||
| 425 | * @deprecated since 14.1 use app.js et2_ready method instead to execute code or bind a handler (CSP will stop onXXX attributes!) |
||||||
| 426 | * @returns string the attributes to be used |
||||||
| 427 | */ |
||||||
| 428 | static public function _get_body_attribs() |
||||||
| 429 | { |
||||||
| 430 | $js = ''; |
||||||
| 431 | foreach(self::$body_tags as $what => $data) |
||||||
| 432 | { |
||||||
| 433 | if (!empty($data)) |
||||||
| 434 | { |
||||||
| 435 | if($what == 'onLoad') |
||||||
| 436 | { |
||||||
| 437 | $js .= 'onLoad="egw_LAB.wait(function() {'. htmlspecialchars($data).'})"'; |
||||||
| 438 | continue; |
||||||
| 439 | } |
||||||
| 440 | $js .= ' '.$what.'="' . htmlspecialchars($data) . '"'; |
||||||
| 441 | } |
||||||
| 442 | } |
||||||
| 443 | return $js; |
||||||
| 444 | } |
||||||
| 445 | |||||||
| 446 | /** |
||||||
| 447 | * Get header as array to eg. set as vars for a template (from idots' head.inc.php) |
||||||
| 448 | * |
||||||
| 449 | * @param array $extra =array() extra attributes passed as data-attribute to egw.js |
||||||
| 450 | * @return array |
||||||
| 451 | */ |
||||||
| 452 | protected function _get_header(array $extra=array()) |
||||||
| 453 | { |
||||||
| 454 | // display password expires in N days message once per session |
||||||
| 455 | $message = null; |
||||||
| 456 | if ($GLOBALS['egw_info']['flags']['currentapp'] != 'login' && |
||||||
| 457 | Auth::check_password_change($message) !== true) |
||||||
| 458 | { |
||||||
| 459 | self::message($message, 'info'); |
||||||
| 460 | } |
||||||
| 461 | |||||||
| 462 | // get used language code (with a little xss check, if someone tries to sneak something in) |
||||||
| 463 | if (preg_match('/^[a-z]{2}(-[a-z]{2})?$/',$GLOBALS['egw_info']['user']['preferences']['common']['lang'])) |
||||||
| 464 | { |
||||||
| 465 | $lang_code = $GLOBALS['egw_info']['user']['preferences']['common']['lang']; |
||||||
| 466 | } |
||||||
| 467 | // IE specific fixes |
||||||
| 468 | if (Header\UserAgent::type() == 'msie') |
||||||
| 469 | { |
||||||
| 470 | // tell IE to use it's own mode, not old compatibility modes (set eg. via group policy for all intranet sites) |
||||||
| 471 | // has to be before any other header tags, but meta and title!!! |
||||||
| 472 | $pngfix = '<meta http-equiv="X-UA-Compatible" content="IE=edge" />'."\n"; |
||||||
| 473 | } |
||||||
| 474 | |||||||
| 475 | $app = $GLOBALS['egw_info']['flags']['currentapp']; |
||||||
| 476 | $app_title = isset($GLOBALS['egw_info']['apps'][$app]) ? $GLOBALS['egw_info']['apps'][$app]['title'] : lang($app); |
||||||
| 477 | $app_header = $GLOBALS['egw_info']['flags']['app_header'] ? $GLOBALS['egw_info']['flags']['app_header'] : $app_title; |
||||||
| 478 | $site_title = strip_tags($GLOBALS['egw_info']['server']['site_title'].' ['.($app_header ? $app_header : $app_title).']'); |
||||||
| 479 | |||||||
| 480 | // send appheader to clientside |
||||||
| 481 | $extra['app-header'] = $app_header; |
||||||
| 482 | |||||||
| 483 | if($GLOBALS['egw_info']['flags']['currentapp'] != 'wiki') $robots ='<meta name="robots" content="none" />'; |
||||||
| 484 | |||||||
| 485 | $var['favicon_file'] = self::get_login_logo_or_bg_url('favicon_file', 'favicon.ico'); |
||||||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||||
| 486 | |||||||
| 487 | if ($GLOBALS['egw_info']['flags']['include_wz_tooltip'] && |
||||||
| 488 | file_exists(EGW_SERVER_ROOT.($wz_tooltip = '/phpgwapi/js/wz_tooltip/wz_tooltip.js'))) |
||||||
| 489 | { |
||||||
| 490 | $include_wz_tooltip = '<script src="'.$GLOBALS['egw_info']['server']['webserver_url']. |
||||||
| 491 | $wz_tooltip.'?'.filemtime(EGW_SERVER_ROOT.$wz_tooltip).'" type="text/javascript"></script>'; |
||||||
| 492 | } |
||||||
| 493 | return $this->_get_css()+array( |
||||||
| 494 | 'img_icon' => $var['favicon_file'], |
||||||
| 495 | 'img_shortcut' => $var['favicon_file'], |
||||||
| 496 | 'pngfix' => $pngfix, |
||||||
| 497 | 'lang_code' => $lang_code, |
||||||
| 498 | 'charset' => Translation::charset(), |
||||||
| 499 | 'website_title' => $site_title, |
||||||
| 500 | 'body_tags' => self::_get_body_attribs(), |
||||||
|
0 ignored issues
–
show
The function
EGroupware\Api\Framework::_get_body_attribs() has been deprecated: since 14.1 use app.js et2_ready method instead to execute code or bind a handler (CSP will stop onXXX attributes!)
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. Loading history...
|
|||||||
| 501 | 'java_script' => self::_get_js($extra), |
||||||
| 502 | 'meta_robots' => $robots, |
||||||
| 503 | 'dir_code' => lang('language_direction_rtl') != 'rtl' ? '' : ' dir="rtl"', |
||||||
| 504 | 'include_wz_tooltip'=> $include_wz_tooltip, |
||||||
| 505 | 'webserver_url' => $GLOBALS['egw_info']['server']['webserver_url'], |
||||||
| 506 | ); |
||||||
| 507 | } |
||||||
| 508 | |||||||
| 509 | /** |
||||||
| 510 | * Get navbar as array to eg. set as vars for a template (from idots' navbar.inc.php) |
||||||
| 511 | * |
||||||
| 512 | * @param array $apps navbar apps from _get_navbar_apps |
||||||
| 513 | * @return array |
||||||
| 514 | */ |
||||||
| 515 | protected function _get_navbar($apps) |
||||||
| 516 | { |
||||||
| 517 | $var['img_root'] = $GLOBALS['egw_info']['server']['webserver_url'] . '/phpgwapi/templates/'.$this->template.'/images'; |
||||||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||||
| 518 | |||||||
| 519 | if(isset($GLOBALS['egw_info']['flags']['app_header'])) |
||||||
| 520 | { |
||||||
| 521 | $var['current_app_title'] = $GLOBALS['egw_info']['flags']['app_header']; |
||||||
| 522 | } |
||||||
| 523 | else |
||||||
| 524 | { |
||||||
| 525 | $var['current_app_title']=$apps[$GLOBALS['egw_info']['flags']['currentapp']]['title']; |
||||||
| 526 | } |
||||||
| 527 | $var['currentapp'] = $GLOBALS['egw_info']['flags']['currentapp']; |
||||||
| 528 | |||||||
| 529 | // quick add selectbox |
||||||
| 530 | $var['quick_add'] = $this->_get_quick_add(); |
||||||
| 531 | |||||||
| 532 | $var['user_info'] = $this->_user_time_info(); |
||||||
|
0 ignored issues
–
show
Are you sure the assignment to
$var['user_info'] is correct as $this->_user_time_info() targeting EGroupware\Api\Framework::_user_time_info() seems to always return null.
This check looks for function or method calls that always return null and whose return value is assigned to a variable. class A
{
function getObject()
{
return null;
}
}
$a = new A();
$object = $a->getObject();
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. Loading history...
|
|||||||
| 533 | |||||||
| 534 | if($GLOBALS['egw_info']['user']['account_lastpwd_change'] == 0) |
||||||
| 535 | { |
||||||
| 536 | $api_messages = lang('You are required to change your password during your first login').'<br />'. |
||||||
|
0 ignored issues
–
show
|
|||||||
| 537 | lang('Click this image on the navbar: %1','<img src="'.Image::find('preferences','navbar.gif').'">'); |
||||||
|
0 ignored issues
–
show
The call to
lang() has too many arguments starting with '<img src="' . EGroupwar...', 'navbar.gif') . '">'.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. Loading history...
|
|||||||
| 538 | } |
||||||
| 539 | elseif($GLOBALS['egw_info']['server']['change_pwd_every_x_days'] && $GLOBALS['egw_info']['user']['account_lastpwd_change'] < time() - (86400*$GLOBALS['egw_info']['server']['change_pwd_every_x_days'])) |
||||||
| 540 | { |
||||||
| 541 | $api_messages = lang('it has been more then %1 days since you changed your password',$GLOBALS['egw_info']['server']['change_pwd_every_x_days']); |
||||||
| 542 | } |
||||||
| 543 | |||||||
| 544 | $var['logo_header'] = $var['logo_file'] = self::get_login_logo_or_bg_url('login_logo_file', 'logo'); |
||||||
| 545 | |||||||
| 546 | if ($GLOBALS['egw_info']['server']['login_logo_header']) |
||||||
| 547 | { |
||||||
| 548 | $var['logo_header'] = self::get_login_logo_or_bg_url('login_logo_header', 'logo'); |
||||||
| 549 | } |
||||||
| 550 | |||||||
| 551 | $var['logo_url'] = $GLOBALS['egw_info']['server']['login_logo_url']?$GLOBALS['egw_info']['server']['login_logo_url']:'http://www.egroupware.org'; |
||||||
| 552 | |||||||
| 553 | if (substr($var['logo_url'],0,4) != 'http') |
||||||
| 554 | { |
||||||
| 555 | $var['logo_url'] = 'http://'.$var['logo_url']; |
||||||
| 556 | } |
||||||
| 557 | $var['logo_title'] = $GLOBALS['egw_info']['server']['login_logo_title']?$GLOBALS['egw_info']['server']['login_logo_title']:'www.egroupware.org'; |
||||||
| 558 | |||||||
| 559 | return $var; |
||||||
| 560 | } |
||||||
| 561 | |||||||
| 562 | /** |
||||||
| 563 | * Get login logo or background image base on requested config type |
||||||
| 564 | * |
||||||
| 565 | * @param type $type config type to fetch. e.g.: "login_logo_file" |
||||||
|
0 ignored issues
–
show
The type
EGroupware\Api\type was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths Loading history...
|
|||||||
| 566 | * @param type $find_type type of image to search on as alternative option. e.g.: "logo" |
||||||
| 567 | * |
||||||
| 568 | * @return string returns full url of the image |
||||||
| 569 | */ |
||||||
| 570 | static function get_login_logo_or_bg_url ($type, $find_type) |
||||||
| 571 | { |
||||||
| 572 | $url = is_array($GLOBALS['egw_info']['server'][$type]) ? |
||||||
| 573 | $GLOBALS['egw_info']['server'][$type][0] : |
||||||
| 574 | $GLOBALS['egw_info']['server'][$type]; |
||||||
| 575 | |||||||
| 576 | if (substr($url, 0, 4) == 'http' || |
||||||
| 577 | $url[0] == '/') |
||||||
| 578 | { |
||||||
| 579 | return $url; |
||||||
| 580 | } |
||||||
| 581 | else |
||||||
| 582 | { |
||||||
| 583 | return Image::find('api',$url ? $url : $find_type, '', null); |
||||||
| 584 | } |
||||||
| 585 | } |
||||||
| 586 | |||||||
| 587 | /** |
||||||
| 588 | * Returns Html with user and time |
||||||
| 589 | * |
||||||
| 590 | * @return void |
||||||
| 591 | */ |
||||||
| 592 | protected static function _user_time_info() |
||||||
| 593 | { |
||||||
| 594 | $now = new DateTime(); |
||||||
| 595 | $user_info = '<span>'.lang($now->format('l')) . ' ' . $now->format(true).'</span>'; |
||||||
| 596 | |||||||
| 597 | $user_tzs = DateTime::getUserTimezones(); |
||||||
| 598 | if (count($user_tzs) > 1) |
||||||
| 599 | { |
||||||
| 600 | $tz = $GLOBALS['egw_info']['user']['preferences']['common']['tz']; |
||||||
| 601 | $user_info .= Html::form(Html::select('tz',$tz,$user_tzs,true),array(), |
||||||
| 602 | '/index.php','','tz_selection',' style="display: inline;"','GET'); |
||||||
| 603 | } |
||||||
| 604 | return $user_info; |
||||||
| 605 | } |
||||||
| 606 | |||||||
| 607 | /** |
||||||
| 608 | * Returns user avatar menu |
||||||
| 609 | * |
||||||
| 610 | * @return string |
||||||
| 611 | */ |
||||||
| 612 | protected static function _user_avatar_menu() |
||||||
| 613 | { |
||||||
| 614 | $stat = array_pop(Hooks::process('framework_avatar_stat')); |
||||||
|
0 ignored issues
–
show
EGroupware\Api\Hooks::pr...framework_avatar_stat') cannot be passed to array_pop() as the parameter $array expects a reference.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
| 615 | |||||||
| 616 | return '<span title="'.Accounts::format_username().'" class="avatar"><img src="'.Egw::link('/api/avatar.php', array( |
||||||
| 617 | 'account_id' => $GLOBALS['egw_info']['user']['account_id'], |
||||||
| 618 | )).'"/>'.(!empty($stat) ? |
||||||
| 619 | '<span class="fw_avatar_stat '.$stat['class'].'" title="'.$stat['title'].'">'.$stat['body'].'</span>' : '').'</span>'; |
||||||
| 620 | } |
||||||
| 621 | |||||||
| 622 | /** |
||||||
| 623 | * Returns logout menu |
||||||
| 624 | * |
||||||
| 625 | * @return string |
||||||
| 626 | */ |
||||||
| 627 | protected static function _logout_menu() |
||||||
| 628 | { |
||||||
| 629 | return '<a href="'.Egw::link('/logout.php').'" title="'.lang("Logout").'" ></a>'; |
||||||
| 630 | } |
||||||
| 631 | |||||||
| 632 | /** |
||||||
| 633 | * Returns print menu |
||||||
| 634 | * |
||||||
| 635 | * @return string |
||||||
| 636 | */ |
||||||
| 637 | protected static function _print_menu() |
||||||
| 638 | { |
||||||
| 639 | return '<span title="'.lang("Print current view").'"</span>'; |
||||||
| 640 | } |
||||||
| 641 | |||||||
| 642 | |||||||
| 643 | /** |
||||||
| 644 | * Prepare the current users |
||||||
| 645 | * |
||||||
| 646 | * @return array |
||||||
| 647 | */ |
||||||
| 648 | protected static function _current_users() |
||||||
| 649 | { |
||||||
| 650 | if( $GLOBALS['egw_info']['user']['apps']['admin'] && $GLOBALS['egw_info']['user']['preferences']['common']['show_currentusers']) |
||||||
| 651 | { |
||||||
| 652 | return [ |
||||||
| 653 | 'name' => 'current_user', |
||||||
| 654 | 'title' => lang('Current users').':'.$GLOBALS['egw']->session->session_count(), |
||||||
| 655 | 'url' => self::link('/index.php','menuaction=admin.admin_accesslog.sessions&ajax=true') |
||||||
| 656 | ]; |
||||||
| 657 | } |
||||||
| 658 | } |
||||||
| 659 | |||||||
| 660 | /** |
||||||
| 661 | * Prepare the quick add selectbox |
||||||
| 662 | * |
||||||
| 663 | * @return string |
||||||
| 664 | */ |
||||||
| 665 | protected static function _get_quick_add() |
||||||
| 666 | { |
||||||
| 667 | return '<span id="quick_add" title="'.lang('Quick add').'"></span>'; |
||||||
| 668 | } |
||||||
| 669 | |||||||
| 670 | /** |
||||||
| 671 | * Prepare notification signal (blinking bell) |
||||||
| 672 | * |
||||||
| 673 | * @return string |
||||||
| 674 | */ |
||||||
| 675 | protected static function _get_notification_bell() |
||||||
| 676 | { |
||||||
| 677 | return Html::image('notifications', 'notificationbell', lang('notifications'), |
||||||
| 678 | 'id="notificationbell" style="display: none"'); |
||||||
| 679 | } |
||||||
| 680 | |||||||
| 681 | /** |
||||||
| 682 | * Get context to use with file_get_context or fopen to use our proxy settings from setup |
||||||
| 683 | * |
||||||
| 684 | * @param string $username =null username for regular basic Auth |
||||||
| 685 | * @param string $password =null password --------- " ---------- |
||||||
| 686 | * @param array $opts =array() further params for http(s) context, eg. array('timeout' => 123) |
||||||
| 687 | * @return resource|null context to use with file_get_context/fopen or null if no proxy configured |
||||||
| 688 | */ |
||||||
| 689 | public static function proxy_context($username=null, $password=null, array $opts = array()) |
||||||
| 690 | { |
||||||
| 691 | $opts += array( |
||||||
| 692 | 'method' => 'GET', |
||||||
| 693 | ); |
||||||
| 694 | if (!empty($GLOBALS['egw_info']['server']['httpproxy_server'])) |
||||||
| 695 | { |
||||||
| 696 | $opts += array ( |
||||||
| 697 | 'proxy' => 'tcp://'.$GLOBALS['egw_info']['server']['httpproxy_server'].':'. |
||||||
| 698 | ($GLOBALS['egw_info']['server']['httpproxy_port'] ? $GLOBALS['egw_info']['server']['httpproxy_port'] : 8080), |
||||||
| 699 | 'request_fulluri' => true, |
||||||
| 700 | ); |
||||||
| 701 | // proxy authentication |
||||||
| 702 | if (!empty($GLOBALS['egw_info']['server']['httpproxy_server_username'])) |
||||||
| 703 | { |
||||||
| 704 | $opts['header'][] = 'Proxy-Authorization: Basic '.base64_encode($GLOBALS['egw_info']['server']['httpproxy_server_username'].':'. |
||||||
| 705 | $GLOBALS['egw_info']['server']['httpproxy_server_password']); |
||||||
| 706 | } |
||||||
| 707 | } |
||||||
| 708 | // optional authentication |
||||||
| 709 | if (isset($username)) |
||||||
| 710 | { |
||||||
| 711 | $opts['header'][] = 'Authorization: Basic '.base64_encode($username.':'.$password); |
||||||
| 712 | } |
||||||
| 713 | return stream_context_create(array( |
||||||
| 714 | 'http' => $opts, |
||||||
| 715 | 'https' => $opts, |
||||||
| 716 | )); |
||||||
| 717 | } |
||||||
| 718 | |||||||
| 719 | /** |
||||||
| 720 | * Get API version from changelog or database, whichever is bigger |
||||||
| 721 | * |
||||||
| 722 | * @param string &$changelog on return path to changelog |
||||||
| 723 | * @return string |
||||||
| 724 | */ |
||||||
| 725 | public static function api_version(&$changelog=null) |
||||||
| 726 | { |
||||||
| 727 | return Framework\Updates::api_version($changelog); |
||||||
| 728 | } |
||||||
| 729 | |||||||
| 730 | /** |
||||||
| 731 | * Get the link to an application's index page |
||||||
| 732 | * |
||||||
| 733 | * @param string $app |
||||||
| 734 | * @return string |
||||||
| 735 | */ |
||||||
| 736 | public static function index($app) |
||||||
| 737 | { |
||||||
| 738 | $data =& $GLOBALS['egw_info']['user']['apps'][$app]; |
||||||
| 739 | if (!isset($data)) |
||||||
| 740 | { |
||||||
| 741 | throw new Exception\WrongParameter("'$app' not a valid app for this user!"); |
||||||
| 742 | } |
||||||
| 743 | $index = '/'.$app.'/index.php'; |
||||||
| 744 | if (isset($data['index'])) |
||||||
| 745 | { |
||||||
| 746 | if ($data['index'][0] == '/') |
||||||
| 747 | { |
||||||
| 748 | $index = $data['index']; |
||||||
| 749 | } |
||||||
| 750 | else |
||||||
| 751 | { |
||||||
| 752 | $index = '/index.php?menuaction='.$data['index']; |
||||||
| 753 | } |
||||||
| 754 | } |
||||||
| 755 | return self::link($index,$GLOBALS['egw_info']['flags']['params'][$app]); |
||||||
| 756 | } |
||||||
| 757 | |||||||
| 758 | /** |
||||||
| 759 | * Used internally to store unserialized value of $GLOBALS['egw_info']['user']['preferences']['common']['user_apporder'] |
||||||
| 760 | */ |
||||||
| 761 | private static $user_apporder = array(); |
||||||
| 762 | |||||||
| 763 | /** |
||||||
| 764 | * Internal usort callback function used to sort an array according to the |
||||||
| 765 | * user sort order |
||||||
| 766 | */ |
||||||
| 767 | private static function _sort_apparray($a, $b) |
||||||
| 768 | { |
||||||
| 769 | //Unserialize the user_apporder array |
||||||
| 770 | $arr = self::$user_apporder; |
||||||
| 771 | |||||||
| 772 | $ind_a = isset($arr[$a['name']]) ? $arr[$a['name']] : null; |
||||||
| 773 | $ind_b = isset($arr[$b['name']]) ? $arr[$b['name']] : null; |
||||||
| 774 | |||||||
| 775 | if ($ind_a == $ind_b) |
||||||
| 776 | return 0; |
||||||
| 777 | |||||||
| 778 | if ($ind_a == null) |
||||||
| 779 | return -1; |
||||||
| 780 | |||||||
| 781 | if ($ind_b == null) |
||||||
| 782 | return 1; |
||||||
| 783 | |||||||
| 784 | return $ind_a > $ind_b ? 1 : -1; |
||||||
| 785 | } |
||||||
| 786 | |||||||
| 787 | /** |
||||||
| 788 | * Prepare an array with apps used to render the navbar |
||||||
| 789 | * |
||||||
| 790 | * This is similar to the former common::navbar() method - though it returns the vars and does not place them in global scope. |
||||||
| 791 | * |
||||||
| 792 | * @return array |
||||||
| 793 | */ |
||||||
| 794 | protected static function _get_navbar_apps() |
||||||
| 795 | { |
||||||
| 796 | $first = key($GLOBALS['egw_info']['user']['apps']); |
||||||
| 797 | if(is_array($GLOBALS['egw_info']['user']['apps']['admin']) && $first != 'admin') |
||||||
| 798 | { |
||||||
| 799 | $newarray['admin'] = $GLOBALS['egw_info']['user']['apps']['admin']; |
||||||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||||
| 800 | foreach($GLOBALS['egw_info']['user']['apps'] as $index => $value) |
||||||
| 801 | { |
||||||
| 802 | if($index != 'admin') |
||||||
| 803 | { |
||||||
| 804 | $newarray[$index] = $value; |
||||||
| 805 | } |
||||||
| 806 | } |
||||||
| 807 | $GLOBALS['egw_info']['user']['apps'] = $newarray; |
||||||
| 808 | reset($GLOBALS['egw_info']['user']['apps']); |
||||||
| 809 | } |
||||||
| 810 | unset($index); |
||||||
| 811 | unset($value); |
||||||
| 812 | unset($newarray); |
||||||
| 813 | |||||||
| 814 | $apps = array(); |
||||||
| 815 | foreach($GLOBALS['egw_info']['user']['apps'] as $app => $data) |
||||||
| 816 | { |
||||||
| 817 | if (is_long($app)) |
||||||
| 818 | { |
||||||
| 819 | continue; |
||||||
| 820 | } |
||||||
| 821 | |||||||
| 822 | if ($app == 'preferences' || $GLOBALS['egw_info']['apps'][$app]['status'] != 2 && $GLOBALS['egw_info']['apps'][$app]['status'] != 3) |
||||||
| 823 | { |
||||||
| 824 | $apps[$app]['title'] = $GLOBALS['egw_info']['apps'][$app]['title']; |
||||||
| 825 | $apps[$app]['url'] = self::index($app); |
||||||
| 826 | $apps[$app]['name'] = $app; |
||||||
| 827 | |||||||
| 828 | // create popup target |
||||||
| 829 | if ($data['status'] == 4) |
||||||
| 830 | { |
||||||
| 831 | $apps[$app]['target'] = ' target="'.$app.'" onClick="'."if (this != '') { window.open(this+'". |
||||||
| 832 | (strpos($apps[$app]['url'],'?') !== false ? '&' : '?'). |
||||||
| 833 | "referer='+encodeURIComponent(location),this.target,'width=800,height=600,scrollbars=yes,resizable=yes'); return false; } else { return true; }".'"'; |
||||||
| 834 | } |
||||||
| 835 | elseif(isset($GLOBALS['egw_info']['flags']['navbar_target']) && $GLOBALS['egw_info']['flags']['navbar_target']) |
||||||
| 836 | { |
||||||
| 837 | $apps[$app]['target'] = 'target="' . $GLOBALS['egw_info']['flags']['navbar_target'] . '"'; |
||||||
| 838 | } |
||||||
| 839 | else |
||||||
| 840 | { |
||||||
| 841 | $apps[$app]['target'] = ''; |
||||||
| 842 | } |
||||||
| 843 | |||||||
| 844 | // take status flag into account as we might use it on client-side. |
||||||
| 845 | // for instance: applications with status 5 will run in background |
||||||
| 846 | $apps[$app]['status'] = $data['status']; |
||||||
| 847 | |||||||
| 848 | $icon = isset($data['icon']) ? $data['icon'] : 'navbar'; |
||||||
| 849 | $icon_app = isset($data['icon_app']) ? $data['icon_app'] : $app; |
||||||
| 850 | $apps[$app]['icon'] = $apps[$app]['icon_hover'] = Image::find($icon_app,Array($icon,'nonav'),''); |
||||||
| 851 | } |
||||||
| 852 | } |
||||||
| 853 | |||||||
| 854 | //Sort the applications accordingly to their user sort setting |
||||||
| 855 | if ($GLOBALS['egw_info']['user']['preferences']['common']['user_apporder']) |
||||||
| 856 | { |
||||||
| 857 | //Sort the application array using the user_apporder array as sort index |
||||||
| 858 | self::$user_apporder = |
||||||
| 859 | unserialize($GLOBALS['egw_info']['user']['preferences']['common']['user_apporder']); |
||||||
| 860 | uasort($apps, __CLASS__.'::_sort_apparray'); |
||||||
| 861 | } |
||||||
| 862 | |||||||
| 863 | if ($GLOBALS['egw_info']['flags']['currentapp'] == 'preferences' || $GLOBALS['egw_info']['flags']['currentapp'] == 'about') |
||||||
| 864 | { |
||||||
| 865 | $app = $app_title = 'EGroupware'; |
||||||
|
0 ignored issues
–
show
|
|||||||
| 866 | } |
||||||
| 867 | else |
||||||
| 868 | { |
||||||
| 869 | $app = $GLOBALS['egw_info']['flags']['currentapp']; |
||||||
| 870 | $app_title = $GLOBALS['egw_info']['apps'][$app]['title']; |
||||||
| 871 | } |
||||||
| 872 | |||||||
| 873 | if ($GLOBALS['egw_info']['user']['apps']['preferences']) // Preferences last |
||||||
| 874 | { |
||||||
| 875 | $prefs = $apps['preferences']; |
||||||
| 876 | unset($apps['preferences']); |
||||||
| 877 | $apps['preferences'] = $prefs; |
||||||
| 878 | } |
||||||
| 879 | |||||||
| 880 | // We handle this here because its special |
||||||
| 881 | $apps['about']['title'] = 'EGroupware'; |
||||||
| 882 | $apps['about']['url'] = self::link('/about.php'); |
||||||
| 883 | $apps['about']['icon'] = $apps['about']['icon_hover'] = Image::find('api',Array('about','nonav')); |
||||||
| 884 | $apps['about']['name'] = 'about'; |
||||||
| 885 | |||||||
| 886 | $apps['logout']['title'] = lang('Logout'); |
||||||
| 887 | $apps['logout']['name'] = 'logout'; |
||||||
| 888 | $apps['logout']['url'] = self::link('/logout.php'); |
||||||
| 889 | $apps['logout']['icon'] = $apps['logout']['icon_hover'] = Image::find('api',Array('logout','nonav')); |
||||||
| 890 | |||||||
| 891 | return $apps; |
||||||
| 892 | } |
||||||
| 893 | |||||||
| 894 | /** |
||||||
| 895 | * Used by template headers for including CSS in the header |
||||||
| 896 | * |
||||||
| 897 | * 'app_css' - css styles from a) the menuaction's css-method and b) the $GLOBALS['egw_info']['flags']['css'] |
||||||
| 898 | * 'file_css' - link tag of the app.css file of the current app |
||||||
| 899 | * 'theme_css' - url of the theme css file |
||||||
| 900 | * 'print_css' - url of the print css file |
||||||
| 901 | * |
||||||
| 902 | * @author Dave Hall (*based* on verdilak? css inclusion code) |
||||||
| 903 | * @return array with keys 'app_css' from the css method of the menuaction-class and 'file_css' (app.css file of the application) |
||||||
| 904 | */ |
||||||
| 905 | public function _get_css() |
||||||
| 906 | { |
||||||
| 907 | $app_css = ''; |
||||||
| 908 | if (isset($GLOBALS['egw_info']['flags']['css'])) |
||||||
| 909 | { |
||||||
| 910 | $app_css = $GLOBALS['egw_info']['flags']['css']; |
||||||
| 911 | } |
||||||
| 912 | |||||||
| 913 | if (self::$load_default_css) |
||||||
| 914 | { |
||||||
| 915 | // For mobile user-agent we prefer mobile theme over selected one with a final fallback to theme named as template |
||||||
| 916 | $themes_to_check = array(); |
||||||
| 917 | if (Header\UserAgent::mobile() || $GLOBALS['egw_info']['user']['preferences']['common']['theme'] == 'fw_mobile') |
||||||
| 918 | { |
||||||
| 919 | $themes_to_check[] = $this->template_dir.'/mobile/'.$GLOBALS['egw_info']['user']['preferences']['common']['theme'].'.css'; |
||||||
| 920 | $themes_to_check[] = $this->template_dir.'/mobile/fw_mobile.css'; |
||||||
| 921 | } |
||||||
| 922 | $themes_to_check[] = $this->template_dir.'/css/'.$GLOBALS['egw_info']['user']['preferences']['common']['theme'].'.css'; |
||||||
| 923 | $themes_to_check[] = $this->template_dir.'/css/'.$this->template.'.css'; |
||||||
| 924 | foreach($themes_to_check as $theme_css) |
||||||
| 925 | { |
||||||
| 926 | if (file_exists(EGW_SERVER_ROOT.$theme_css)) break; |
||||||
| 927 | } |
||||||
| 928 | $debug_minify = $GLOBALS['egw_info']['server']['debug_minify'] === 'True'; |
||||||
| 929 | if (!$debug_minify && file_exists(EGW_SERVER_ROOT.($theme_min_css = str_replace('.css', '.min.css', $theme_css)))) |
||||||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||||
| 930 | { |
||||||
| 931 | //error_log(__METHOD__."() Framework\CssIncludes::get()=".array2string(Framework\CssIncludes::get())); |
||||||
| 932 | self::includeCSS($theme_min_css); |
||||||
| 933 | |||||||
| 934 | // Global category styles |
||||||
| 935 | if (basename($_SERVER['PHP_SELF']) !== 'login.php') |
||||||
| 936 | { |
||||||
| 937 | Categories::css(Categories::GLOBAL_APPNAME); |
||||||
| 938 | } |
||||||
| 939 | } |
||||||
| 940 | else |
||||||
| 941 | { |
||||||
| 942 | // Load these first |
||||||
| 943 | // Cascade should go: |
||||||
| 944 | // Libs < etemplate2 < framework/theme < app < print |
||||||
| 945 | // Enhanced selectboxes (et1) |
||||||
| 946 | self::includeCSS('/api/js/jquery/chosen/chosen.css'); |
||||||
| 947 | |||||||
| 948 | // eTemplate2 uses jQueryUI, so load it first so et2 can override if needed |
||||||
| 949 | self::includeCSS("/vendor/bower-asset/jquery-ui/themes/redmond/jquery-ui.css"); |
||||||
| 950 | |||||||
| 951 | // eTemplate2 - load in top so sidebox has styles too |
||||||
| 952 | self::includeCSS('/api/templates/default/etemplate2.css'); |
||||||
| 953 | |||||||
| 954 | // Category styles |
||||||
| 955 | if (basename($_SERVER['PHP_SELF']) !== 'login.php') |
||||||
| 956 | { |
||||||
| 957 | Categories::css(Categories::GLOBAL_APPNAME); |
||||||
| 958 | } |
||||||
| 959 | |||||||
| 960 | self::includeCSS($theme_css); |
||||||
| 961 | |||||||
| 962 | // sending print css last, so it can overwrite anything |
||||||
| 963 | $print_css = $this->template_dir.'/print.css'; |
||||||
| 964 | if(!file_exists(EGW_SERVER_ROOT.$print_css)) |
||||||
| 965 | { |
||||||
| 966 | $print_css = '/api/templates/default/print.css'; |
||||||
| 967 | } |
||||||
| 968 | self::includeCSS($print_css); |
||||||
| 969 | } |
||||||
| 970 | // search for app specific css file, so it can customize the theme |
||||||
| 971 | self::includeCSS($GLOBALS['egw_info']['flags']['currentapp'], 'app-'.$GLOBALS['egw_info']['user']['preferences']['common']['theme']) || |
||||||
| 972 | self::includeCSS($GLOBALS['egw_info']['flags']['currentapp'], 'app'); |
||||||
| 973 | } |
||||||
| 974 | return array( |
||||||
| 975 | 'app_css' => $app_css, |
||||||
| 976 | 'css_file' => Framework\CssIncludes::tags(), |
||||||
| 977 | ); |
||||||
| 978 | } |
||||||
| 979 | |||||||
| 980 | /** |
||||||
| 981 | * Used by the template headers for including javascript in the header |
||||||
| 982 | * |
||||||
| 983 | * The method is included here to make it easier to change the js support |
||||||
| 984 | * in eGW. One change then all templates will support it (as long as they |
||||||
| 985 | * include a call to this method). |
||||||
| 986 | * |
||||||
| 987 | * @param array $extra =array() extra data to pass to egw.js as data-parameter |
||||||
| 988 | * @return string the javascript to be included |
||||||
| 989 | */ |
||||||
| 990 | public static function _get_js(array $extra=array()) |
||||||
| 991 | { |
||||||
| 992 | $java_script = ''; |
||||||
| 993 | |||||||
| 994 | /* this flag is for all javascript code that has to be put before other jscode. |
||||||
| 995 | Think of conf vars etc... ([email protected]) */ |
||||||
| 996 | if (isset($GLOBALS['egw_info']['flags']['java_script_thirst'])) |
||||||
| 997 | { |
||||||
| 998 | $java_script .= $GLOBALS['egw_info']['flags']['java_script_thirst'] . "\n"; |
||||||
| 999 | } |
||||||
| 1000 | // add configuration, link-registry, images, user-data and -perferences for non-popup windows |
||||||
| 1001 | // specifying etag in url to force reload, as we send expires header |
||||||
| 1002 | if ($GLOBALS['egw_info']['flags']['js_link_registry']) |
||||||
| 1003 | { |
||||||
| 1004 | self::includeJS('/api/config.php', array( |
||||||
| 1005 | 'etag' => md5(json_encode(Config::clientConfigs()).Link::json_registry()), |
||||||
| 1006 | )); |
||||||
| 1007 | self::includeJS('/api/images.php', array( |
||||||
| 1008 | 'template' => $GLOBALS['egw_info']['server']['template_set'], |
||||||
| 1009 | 'etag' => md5(json_encode(Image::map($GLOBALS['egw_info']['server']['template_set']))) |
||||||
| 1010 | )); |
||||||
| 1011 | self::includeJS('/api/user.php', array( |
||||||
| 1012 | 'user' => $GLOBALS['egw_info']['user']['account_lid'], |
||||||
| 1013 | 'lang' => $GLOBALS['egw_info']['user']['preferences']['common']['lang'], |
||||||
| 1014 | // add etag on url, so we can set an expires header |
||||||
| 1015 | 'etag' => md5(json_encode($GLOBALS['egw_info']['user']['preferences']['common']). |
||||||
| 1016 | $GLOBALS['egw']->accounts->json($GLOBALS['egw_info']['user']['account_id'])), |
||||||
| 1017 | )); |
||||||
| 1018 | } |
||||||
| 1019 | |||||||
| 1020 | $extra['url'] = $GLOBALS['egw_info']['server']['webserver_url']; |
||||||
| 1021 | $extra['include'] = array_map(function($str){return substr($str,1);}, self::get_script_links(true), array(1)); |
||||||
| 1022 | $extra['app'] = $GLOBALS['egw_info']['flags']['currentapp']; |
||||||
| 1023 | |||||||
| 1024 | // Load LABjs ONCE here |
||||||
| 1025 | $java_script .= '<script type="text/javascript" src="'.$GLOBALS['egw_info']['server']['webserver_url']. |
||||||
| 1026 | '/api/js/labjs/LAB.src.js?'.filemtime(EGW_SERVER_ROOT.'/api/js/labjs/LAB.src.js')."\"></script>\n". |
||||||
| 1027 | '<script type="text/javascript" src="'.$GLOBALS['egw_info']['server']['webserver_url']. |
||||||
| 1028 | '/api/js/jsapi/egw.js?'.filemtime(EGW_SERVER_ROOT.'/api/js/jsapi/egw.js').'" id="egw_script_id"'; |
||||||
| 1029 | |||||||
| 1030 | // add values of extra parameter and class var as data attributes to script tag of egw.js |
||||||
| 1031 | foreach($extra+self::$extra as $name => $value) |
||||||
| 1032 | { |
||||||
| 1033 | if (is_array($value)) $value = json_encode($value); |
||||||
| 1034 | // we need to double encode (Html::htmlspecialchars( , TRUE)), as otherwise we get invalid json, eg. for quotes |
||||||
| 1035 | $java_script .= ' data-'.$name."=\"". Html::htmlspecialchars($value, true)."\""; |
||||||
| 1036 | } |
||||||
| 1037 | $java_script .= "></script>\n"; |
||||||
| 1038 | |||||||
| 1039 | if(@isset($_GET['menuaction'])) |
||||||
| 1040 | { |
||||||
| 1041 | list(, $class) = explode('.',$_GET['menuaction']); |
||||||
| 1042 | if(is_array($GLOBALS[$class]->public_functions) && |
||||||
| 1043 | $GLOBALS[$class]->public_functions['java_script']) |
||||||
| 1044 | { |
||||||
| 1045 | $java_script .= $GLOBALS[$class]->java_script(); |
||||||
| 1046 | } |
||||||
| 1047 | } |
||||||
| 1048 | if (isset($GLOBALS['egw_info']['flags']['java_script'])) |
||||||
| 1049 | { |
||||||
| 1050 | // Strip out any script tags, this needs to be executed as anonymous function |
||||||
| 1051 | $GLOBALS['egw_info']['flags']['java_script'] = preg_replace(array('/(<script[^>]*>)([^<]*)/is','/<\/script>/'),array('$2',''),$GLOBALS['egw_info']['flags']['java_script']); |
||||||
| 1052 | if(trim($GLOBALS['egw_info']['flags']['java_script']) != '') |
||||||
| 1053 | { |
||||||
| 1054 | $java_script .= '<script type="text/javascript">window.egw_LAB.wait(function() {'.$GLOBALS['egw_info']['flags']['java_script'] . "});</script>\n"; |
||||||
| 1055 | } |
||||||
| 1056 | } |
||||||
| 1057 | |||||||
| 1058 | return $java_script; |
||||||
| 1059 | } |
||||||
| 1060 | |||||||
| 1061 | /** |
||||||
| 1062 | * List available themes |
||||||
| 1063 | * |
||||||
| 1064 | * Themes are css file in the template directory |
||||||
| 1065 | * |
||||||
| 1066 | * @param string $themes_dir ='css' |
||||||
| 1067 | */ |
||||||
| 1068 | function list_themes() |
||||||
| 1069 | { |
||||||
| 1070 | $list = array(); |
||||||
| 1071 | if (file_exists($file=EGW_SERVER_ROOT.$this->template_dir.'/setup/setup.inc.php') && |
||||||
| 1072 | (include $file) && isset($GLOBALS['egw_info']['template'][$this->template]['themes'])) |
||||||
| 1073 | { |
||||||
| 1074 | $list = $GLOBALS['egw_info']['template'][$this->template]['themes']; |
||||||
| 1075 | } |
||||||
| 1076 | if (($dh = @opendir(EGW_SERVER_ROOT.$this->template_dir.'/css'))) |
||||||
| 1077 | { |
||||||
| 1078 | while (($file = readdir($dh))) |
||||||
| 1079 | { |
||||||
| 1080 | if (preg_match('/'."\.css$".'/i', $file)) |
||||||
| 1081 | { |
||||||
| 1082 | list($name) = explode('.',$file); |
||||||
| 1083 | if (!isset($list[$name])) $list[$name] = ucfirst ($name); |
||||||
| 1084 | } |
||||||
| 1085 | } |
||||||
| 1086 | closedir($dh); |
||||||
| 1087 | } |
||||||
| 1088 | return $list; |
||||||
| 1089 | } |
||||||
| 1090 | |||||||
| 1091 | /** |
||||||
| 1092 | * List available templates |
||||||
| 1093 | * |
||||||
| 1094 | * @param boolean $full_data =false true: value is array with values for keys 'name', 'title', ... |
||||||
| 1095 | * @returns array alphabetically sorted list of templates |
||||||
| 1096 | */ |
||||||
| 1097 | static function list_templates($full_data=false) |
||||||
| 1098 | { |
||||||
| 1099 | $list = array('pixelegg'=>null); |
||||||
| 1100 | // templates packaged like apps in own directories (containing as setup/setup.inc.php file!) |
||||||
| 1101 | $dr = dir(EGW_SERVER_ROOT); |
||||||
| 1102 | while (($entry=$dr->read())) |
||||||
| 1103 | { |
||||||
| 1104 | if ($entry != '..' && !isset($GLOBALS['egw_info']['apps'][$entry]) && is_dir(EGW_SERVER_ROOT.'/'.$entry) && |
||||||
| 1105 | file_exists($f = EGW_SERVER_ROOT . '/' . $entry .'/setup/setup.inc.php')) |
||||||
| 1106 | { |
||||||
| 1107 | include($f); |
||||||
| 1108 | if (isset($GLOBALS['egw_info']['template'][$entry])) |
||||||
| 1109 | { |
||||||
| 1110 | $list[$entry] = $full_data ? $GLOBALS['egw_info']['template'][$entry] : |
||||||
| 1111 | $GLOBALS['egw_info']['template'][$entry]['title']; |
||||||
| 1112 | } |
||||||
| 1113 | } |
||||||
| 1114 | } |
||||||
| 1115 | $dr->close(); |
||||||
| 1116 | |||||||
| 1117 | return array_filter($list); |
||||||
| 1118 | } |
||||||
| 1119 | |||||||
| 1120 | /** |
||||||
| 1121 | * Compile entries for topmenu: |
||||||
| 1122 | * - regular items: links |
||||||
| 1123 | * - info items |
||||||
| 1124 | * |
||||||
| 1125 | * @param array $vars |
||||||
| 1126 | * @param array $apps |
||||||
| 1127 | */ |
||||||
| 1128 | function topmenu(array $vars,array $apps) |
||||||
| 1129 | { |
||||||
| 1130 | // array of topmenu info items (orders of the items matter) |
||||||
| 1131 | $topmenu_info_items = [ |
||||||
| 1132 | 'user_avatar' => $this->_user_avatar_menu(), |
||||||
| 1133 | 'logout' => (Header\UserAgent::mobile() || $GLOBALS['egw_info']['user']['preferences']['common']['theme'] == 'fw_mobile') ? self::_logout_menu() : null, |
||||||
| 1134 | 'update' => ($update = Framework\Updates::notification()) ? $update : null, |
||||||
| 1135 | 'notifications' => ($GLOBALS['egw_info']['user']['apps']['notifications']) ? self::_get_notification_bell() : null, |
||||||
| 1136 | 'quick_add' => $vars['quick_add'], |
||||||
| 1137 | 'print_title' => $this->_print_menu() |
||||||
| 1138 | ]; |
||||||
| 1139 | |||||||
| 1140 | // array of topmenu items (orders of the items matter) |
||||||
| 1141 | $topmenu_items = [ |
||||||
| 1142 | 0 => (is_array(($current_user = $this->_current_users()))) ? $current_user : null, |
||||||
|
0 ignored issues
–
show
|
|||||||
| 1143 | ]; |
||||||
| 1144 | |||||||
| 1145 | // Home should be at the top before preferences |
||||||
| 1146 | if($GLOBALS['egw_info']['user']['apps']['home'] && isset($apps['home'])) |
||||||
| 1147 | { |
||||||
| 1148 | $this->_add_topmenu_item($apps['home']); |
||||||
| 1149 | } |
||||||
| 1150 | |||||||
| 1151 | // array of topmenu preferences items (orders of the items matter) |
||||||
| 1152 | $topmenu_preferences = ['prefs', 'acl', 'cats', 'security']; |
||||||
| 1153 | |||||||
| 1154 | // set topmenu preferences items |
||||||
| 1155 | if($GLOBALS['egw_info']['user']['apps']['preferences']) |
||||||
| 1156 | { |
||||||
| 1157 | foreach ($topmenu_preferences as $prefs) |
||||||
| 1158 | { |
||||||
| 1159 | $this->add_preferences_topmenu($prefs); |
||||||
| 1160 | } |
||||||
| 1161 | } |
||||||
| 1162 | |||||||
| 1163 | // call topmenu info items hooks |
||||||
| 1164 | Hooks::process('topmenu_info',array(),true); |
||||||
| 1165 | |||||||
| 1166 | // Add extra items added by hooks |
||||||
| 1167 | foreach(self::$top_menu_extra as $extra_item) { |
||||||
| 1168 | if ($extra_item['name'] == 'search') |
||||||
| 1169 | { |
||||||
| 1170 | $topmenu_info_items['search'] = '<a href="'.$extra_item['url'].'" title="'.$extra_item['title'].'"></a>'; |
||||||
| 1171 | } |
||||||
| 1172 | else |
||||||
| 1173 | { |
||||||
| 1174 | array_push($topmenu_items, $extra_item); |
||||||
| 1175 | } |
||||||
| 1176 | } |
||||||
| 1177 | // push logout as the last item in topmenu items list |
||||||
| 1178 | array_push($topmenu_items, $apps['logout']); |
||||||
| 1179 | |||||||
| 1180 | // set topmenu info items |
||||||
| 1181 | foreach ($topmenu_info_items as $id => $content) |
||||||
| 1182 | { |
||||||
| 1183 | if (!$content || (in_array($id, ['search', 'quick_add', 'update']) && (Header\UserAgent::mobile() || $GLOBALS['egw_info']['user']['preferences']['common']['theme'] == 'fw_mobile'))) |
||||||
| 1184 | { |
||||||
| 1185 | continue; |
||||||
| 1186 | } |
||||||
| 1187 | $this->_add_topmenu_info_item($content, $id); |
||||||
| 1188 | } |
||||||
| 1189 | // set topmenu items |
||||||
| 1190 | foreach ($topmenu_items as $item) |
||||||
| 1191 | { |
||||||
| 1192 | if ($item) $this->_add_topmenu_item($item); |
||||||
| 1193 | } |
||||||
| 1194 | } |
||||||
| 1195 | |||||||
| 1196 | /** |
||||||
| 1197 | * Add Preferences link to topmenu using settings-hook to know if an app supports Preferences |
||||||
| 1198 | */ |
||||||
| 1199 | protected function add_preferences_topmenu($type='prefs') |
||||||
| 1200 | { |
||||||
| 1201 | static $memberships=null; |
||||||
| 1202 | if (!isset($memberships)) $memberships = $GLOBALS['egw']->accounts->memberships($GLOBALS['egw_info']['user']['account_id'], true); |
||||||
| 1203 | static $types = array( |
||||||
| 1204 | 'prefs' => array( |
||||||
| 1205 | 'title' => 'Preferences', |
||||||
| 1206 | 'hook' => 'settings', |
||||||
| 1207 | ), |
||||||
| 1208 | 'acl' => array( |
||||||
| 1209 | 'title' => 'Access', |
||||||
| 1210 | 'hook' => 'acl_rights', |
||||||
| 1211 | ), |
||||||
| 1212 | 'cats' => array( |
||||||
| 1213 | 'title' => 'Categories', |
||||||
| 1214 | 'hook' => 'categories', |
||||||
| 1215 | 'run_hook' => true, // acturally run hook, not just look it's implemented |
||||||
| 1216 | ), |
||||||
| 1217 | 'security' => array( |
||||||
| 1218 | 'title' => 'Security & Password', |
||||||
| 1219 | 'hook' => 'preferences_security', |
||||||
| 1220 | ), |
||||||
| 1221 | ); |
||||||
| 1222 | if (!$GLOBALS['egw_info']['user']['apps']['preferences'] || $GLOBALS['egw_info']['server']['deny_'.$type] && |
||||||
| 1223 | array_intersect($memberships, (array)$GLOBALS['egw_info']['server']['deny_'.$type]) && |
||||||
| 1224 | !$GLOBALS['egw_info']['user']['apps']['admin']) |
||||||
| 1225 | { |
||||||
| 1226 | return; // user has no access to Preferences app |
||||||
| 1227 | } |
||||||
| 1228 | if (isset($types[$type]['run_hook'])) |
||||||
| 1229 | { |
||||||
| 1230 | $apps = Hooks::process($types[$type]['hook']); |
||||||
| 1231 | // as all apps answer, we need to remove none-true responses |
||||||
| 1232 | foreach($apps as $app => $val) |
||||||
| 1233 | { |
||||||
| 1234 | if (!$val) unset($apps[$app]); |
||||||
| 1235 | } |
||||||
| 1236 | } |
||||||
| 1237 | else |
||||||
| 1238 | { |
||||||
| 1239 | $apps = Hooks::implemented($types[$type]['hook']); |
||||||
| 1240 | } |
||||||
| 1241 | // allways display password in topmenu, if user has rights to change it |
||||||
| 1242 | switch ($type) |
||||||
| 1243 | { |
||||||
| 1244 | case 'security': |
||||||
| 1245 | if ($apps || $GLOBALS['egw_info']['server']['2fa_required'] !== 'disabled' || |
||||||
| 1246 | !$GLOBALS['egw']->acl->check('nopasswordchange', 1)) |
||||||
| 1247 | { |
||||||
| 1248 | $this->_add_topmenu_item(array( |
||||||
| 1249 | 'id' => 'password', |
||||||
| 1250 | 'name' => 'preferences', |
||||||
| 1251 | 'title' => lang($types[$type]['title']), |
||||||
| 1252 | 'url' => "javascript:egw.open_link('". |
||||||
| 1253 | self::link('/index.php?menuaction=preferences.preferences_password.change')."','_blank','850x580')", |
||||||
| 1254 | )); |
||||||
| 1255 | } |
||||||
| 1256 | break; |
||||||
| 1257 | |||||||
| 1258 | default: |
||||||
| 1259 | $this->_add_topmenu_item(array( |
||||||
| 1260 | 'id' => $type, |
||||||
| 1261 | 'name' => 'preferences', |
||||||
| 1262 | 'title' => lang($types[$type]['title']), |
||||||
| 1263 | 'url' => "javascript:egw.show_preferences(\"$type\",".json_encode($apps).')', |
||||||
| 1264 | )); |
||||||
| 1265 | } |
||||||
| 1266 | } |
||||||
| 1267 | |||||||
| 1268 | /** |
||||||
| 1269 | * Add menu items to the topmenu template class to be displayed |
||||||
| 1270 | * |
||||||
| 1271 | * @param array $app application data |
||||||
| 1272 | * @param mixed $alt_label string with alternative menu item label default value = null |
||||||
| 1273 | * @param string $urlextra string with alternate additional code inside <a>-tag |
||||||
| 1274 | * @access protected |
||||||
| 1275 | * @return void |
||||||
| 1276 | */ |
||||||
| 1277 | abstract function _add_topmenu_item(array $app_data,$alt_label=null); |
||||||
| 1278 | |||||||
| 1279 | /** |
||||||
| 1280 | * Add info items to the topmenu template class to be displayed |
||||||
| 1281 | * |
||||||
| 1282 | * @param string $content Html of item |
||||||
| 1283 | * @param string $id =null |
||||||
| 1284 | * @access protected |
||||||
| 1285 | * @return void |
||||||
| 1286 | */ |
||||||
| 1287 | abstract function _add_topmenu_info_item($content, $id=null); |
||||||
| 1288 | |||||||
| 1289 | static $top_menu_extra = array(); |
||||||
| 1290 | |||||||
| 1291 | /** |
||||||
| 1292 | * Called by hooks to add an entry in the topmenu location. |
||||||
| 1293 | * Extra entries will be added just before Logout. |
||||||
| 1294 | * |
||||||
| 1295 | * @param string $id unique element id |
||||||
| 1296 | * @param string $url Address for the entry to link to |
||||||
| 1297 | * @param string $title Text displayed for the entry |
||||||
| 1298 | * @param string $target Optional, so the entry can open in a new page or popup |
||||||
| 1299 | * @access public |
||||||
| 1300 | * @return void |
||||||
| 1301 | */ |
||||||
| 1302 | public static function add_topmenu_item($id,$url,$title,$target = '') |
||||||
| 1303 | { |
||||||
| 1304 | $entry['name'] = $id; |
||||||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||||
| 1305 | $entry['url'] = $url; |
||||||
| 1306 | $entry['title'] = $title; |
||||||
| 1307 | $entry['target'] = $target; |
||||||
| 1308 | |||||||
| 1309 | self::$top_menu_extra[$id] = $entry; |
||||||
| 1310 | } |
||||||
| 1311 | |||||||
| 1312 | /** |
||||||
| 1313 | * called by hooks to add an icon in the topmenu info location |
||||||
| 1314 | * |
||||||
| 1315 | * @param string $id unique element id |
||||||
| 1316 | * @param string $icon_src src of the icon image. Make sure this nog height then 18pixels |
||||||
| 1317 | * @param string $iconlink where the icon links to |
||||||
| 1318 | * @param booleon $blink set true to make the icon blink |
||||||
|
0 ignored issues
–
show
The type
EGroupware\Api\booleon was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths Loading history...
|
|||||||
| 1319 | * @param mixed $tooltip string containing the tooltip html, or null of no tooltip |
||||||
| 1320 | * @access public |
||||||
| 1321 | * @return void |
||||||
| 1322 | */ |
||||||
| 1323 | abstract function topmenu_info_icon($id,$icon_src,$iconlink,$blink=false,$tooltip=null); |
||||||
| 1324 | |||||||
| 1325 | /** |
||||||
| 1326 | * Call and return content of 'after_navbar' hook |
||||||
| 1327 | * |
||||||
| 1328 | * @return string |
||||||
| 1329 | */ |
||||||
| 1330 | protected function _get_after_navbar() |
||||||
| 1331 | { |
||||||
| 1332 | ob_start(); |
||||||
| 1333 | Hooks::process('after_navbar',null,true); |
||||||
| 1334 | $content = ob_get_contents(); |
||||||
| 1335 | ob_end_clean(); |
||||||
| 1336 | |||||||
| 1337 | return $content; |
||||||
| 1338 | } |
||||||
| 1339 | |||||||
| 1340 | /** |
||||||
| 1341 | * Return javascript (eg. for onClick) to open manual with given url |
||||||
| 1342 | * |
||||||
| 1343 | * @param string $url |
||||||
| 1344 | */ |
||||||
| 1345 | abstract function open_manual_js($url); |
||||||
| 1346 | |||||||
| 1347 | /** |
||||||
| 1348 | * Methods to add javascript to framework |
||||||
| 1349 | */ |
||||||
| 1350 | |||||||
| 1351 | /** |
||||||
| 1352 | * The include manager manages including js files and their dependencies |
||||||
| 1353 | */ |
||||||
| 1354 | protected static $js_include_mgr; |
||||||
| 1355 | |||||||
| 1356 | /** |
||||||
| 1357 | * Checks to make sure a valid package and file name is provided |
||||||
| 1358 | * |
||||||
| 1359 | * Example call syntax: |
||||||
| 1360 | * a) Api\Framework::includeJS('jscalendar','calendar') |
||||||
| 1361 | * --> /phpgwapi/js/jscalendar/calendar.js |
||||||
| 1362 | * b) Api\Framework::includeJS('/phpgwapi/inc/calendar-setup.js',array('lang'=>'de')) |
||||||
| 1363 | * --> /phpgwapi/inc/calendar-setup.js?lang=de |
||||||
| 1364 | * |
||||||
| 1365 | * @param string $package package or complete path (relative to EGW_SERVER_ROOT) to be included |
||||||
| 1366 | * @param string|array $file =null file to be included - no ".js" on the end or array with get params |
||||||
| 1367 | * @param string $app ='phpgwapi' application directory to search - default = phpgwapi |
||||||
| 1368 | * @param boolean $append =true should the file be added |
||||||
| 1369 | */ |
||||||
| 1370 | static function includeJS($package, $file=null, $app='phpgwapi', $append=true) |
||||||
| 1371 | { |
||||||
| 1372 | self::$js_include_mgr->include_js_file($package, $file, $app, $append); |
||||||
| 1373 | } |
||||||
| 1374 | |||||||
| 1375 | /** |
||||||
| 1376 | * Set or return all javascript files set via validate_file, optionally clear all files |
||||||
| 1377 | * |
||||||
| 1378 | * @param array $files =null array with pathes relative to EGW_SERVER_ROOT, eg. /api/js/jquery/jquery.js |
||||||
| 1379 | * @param boolean $clear_files =false true clear files after returning them |
||||||
| 1380 | * @return array with pathes relative to EGW_SERVER_ROOT |
||||||
| 1381 | */ |
||||||
| 1382 | static function js_files(array $files=null, $clear_files=false) |
||||||
| 1383 | { |
||||||
| 1384 | if (isset($files) && is_array($files)) |
||||||
| 1385 | { |
||||||
| 1386 | self::$js_include_mgr->include_files($files); |
||||||
| 1387 | } |
||||||
| 1388 | return self::$js_include_mgr->get_included_files($clear_files); |
||||||
| 1389 | } |
||||||
| 1390 | |||||||
| 1391 | /** |
||||||
| 1392 | * Used for generating the list of external js files to be included in the head of a page |
||||||
| 1393 | * |
||||||
| 1394 | * NOTE: This method should only be called by the template class. |
||||||
| 1395 | * The validation is done when the file is added so we don't have to worry now |
||||||
| 1396 | * |
||||||
| 1397 | * @param boolean $return_pathes =false false: return Html script tags, true: return array of file pathes relative to webserver_url |
||||||
| 1398 | * @param boolean $clear_files =false true clear files after returning them |
||||||
| 1399 | * @return string|array see $return_pathes parameter |
||||||
| 1400 | */ |
||||||
| 1401 | static public function get_script_links($return_pathes=false, $clear_files=false) |
||||||
| 1402 | { |
||||||
| 1403 | $to_include = Framework\Bundle::js_includes(self::$js_include_mgr->get_included_files($clear_files)); |
||||||
| 1404 | |||||||
| 1405 | if ($return_pathes) |
||||||
| 1406 | { |
||||||
| 1407 | return $to_include; |
||||||
| 1408 | } |
||||||
| 1409 | $start = '<script type="text/javascript" src="'. $GLOBALS['egw_info']['server']['webserver_url']; |
||||||
| 1410 | $end = '">'."</script>\n"; |
||||||
| 1411 | return "\n".$start.implode($end.$start, $to_include).$end; |
||||||
| 1412 | } |
||||||
| 1413 | |||||||
| 1414 | /** |
||||||
| 1415 | * |
||||||
| 1416 | * @var boolean |
||||||
| 1417 | */ |
||||||
| 1418 | protected static $load_default_css = true; |
||||||
| 1419 | |||||||
| 1420 | /** |
||||||
| 1421 | * Include a css file, either speicified by it's path (relative to EGW_SERVER_ROOT) or appname and css file name |
||||||
| 1422 | * |
||||||
| 1423 | * @param string $app path (relative to EGW_SERVER_ROOT) or appname (if !is_null($name)) |
||||||
| 1424 | * @param string $name =null name of css file in $app/templates/{default|$this->template}/$name.css |
||||||
| 1425 | * @param boolean $append =true true append file, false prepend (add as first) file used eg. for template itself |
||||||
| 1426 | * @param boolean $no_default_css =false true do NOT load any default css, only what app explicitly includes |
||||||
| 1427 | * @return boolean false: css file not found, true: file found |
||||||
| 1428 | */ |
||||||
| 1429 | public static function includeCSS($app, $name=null, $append=true, $no_default_css=false) |
||||||
| 1430 | { |
||||||
| 1431 | if ($no_default_css) |
||||||
| 1432 | { |
||||||
| 1433 | self::$load_default_css = false; |
||||||
| 1434 | } |
||||||
| 1435 | //error_log(__METHOD__."('$app', '$name', append=$append, no_default=$no_default_css) ".function_backtrace()); |
||||||
| 1436 | return Framework\CssIncludes::add($app, $name, $append, $no_default_css); |
||||||
| 1437 | } |
||||||
| 1438 | |||||||
| 1439 | /** |
||||||
| 1440 | * Add registered CSS and javascript to ajax response |
||||||
| 1441 | */ |
||||||
| 1442 | public static function include_css_js_response() |
||||||
| 1443 | { |
||||||
| 1444 | $response = Json\Response::get(); |
||||||
| 1445 | $app = $GLOBALS['egw_info']['flags']['currentapp']; |
||||||
| 1446 | |||||||
| 1447 | // try to add app specific css file |
||||||
| 1448 | self::includeCSS($app, 'app-'.$GLOBALS['egw_info']['user']['preferences']['common']['theme']) || |
||||||
| 1449 | self::includeCSS($app,'app'); |
||||||
| 1450 | |||||||
| 1451 | // add all css files from Framework::includeCSS() |
||||||
| 1452 | $query = null; |
||||||
| 1453 | //error_log(__METHOD__."() Framework\CssIncludes::get()=".array2string(Framework\CssIncludes::get())); |
||||||
| 1454 | foreach(Framework\CssIncludes::get() as $path) |
||||||
|
0 ignored issues
–
show
|
|||||||
| 1455 | { |
||||||
| 1456 | unset($query); |
||||||
| 1457 | list($path,$query) = explode('?',$path,2); |
||||||
| 1458 | $path .= '?'. ($query ? $query : filemtime(EGW_SERVER_ROOT.$path)); |
||||||
| 1459 | $response->includeCSS($GLOBALS['egw_info']['server']['webserver_url'].$path); |
||||||
| 1460 | } |
||||||
| 1461 | |||||||
| 1462 | // try to add app specific js file |
||||||
| 1463 | self::includeJS('.', 'app', $app); |
||||||
| 1464 | |||||||
| 1465 | // add all js files from Framework::includeJS() |
||||||
| 1466 | $files = Framework\Bundle::js_includes(self::$js_include_mgr->get_included_files()); |
||||||
| 1467 | foreach($files as $path) |
||||||
| 1468 | { |
||||||
| 1469 | $response->includeScript($GLOBALS['egw_info']['server']['webserver_url'].$path); |
||||||
| 1470 | } |
||||||
| 1471 | } |
||||||
| 1472 | |||||||
| 1473 | /** |
||||||
| 1474 | * Set a preference via ajax |
||||||
| 1475 | * |
||||||
| 1476 | * @param string $app |
||||||
| 1477 | * @param string $name |
||||||
| 1478 | * @param string $value |
||||||
| 1479 | */ |
||||||
| 1480 | public static function ajax_set_preference($app, $name, $value) |
||||||
| 1481 | { |
||||||
| 1482 | $GLOBALS['egw']->preferences->read_repository(); |
||||||
| 1483 | if ((string)$value === '') |
||||||
| 1484 | { |
||||||
| 1485 | $GLOBALS['egw']->preferences->delete($app, $name); |
||||||
| 1486 | } |
||||||
| 1487 | else |
||||||
| 1488 | { |
||||||
| 1489 | $GLOBALS['egw']->preferences->add($app, $name, $value); |
||||||
| 1490 | } |
||||||
| 1491 | $GLOBALS['egw']->preferences->save_repository(True); |
||||||
| 1492 | } |
||||||
| 1493 | |||||||
| 1494 | /** |
||||||
| 1495 | * Get Preferences of a certain application via ajax |
||||||
| 1496 | * |
||||||
| 1497 | * @param string $app |
||||||
| 1498 | */ |
||||||
| 1499 | public static function ajax_get_preference($app) |
||||||
| 1500 | { |
||||||
| 1501 | // dont block session, while we read preferences, they are not supposed to change something in the session |
||||||
| 1502 | $GLOBALS['egw']->session->commit_session(); |
||||||
| 1503 | |||||||
| 1504 | if (preg_match('/^[a-z0-9_]+$/i', $app)) |
||||||
| 1505 | { |
||||||
| 1506 | // send etag header, if we are directly called (not via jsonq!) |
||||||
| 1507 | if (strpos($_GET['menuaction'], __FUNCTION__) !== false) |
||||||
| 1508 | { |
||||||
| 1509 | $etag = '"'.$app.'-'.md5(json_encode($GLOBALS['egw_info']['user']['preferences'][$app])).'"'; |
||||||
| 1510 | if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $etag) |
||||||
| 1511 | { |
||||||
| 1512 | header("HTTP/1.1 304 Not Modified"); |
||||||
| 1513 | exit(); |
||||||
| 1514 | } |
||||||
| 1515 | header('ETag: '.$etag); |
||||||
| 1516 | } |
||||||
| 1517 | $response = Json\Response::get(); |
||||||
| 1518 | $response->call('egw.set_preferences', (array)$GLOBALS['egw_info']['user']['preferences'][$app], $app); |
||||||
| 1519 | } |
||||||
| 1520 | } |
||||||
| 1521 | |||||||
| 1522 | /** |
||||||
| 1523 | * Create or delete a favorite for multiple users |
||||||
| 1524 | * |
||||||
| 1525 | * Need to be in egw_framework to be called with .template postfix from json.php! |
||||||
| 1526 | * |
||||||
| 1527 | * @param string $app Current application, needed to save preference |
||||||
| 1528 | * @param string $name Name of the favorite |
||||||
| 1529 | * @param string $action "add" or "delete" |
||||||
| 1530 | * @param boolean|int|string $group ID of the group to create the favorite for, or 'all' for all users |
||||||
| 1531 | * @param array $filters =array() key => value pairs for the filter |
||||||
| 1532 | * @return boolean Success |
||||||
| 1533 | */ |
||||||
| 1534 | public static function ajax_set_favorite($app, $name, $action, $group, $filters = array()) |
||||||
| 1535 | { |
||||||
| 1536 | return Framework\Favorites::set_favorite($app, $name, $action, $group, $filters); |
||||||
| 1537 | } |
||||||
| 1538 | |||||||
| 1539 | /** |
||||||
| 1540 | * Get a cachable list of users for the client |
||||||
| 1541 | * |
||||||
| 1542 | * The account source takes care of access and filtering according to preference |
||||||
| 1543 | */ |
||||||
| 1544 | public static function ajax_user_list() |
||||||
| 1545 | { |
||||||
| 1546 | $list = array('accounts' => array(),'groups' => array(), 'owngroups' => array()); |
||||||
| 1547 | if($GLOBALS['egw_info']['user']['preferences']['common']['account_selection'] == 'primary_group') |
||||||
| 1548 | { |
||||||
| 1549 | $list['accounts']['filter']['group'] = $GLOBALS['egw_info']['user']['account_primary_group']; |
||||||
| 1550 | } |
||||||
| 1551 | $contact_obj = new Contacts(); |
||||||
| 1552 | foreach($list as $type => &$accounts) |
||||||
| 1553 | { |
||||||
| 1554 | $options = array('account_type' => $type) + $accounts; |
||||||
| 1555 | $key_pair = Accounts::link_query('',$options); |
||||||
| 1556 | $accounts = array(); |
||||||
| 1557 | foreach($key_pair as $account_id => $name) |
||||||
| 1558 | { |
||||||
| 1559 | $contact = $contact_obj->read('account:'.$account_id, true); |
||||||
| 1560 | $accounts[] = array('value' => $account_id, 'label' => $name, 'icon' => self::link('/api/avatar.php', array( |
||||||
| 1561 | 'contact_id' => $contact['id'], |
||||||
| 1562 | 'etag' => $contact['etag'] |
||||||
| 1563 | ))); |
||||||
| 1564 | } |
||||||
| 1565 | } |
||||||
| 1566 | |||||||
| 1567 | Json\Response::get()->data($list); |
||||||
| 1568 | return $list; |
||||||
| 1569 | } |
||||||
| 1570 | |||||||
| 1571 | /** |
||||||
| 1572 | * Get certain account-data of given account-id(s) |
||||||
| 1573 | * |
||||||
| 1574 | * @param string|array $_account_ids |
||||||
| 1575 | * @param string $_field ='account_email' |
||||||
| 1576 | * @param boolean $_resolve_groups =false true: return attribute for all members, false return attribute for group itself |
||||||
| 1577 | * @return array account_id => data pairs |
||||||
| 1578 | */ |
||||||
| 1579 | public static function ajax_account_data($_account_ids, $_field, $_resolve_groups=false) |
||||||
| 1580 | { |
||||||
| 1581 | $list = array(); |
||||||
| 1582 | foreach((array)$_account_ids as $account_id) |
||||||
| 1583 | { |
||||||
| 1584 | foreach($account_id < 0 && $_resolve_groups ? |
||||||
|
0 ignored issues
–
show
|
|||||||
| 1585 | $GLOBALS['egw']->accounts->members($account_id, true) : array($account_id) as $account_id) |
||||||
| 1586 | { |
||||||
| 1587 | // Make sure name is formatted according to preference |
||||||
| 1588 | if($_field == 'account_fullname') |
||||||
| 1589 | { |
||||||
| 1590 | $list[$account_id] = Accounts::format_username( |
||||||
| 1591 | $GLOBALS['egw']->accounts->id2name($account_id, 'account_lid'), |
||||||
| 1592 | $GLOBALS['egw']->accounts->id2name($account_id, 'account_firstname'), |
||||||
| 1593 | $GLOBALS['egw']->accounts->id2name($account_id, 'account_lastname'), |
||||||
| 1594 | $account_id |
||||||
| 1595 | ); |
||||||
| 1596 | } |
||||||
| 1597 | else |
||||||
| 1598 | { |
||||||
| 1599 | $list[$account_id] = $GLOBALS['egw']->accounts->id2name($account_id, $_field); |
||||||
| 1600 | } |
||||||
| 1601 | } |
||||||
| 1602 | } |
||||||
| 1603 | |||||||
| 1604 | Json\Response::get()->data($list); |
||||||
| 1605 | return $list; |
||||||
| 1606 | } |
||||||
| 1607 | } |
||||||
| 1608 | // Init all static variables |
||||||
| 1609 | Framework::init_static(); |
||||||
| 1610 |