mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-25 01:13:25 +01:00
move egw_framework to api and refactor it
This commit is contained in:
parent
d48a968674
commit
8c87cf9dfc
@ -14,22 +14,23 @@ $GLOBALS['egw_info'] = array(
|
||||
);
|
||||
include('../../../header.inc.php');
|
||||
|
||||
egw_framework::validate_file('.','etemplate2','etemplate');
|
||||
egw_framework::validate_file('jquery','jquery.tools.min','phpgwapi'); // Not needed once JS require works for files like this
|
||||
egw_framework::validate_file('jquery','jquery.html5_upload','phpgwapi'); // Not needed once JS require works for files like this
|
||||
egw_framework::includeCSS('/etemplate/js/test/test.css');
|
||||
use EGroupware\Api;
|
||||
|
||||
Api\Framework::includeJS('.','etemplate2','etemplate');
|
||||
Api\Framework::includeJS('jquery','jquery.tools.min','phpgwapi'); // Not needed once JS require works for files like this
|
||||
Api\Framework::includeJS('jquery','jquery.html5_upload','phpgwapi'); // Not needed once JS require works for files like this
|
||||
Api\Framework::includeCSS('/api/js/etemplate/test/test.css');
|
||||
|
||||
/*
|
||||
* Test using any actual template
|
||||
*/
|
||||
$template = 'etemplate.et2_test_file_upload';
|
||||
if($template) {
|
||||
$etemplate = new etemplate_new('etemplate.et2_test_file_upload');
|
||||
$etemplate = new Api\Etemplate('etemplate.et2_test_file_upload');
|
||||
$etemplate->exec('',array());
|
||||
return;
|
||||
}
|
||||
common::egw_header();
|
||||
// parse_navbar();
|
||||
echo $GLOBALS['egw']->framework->header();
|
||||
?>
|
||||
<script src="et2_test_timesheet_edit.json"></script>
|
||||
<script src="et2_test_input_validator.json"></script>
|
||||
@ -58,6 +59,4 @@ Testing from inside framework, so JS includes work
|
||||
}
|
||||
</script>
|
||||
<?php
|
||||
common::egw_footer();
|
||||
|
||||
?>
|
||||
echo $GLOBALS['egw']->framework->footer();
|
||||
|
@ -19,7 +19,7 @@
|
||||
namespace EGroupware\Api;
|
||||
|
||||
// explicitly reference classes still in phpgwapi of old structure
|
||||
use egw;
|
||||
use egw; // invalidate_session_cache
|
||||
|
||||
/**
|
||||
* API - accounts
|
||||
|
@ -15,9 +15,6 @@ namespace EGroupware\Api\CalDAV;
|
||||
|
||||
use EGroupware\Api;
|
||||
|
||||
// explicit import old non-namespaced api classes
|
||||
use egw; // link
|
||||
|
||||
/**
|
||||
* GroupDAV hooks: eg. preferences
|
||||
*/
|
||||
@ -40,7 +37,7 @@ class Hooks
|
||||
if ($location == 'preferences')
|
||||
{
|
||||
$file = array(
|
||||
'Preferences' => egw::link('/index.php','menuaction=preferences.preference_settings.index&appname='.$appname),
|
||||
'Preferences' => Api\Framework::link('/index.php','menuaction=preferences.preference_settings.index&appname='.$appname),
|
||||
);
|
||||
if ($location == 'preferences')
|
||||
{
|
||||
@ -121,7 +118,7 @@ class Hooks
|
||||
}
|
||||
}
|
||||
}
|
||||
$link = egw::link('/index.php',array(
|
||||
$link = Api\Framework::link('/index.php',array(
|
||||
'menuaction' => 'api.'.__CLASS__.'.log',
|
||||
'filename' => '',
|
||||
));
|
||||
|
@ -19,8 +19,6 @@
|
||||
|
||||
namespace EGroupware\Api;
|
||||
|
||||
use egw_framework; // includeCSS
|
||||
|
||||
/**
|
||||
* class to manage categories in eGroupWare
|
||||
*
|
||||
@ -1040,7 +1038,7 @@ class Categories
|
||||
$last_mod = $cats->return_array('all',0,1,'','DESC','last_mod', $appname == self::GLOBAL_APPNAME);
|
||||
$time = count($last_mod) ? $last_mod[0]['last_mod'] : time();
|
||||
$path = '/api/categories.php?app='.$appname.'&'.$time;
|
||||
egw_framework::includeCSS($path);
|
||||
Framework::includeCSS($path);
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
@ -13,10 +13,6 @@
|
||||
|
||||
namespace EGroupware\Api;
|
||||
|
||||
// explicitly import old not yet ported classes
|
||||
use egw;
|
||||
use egw_framework;
|
||||
|
||||
/**
|
||||
* New eTemplate serverside contains:
|
||||
* - main server methods like read, exec
|
||||
@ -71,7 +67,7 @@ class Etemplate extends Etemplate\Widget\Template
|
||||
*/
|
||||
static function location($params='')
|
||||
{
|
||||
egw::redirect_link(is_array($params) ? '/index.php' : $params,
|
||||
Framework::redirect_link(is_array($params) ? '/index.php' : $params,
|
||||
is_array($params) ? $params : '');
|
||||
}
|
||||
|
||||
@ -138,7 +134,7 @@ class Etemplate extends Etemplate\Widget\Template
|
||||
unset($hook_data);
|
||||
|
||||
// Include the etemplate2 javascript code
|
||||
egw_framework::validate_file('etemplate', 'etemplate2', 'api');
|
||||
Framework::includeJS('etemplate', 'etemplate2', 'api');
|
||||
|
||||
if (!$this->rel_path) throw new Exception\AssertionFailed("No (valid) template '$this->name' found!");
|
||||
|
||||
@ -210,25 +206,25 @@ class Etemplate extends Etemplate\Widget\Template
|
||||
if (self::$response) // call is within an ajax event / form submit
|
||||
{
|
||||
//error_log("Ajax " . __LINE__);
|
||||
self::$response->generic('et2_load', $load_array+egw_framework::get_extra());
|
||||
egw_framework::clear_extra(); // to not send/set it twice for multiple etemplates (eg. CRM view)
|
||||
self::$response->generic('et2_load', $load_array+Framework::get_extra());
|
||||
Framework::clear_extra(); // to not send/set it twice for multiple etemplates (eg. CRM view)
|
||||
}
|
||||
else // first call
|
||||
{
|
||||
// missing dependency, thought egw:uses jquery.jquery.tools does NOT work, maybe we should rename it to jquery-tools
|
||||
// egw_framework::validate_file('jquery','jquery.tools.min');
|
||||
// Framework::includeJS('jquery','jquery.tools.min');
|
||||
|
||||
// Include the jQuery-UI CSS - many more complex widgets use it
|
||||
$theme = 'redmond';
|
||||
egw_framework::includeCSS("/api/js/jquery/jquery-ui/$theme/jquery-ui-1.10.3.custom.css");
|
||||
Framework::includeCSS("/api/js/jquery/jquery-ui/$theme/jquery-ui-1.10.3.custom.css");
|
||||
// Load our CSS after jQuery-UI, so we can override it
|
||||
egw_framework::includeCSS('/api/templates/default/etemplate2.css');
|
||||
Framework::includeCSS('/api/templates/default/etemplate2.css');
|
||||
|
||||
// check if application of template has a app.js file --> load it
|
||||
list($app) = explode('.',$this->name);
|
||||
if (file_exists(EGW_SERVER_ROOT.'/'.$app.'/js/app.js'))
|
||||
{
|
||||
egw_framework::validate_file('.','app',$app,false);
|
||||
Framework::includeJS('.','app',$app,false);
|
||||
}
|
||||
// Category styles
|
||||
Categories::css($app);
|
||||
@ -252,8 +248,8 @@ class Etemplate extends Etemplate\Widget\Template
|
||||
$content .= "\n".$vars['page_generation_time'];
|
||||
}
|
||||
$GLOBALS['egw']->framework->response->generic("data", array($content));
|
||||
$GLOBALS['egw']->framework->response->generic('et2_load',$load_array+egw_framework::get_extra());
|
||||
egw_framework::clear_extra(); // to not send/set it twice for multiple etemplates (eg. CRM view)
|
||||
$GLOBALS['egw']->framework->response->generic('et2_load',$load_array+Framework::get_extra());
|
||||
Framework::clear_extra(); // to not send/set it twice for multiple etemplates (eg. CRM view)
|
||||
self::$request = null;
|
||||
return;
|
||||
}
|
||||
|
@ -15,9 +15,6 @@ namespace EGroupware\Api\Etemplate;
|
||||
|
||||
use EGroupware\Api;
|
||||
|
||||
// explicitly import old not yet ported classes
|
||||
use egw_framework;
|
||||
|
||||
/**
|
||||
* Class to represent the persitent information of an eTemplate request
|
||||
*
|
||||
@ -212,7 +209,7 @@ class Request
|
||||
}
|
||||
else
|
||||
{
|
||||
egw_framework::redirect_link($index_url);
|
||||
Api\Framework::redirect_link($index_url);
|
||||
}
|
||||
}
|
||||
return $request;
|
||||
|
@ -16,10 +16,6 @@ namespace EGroupware\Api\Etemplate\Widget;
|
||||
use EGroupware\Api\Etemplate;
|
||||
use EGroupware\Api;
|
||||
|
||||
// explicitly import old not yet ported classes
|
||||
use egw;
|
||||
use egw_framework; // includeCSS
|
||||
|
||||
/**
|
||||
* eTemplate serverside implementation of the nextmatch widget
|
||||
*
|
||||
@ -95,7 +91,7 @@ class Nextmatch extends Etemplate\Widget
|
||||
parent::__construct($xml);
|
||||
|
||||
// TODO: probably a better way to do this
|
||||
egw_framework::includeCSS('/api/js/egw_action/test/skins/dhtmlxmenu_egw.css');
|
||||
Api\Framework::includeCSS('/api/js/egw_action/test/skins/dhtmlxmenu_egw.css');
|
||||
}
|
||||
}
|
||||
|
||||
@ -863,7 +859,7 @@ class Nextmatch extends Etemplate\Widget
|
||||
// link or popup action
|
||||
if ($action['url'])
|
||||
{
|
||||
$action['url'] = egw::link('/index.php',str_replace('$action',$id,$action['url']));
|
||||
$action['url'] = Api\Framework::link('/index.php',str_replace('$action',$id,$action['url']));
|
||||
if ($action['popup'])
|
||||
{
|
||||
list($action['data']['width'],$action['data']['height']) = explode('x',$action['popup']);
|
||||
|
@ -17,9 +17,6 @@ use EGroupware\Api\Etemplate;
|
||||
use EGroupware\Api;
|
||||
use XMLReader;
|
||||
|
||||
// explicitly import old not yet ported classes
|
||||
use egw; // link
|
||||
|
||||
/* allow to call direct for tests (see end of class)
|
||||
if (!isset($GLOBALS['egw_info']))
|
||||
{
|
||||
@ -211,7 +208,7 @@ class Template extends Etemplate\Widget
|
||||
{
|
||||
$url = Api\Vfs::download_url($path);
|
||||
|
||||
if ($url[0] == '/') $url = egw::link($url);
|
||||
if ($url[0] == '/') $url = Api\Framework::link($url);
|
||||
|
||||
// mtime postfix has to use '?download=', as our WebDAV treats everything else literal and not ignore them like Apache for static files!
|
||||
$url .= '?download='.filemtime($path);
|
||||
|
@ -16,10 +16,7 @@ namespace EGroupware\Api\Etemplate\Widget;
|
||||
use EGroupware\Api\Etemplate;
|
||||
use EGroupware\Api;
|
||||
|
||||
// explicitly import old not yet ported classes
|
||||
use egw_framework;
|
||||
|
||||
egw_framework::includeCSS('/api/js/dhtmlxtree/codebase/dhtmlXTree.css');
|
||||
Api\Framework::includeCSS('/api/js/dhtmlxtree/codebase/dhtmlXTree.css');
|
||||
|
||||
/**
|
||||
* eTemplate tree widget
|
||||
|
@ -16,9 +16,6 @@ namespace EGroupware\Api\Etemplate\Widget;
|
||||
use EGroupware\Api\Etemplate;
|
||||
use EGroupware\Api;
|
||||
|
||||
// explicitly import old not yet ported classes
|
||||
use egw; // link
|
||||
|
||||
/**
|
||||
* eTemplate VFS widget
|
||||
* Deals with the Virtual File System
|
||||
@ -165,7 +162,7 @@ class Vfs extends File
|
||||
$file = array(
|
||||
"uploaded" => (int)empty($error),
|
||||
"fileName" => Api\Html::htmlspecialchars($_FILES['upload']['name']),
|
||||
"url" => egw::link(Api\Vfs::download_url($path)),
|
||||
"url" => Api\Framework::link(Api\Vfs::download_url($path)),
|
||||
"error" => array(
|
||||
"message" => $error,
|
||||
)
|
||||
|
@ -15,9 +15,6 @@ namespace EGroupware\Api\Etemplate;
|
||||
|
||||
use EGroupware\Api;
|
||||
|
||||
// explicitly list not yet ported api classes
|
||||
use egw_framework;
|
||||
|
||||
/**
|
||||
* eTemplate2 widget browser
|
||||
*
|
||||
@ -38,18 +35,18 @@ class WidgetBrowser
|
||||
//'js_link_registry' => True,
|
||||
|
||||
// Widget browser code
|
||||
egw_framework::validate_file('/api/js/etemplate/widget_browser.js');
|
||||
Api\Framework::includeJS('/api/js/etemplate/widget_browser.js');
|
||||
|
||||
// Include the etemplate2 javascript code
|
||||
egw_framework::validate_file('.', 'etemplate2', 'etemplate');
|
||||
Api\Framework::includeJS('.', 'etemplate2', 'etemplate');
|
||||
|
||||
// Include the jQuery-UI CSS - many more complex widgets use it
|
||||
$theme = 'redmond';
|
||||
egw_framework::includeCSS("/api/js/jquery/jquery-ui/$theme/jquery-ui-1.10.3.custom.css");
|
||||
Api\Framework::includeCSS("/api/js/jquery/jquery-ui/$theme/jquery-ui-1.10.3.custom.css");
|
||||
|
||||
egw_framework::includeCSS('/api/templates/default/etemplate2.css');
|
||||
Api\Framework::includeCSS('/api/templates/default/etemplate2.css');
|
||||
|
||||
egw_framework::includeCSS('api','widget_browser',false);
|
||||
Api\Framework::includeCSS('api','widget_browser',false);
|
||||
|
||||
// load translations
|
||||
Api\Translation::add_app('etemplate');
|
||||
|
1418
api/src/Framework.php
Normal file
1418
api/src/Framework.php
Normal file
File diff suppressed because it is too large
Load Diff
279
api/src/Framework/Bundle.php
Normal file
279
api/src/Framework/Bundle.php
Normal file
@ -0,0 +1,279 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware API - Bundle JS includes
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage framework
|
||||
* @access public
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Framework;
|
||||
|
||||
use EGroupware\Api\Cache;
|
||||
use EGroupware\Api\Header\UserAgent;
|
||||
|
||||
/**
|
||||
* Bundle JS includes
|
||||
*/
|
||||
class Bundle
|
||||
{
|
||||
/**
|
||||
* Url of minified version of bundle
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
static $bundle2minurl = array(
|
||||
'api' => '/api/js/jsapi.min.js',
|
||||
'et2' => '/api/js/etemplate/etemplate2.min.js',
|
||||
'et21'=> '/api/js/etemplate/etemplate2.min.js',
|
||||
'pixelegg' => '/pixelegg/js/fw_pixelegg.min.js',
|
||||
'jdots' => '/jdots/js/fw_jdots.min.js',
|
||||
'mobile' => '/jdots/js/fw_mobile.min.js',
|
||||
);
|
||||
|
||||
/**
|
||||
* Devide js-includes in bundles of javascript files to include eg. api or etemplate2, if minifying is enabled
|
||||
*
|
||||
* @param array $js_includes files to include with egw relative url
|
||||
* @return array egw relative urls to include incl. bundels/minify urls, if enabled
|
||||
*/
|
||||
public static function js_includes(array $js_includes)
|
||||
{
|
||||
$file2bundle = array();
|
||||
if ($GLOBALS['egw_info']['server']['debug_minify'] !== 'True')
|
||||
{
|
||||
// get used bundles and cache them on tree-level for 2h
|
||||
//$bundles = self::all(); Cache::setTree(__CLASS__, 'bundles', $bundles, 7200);
|
||||
$bundles = Cache::getTree(__CLASS__, 'bundles', array(__CLASS__, 'all'), array(), 7200);
|
||||
$bundles_ts = $bundles['.ts'];
|
||||
unset($bundles['.ts']);
|
||||
foreach($bundles as $name => $files)
|
||||
{
|
||||
// to facilitate move to new et2 location, can be removed after 16.1 release
|
||||
if ($name == 'et21' && !in_array('/api/js/etemplate/etemplate2.js', $files))
|
||||
{
|
||||
Cache::unsetTree(__CLASS__, 'bundles');
|
||||
return self::js_includes($js_includes);
|
||||
}
|
||||
// ignore bundles of not used templates, as they can contain identical files
|
||||
if (in_array($name, array('api', 'et2', 'et21')) ||
|
||||
$name == (UserAgent::mobile() ? 'mobile' : $GLOBALS['egw_info']['server']['template_set']) ||
|
||||
isset($GLOBALS['egw_info']['apps'][$name]))
|
||||
{
|
||||
$file2bundle += array_combine($files, array_fill(0, count($files), $name));
|
||||
}
|
||||
}
|
||||
//error_log(__METHOD__."() file2bundle=".array2string($file2bundle));
|
||||
}
|
||||
$to_include = $included_bundles = array();
|
||||
$query = null;
|
||||
foreach($js_includes as $file)
|
||||
{
|
||||
if (!isset($to_include[$file]))
|
||||
{
|
||||
if (($bundle = $file2bundle[$file]))
|
||||
{
|
||||
//error_log(__METHOD__."() requiring bundle $bundle for $file");
|
||||
if (!in_array($bundle, $included_bundles))
|
||||
{
|
||||
$included_bundles[] = $bundle;
|
||||
$minurl = self::$bundle2minurl[$bundle];
|
||||
if (!isset($minurl) && isset($GLOBALS['egw_info']['apps'][$bundle]))
|
||||
{
|
||||
$minurl = '/'.$bundle.'/js/app.min.js';
|
||||
}
|
||||
$max_modified = 0;
|
||||
$to_include = array_merge($to_include, self::urls($bundles[$bundle], $max_modified, $minurl));
|
||||
// check if bundle-config is more recent then
|
||||
if ($max_modified > $bundles_ts)
|
||||
{
|
||||
// force new bundle Config by deleting cached one and call ourself again
|
||||
Cache::unsetTree(__CLASS__, 'bundles');
|
||||
return self::js_includes($js_includes);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unset($query);
|
||||
list($path, $query) = explode('?', $file, 2);
|
||||
$mod = filemtime(EGW_SERVER_ROOT.$path);
|
||||
// check if we have a more recent minified version of the file and use it
|
||||
if ($GLOBALS['egw_info']['server']['debug_minify'] !== 'True' &&
|
||||
substr($path, -3) == '.js' && file_exists(EGW_SERVER_ROOT.($min_path = substr($path, 0, -3).'.min.js')) &&
|
||||
(($min_mod = filemtime(EGW_SERVER_ROOT.$min_path)) >= $mod))
|
||||
{
|
||||
$path = $min_path;
|
||||
$mod = $min_mod;
|
||||
}
|
||||
$to_include[$file] = $path.'?'.$mod.($query ? '&'.$query : '');
|
||||
}
|
||||
}
|
||||
}
|
||||
//error_log(__METHOD__."(".array2string($js_includes).') debug_minify='.array2string($GLOBALS['egw_info']['server']['debug_minify']).', include_bundels='.array2string($included_bundles).' returning '.array2string(array_values(array_unique($to_include))));
|
||||
return array_values(array_unique($to_include));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate bundle url(s) for given js files
|
||||
*
|
||||
* @param array $js_includes
|
||||
* @param int& $max_modified =null on return maximum modification time of bundle
|
||||
* @param string $minurl =null url of minified bundle, to be used, if existing and recent
|
||||
* @return array js-files (can be more then one, if one of given files can not be bundeled)
|
||||
*/
|
||||
protected static function urls(array $js_includes, &$max_modified=null, $minurl=null)
|
||||
{
|
||||
$debug_minify = $GLOBALS['egw_info']['server']['debug_minify'] === 'True';
|
||||
// ignore not existing minurl
|
||||
$to_include_first = $to_include = $to_minify = array();
|
||||
$max_modified = 0;
|
||||
$query = null;
|
||||
foreach($js_includes as $path)
|
||||
{
|
||||
if ($path == '/api/js/jsapi/egw.js') continue; // loaded via own tag, and we must not load it twice!
|
||||
|
||||
unset($query);
|
||||
list($path,$query) = explode('?',$path,2);
|
||||
$mod = filemtime(EGW_SERVER_ROOT.$path);
|
||||
|
||||
// ckeditor must be included before bundled files, as they depend on it!
|
||||
if (strpos($path,'/ckeditor/ckeditor.js') !== false)
|
||||
{
|
||||
$to_include_first[] = $path . '?' . $mod;
|
||||
}
|
||||
// for now minify does NOT support query parameters, nor php files generating javascript
|
||||
elseif ($debug_minify || $query || substr($path, -3) != '.js')
|
||||
{
|
||||
$path .= '?'. $mod.($query ? '&'.$query : '');
|
||||
$to_include[] = $path;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($mod > $max_modified) $max_modified = $mod;
|
||||
$to_minify[] = substr($path,1);
|
||||
}
|
||||
}
|
||||
if (!$debug_minify && $to_minify)
|
||||
{
|
||||
if (!empty($minurl) && file_exists(EGW_SERVER_ROOT.$minurl) &&
|
||||
($mod=filemtime(EGW_SERVER_ROOT.$minurl)) >= $max_modified)
|
||||
{
|
||||
$path = $minurl.'?'.$mod;
|
||||
}
|
||||
else
|
||||
{
|
||||
$base_path = $GLOBALS['egw_info']['server']['webserver_url'];
|
||||
if ($base_path[0] != '/') $base_path = parse_url($base_path, PHP_URL_PATH);
|
||||
$path = '/phpgwapi/inc/min/?'.($base_path && $base_path != '/' ? 'b='.substr($base_path, 1).'&' : '').
|
||||
'f='.implode(',', $to_minify) .
|
||||
($GLOBALS['egw_info']['server']['debug_minify'] === 'debug' ? '&debug' : '').
|
||||
'&'.$max_modified;
|
||||
}
|
||||
// need to include minified javascript before not minified stuff like jscalendar-setup, as it might depend on it
|
||||
array_unshift($to_include, $path);
|
||||
}
|
||||
if ($to_include_first) $to_include = array_merge($to_include_first, $to_include);
|
||||
//error_log(__METHOD__."("./*array2string($js_includes).*/", $max_modified, $minurl) returning ".array2string($to_include));
|
||||
return $to_include;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximum number of files in a bundle
|
||||
*
|
||||
* We split bundles, if they contain more then these number of files,
|
||||
* because IE silently stops caching them, if Content-Length get's too big.
|
||||
*
|
||||
* IE11 cached 142kb compressed api bundle, but not 190kb et2 bundle.
|
||||
* Splitting et2 bundle in max 50 files chunks, got IE11 to cache both bundles.
|
||||
*/
|
||||
const MAX_BUNDLE_FILES = 50;
|
||||
|
||||
/**
|
||||
* Return all bundels we use:
|
||||
* - api stuff phpgwapi/js/jsapi/* and it's dependencies incl. jquery
|
||||
* - etemplate2 stuff not including api bundle, but jquery-ui
|
||||
*
|
||||
* @return array bundle-url => array of contained files
|
||||
*/
|
||||
public static function all()
|
||||
{
|
||||
$inc_mgr = new IncludeMgr();
|
||||
$bundles = array();
|
||||
|
||||
$max_mod = array();
|
||||
|
||||
// generate api bundle
|
||||
$inc_mgr->include_js_file('/api/js/jquery/jquery.js');
|
||||
$inc_mgr->include_js_file('/api/js/jquery/jquery-ui.js');
|
||||
$inc_mgr->include_js_file('/api/js/jsapi/jsapi.js');
|
||||
$inc_mgr->include_js_file('/api/js/egw_json.js');
|
||||
$inc_mgr->include_js_file('/api/js/jsapi/egw.js');
|
||||
// dhtmlxTree (dhtmlxMenu get loaded via dependency in egw_menu_dhtmlx.js)
|
||||
$inc_mgr->include_js_file('/api/js/dhtmlxtree/codebase/dhtmlxcommon.js');
|
||||
$inc_mgr->include_js_file('/api/js/dhtmlxtree/sources/dhtmlxtree.js');
|
||||
$inc_mgr->include_js_file('/api/js/dhtmlxtree/sources/ext/dhtmlxtree_json.js');
|
||||
// actions
|
||||
$inc_mgr->include_js_file('/api/js/egw_action/egw_action.js');
|
||||
$inc_mgr->include_js_file('/api/js/egw_action/egw_keymanager.js');
|
||||
$inc_mgr->include_js_file('/api/js/egw_action/egw_action_popup.js');
|
||||
$inc_mgr->include_js_file('/api/js/egw_action/egw_action_dragdrop.js');
|
||||
$inc_mgr->include_js_file('/api/js/egw_action/egw_dragdrop_dhtmlx_tree.js');
|
||||
$inc_mgr->include_js_file('/api/js/egw_action/egw_menu.js');
|
||||
$inc_mgr->include_js_file('/api/js/egw_action/egw_menu_dhtmlx.js');
|
||||
// include choosen in api, as old eTemplate uses it and fail if it pulls in half of et2
|
||||
$inc_mgr->include_js_file('/api/js/jquery/chosen/chosen.jquery.js');
|
||||
// include CKEditor in api, as old eTemplate uses it too
|
||||
$inc_mgr->include_js_file('/api/js/ckeditor/ckeditor.js');
|
||||
$inc_mgr->include_js_file('/api/js/ckeditor/config.js');
|
||||
$bundles['api'] = $inc_mgr->get_included_files();
|
||||
self::urls($bundles['api'], $max_mod['api']);
|
||||
|
||||
// generate et2 bundle (excluding files in api bundle)
|
||||
$inc_mgr->include_js_file('/api/js/etemplate/etemplate2.js');
|
||||
$bundles['et2'] = array_diff($inc_mgr->get_included_files(), $bundles['api']);
|
||||
self::urls($bundles['et2'], $max_mod['et2']);
|
||||
|
||||
$stock_files = call_user_func_array('array_merge', $bundles);
|
||||
|
||||
// generate template and app bundles, if installed
|
||||
foreach(array(
|
||||
'jdots' => '/jdots/js/fw_jdots.js',
|
||||
'mobile' => '/jdots/js/fw_mobile.js',
|
||||
'pixelegg' => '/pixelegg/js/fw_pixelegg.js',
|
||||
'calendar' => '/calendar/js/app.js',
|
||||
'mail' => '/mail/js/app.js',
|
||||
'projectmanager' => '/projectmanager/js/app.js',
|
||||
) as $bundle => $file)
|
||||
{
|
||||
if (@file_exists(EGW_SERVER_ROOT.$file))
|
||||
{
|
||||
$inc_mgr = new IncludeMgr($stock_files); // reset loaded files to stock files
|
||||
$inc_mgr->include_js_file($file);
|
||||
$bundles[$bundle] = array_diff($inc_mgr->get_included_files(), $stock_files);
|
||||
self::urls($bundles[$bundle], $max_mod[$bundle]);
|
||||
}
|
||||
}
|
||||
|
||||
// automatic split bundles with more then MAX_BUNDLE_FILES (=50) files
|
||||
foreach($bundles as $name => $files)
|
||||
{
|
||||
$n = '';
|
||||
while (count($files) > self::MAX_BUNDLE_FILES*(int)$n)
|
||||
{
|
||||
$files80 = array_slice($files, self::MAX_BUNDLE_FILES*(int)$n, self::MAX_BUNDLE_FILES, true);
|
||||
$bundles[$name.$n++] = $files80;
|
||||
}
|
||||
}
|
||||
|
||||
// store max modification time of all files in all bundles
|
||||
$bundles['.ts'] = max($max_mod);
|
||||
|
||||
//error_log(__METHOD__."() returning ".array2string($bundles));
|
||||
return $bundles;
|
||||
}
|
||||
}
|
163
api/src/Framework/CssIncludes.php
Normal file
163
api/src/Framework/CssIncludes.php
Normal file
@ -0,0 +1,163 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware API - CSS Includes
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de> rewrite in 12/2006
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage framework
|
||||
* @access public
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Framework;
|
||||
|
||||
/**
|
||||
* CSS includes
|
||||
*/
|
||||
class CssIncludes
|
||||
{
|
||||
/**
|
||||
* Content from add calls
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $files = array();
|
||||
|
||||
/**
|
||||
* Include a css file, either speicified by it's path (relative to EGW_SERVER_ROOT) or appname and css file name
|
||||
*
|
||||
* @param string $app path (relative to EGW_SERVER_ROOT) or appname (if !is_null($name))
|
||||
* @param string $name =null name of css file in $app/templates/{default|$this->template}/$name.css
|
||||
* @param boolean $append =true true append file, false prepend (add as first) file used eg. for template itself
|
||||
* @param boolean $clear_includes =false true: clear all previous includes
|
||||
* @return boolean false: css file not found, true: file found
|
||||
*/
|
||||
public static function add($app, $name=null, $append=true, $clear_includes=false)
|
||||
{
|
||||
if ($clear_includes)
|
||||
{
|
||||
self::$files = array();
|
||||
}
|
||||
|
||||
if (!is_null($name))
|
||||
{
|
||||
foreach($GLOBALS['egw']->framework->template_dirs as $dir)
|
||||
{
|
||||
if (file_exists(EGW_SERVER_ROOT.($path = '/'.$app.'/templates/'.$dir.'/'.$name.'.css')))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$path = $app;
|
||||
}
|
||||
if (!file_exists(EGW_SERVER_ROOT.$path) && !file_exists(EGW_SERVER_ROOT . parse_url($path,PHP_URL_PATH)))
|
||||
{
|
||||
//error_log(__METHOD__."($app,$name) $path NOT found!");
|
||||
return false;
|
||||
}
|
||||
if (!in_array($path,self::$files))
|
||||
{
|
||||
if ($append)
|
||||
{
|
||||
self::$files[] = $path;
|
||||
}
|
||||
else
|
||||
{
|
||||
self::$files = array_merge(array($path), self::$files);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all css files included with add
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get()
|
||||
{
|
||||
return self::$files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return link tags for all included css files incl. minifying
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function tags()
|
||||
{
|
||||
// add all css files from self::includeCSS
|
||||
$max_modified = 0;
|
||||
$debug_minify = $GLOBALS['egw_info']['server']['debug_minify'] === 'True';
|
||||
$base_path = $GLOBALS['egw_info']['server']['webserver_url'];
|
||||
if ($base_path[0] != '/') $base_path = parse_url($base_path, PHP_URL_PATH);
|
||||
$css_files = '';
|
||||
foreach(self::$files as $path)
|
||||
{
|
||||
foreach(self::resolve_css_includes($path) as $path)
|
||||
{
|
||||
list($file,$query) = explode('?',$path,2);
|
||||
if (($mod = filemtime(EGW_SERVER_ROOT.$file)) > $max_modified) $max_modified = $mod;
|
||||
|
||||
// do NOT include app.css or categories.php, as it changes from app to app
|
||||
if ($debug_minify || substr($path, -8) == '/app.css' || substr($file,-14) == 'categories.php')
|
||||
{
|
||||
$css_files .= '<link href="'.$GLOBALS['egw_info']['server']['webserver_url'].$path.($query ? '&' : '?').$mod.'" type="text/css" rel="StyleSheet" />'."\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$css_file .= ($css_file ? ',' : '').substr($path, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$debug_minify)
|
||||
{
|
||||
$css = $GLOBALS['egw_info']['server']['webserver_url'].'/phpgwapi/inc/min/?';
|
||||
if ($base_path && $base_path != '/') $css .= 'b='.substr($base_path, 1).'&';
|
||||
$css .= 'f='.$css_file .
|
||||
($GLOBALS['egw_info']['server']['debug_minify'] === 'debug' ? '&debug' : '').
|
||||
'&'.$max_modified;
|
||||
$css_files = '<link href="'.$css.'" type="text/css" rel="StyleSheet" />'."\n".$css_files;
|
||||
}
|
||||
return $css_files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse beginning of given CSS file for /*@import url("...") statements
|
||||
*
|
||||
* @param string $path EGroupware relative path eg. /phpgwapi/templates/default/some.css
|
||||
* @return array parsed pathes (EGroupware relative) including $path itself
|
||||
*/
|
||||
protected static function resolve_css_includes($path, &$pathes=array())
|
||||
{
|
||||
$matches = null;
|
||||
|
||||
list($file) = explode('?',$path,2);
|
||||
if (($to_check = file_get_contents (EGW_SERVER_ROOT.$file, false, null, -1, 1024)) &&
|
||||
stripos($to_check, '/*@import') !== false && preg_match_all('|/\*@import url\("([^"]+)"|i', $to_check, $matches))
|
||||
{
|
||||
foreach($matches[1] as $import_path)
|
||||
{
|
||||
if ($import_path[0] != '/')
|
||||
{
|
||||
$dir = dirname($path);
|
||||
while(substr($import_path,0,3) == '../')
|
||||
{
|
||||
$dir = dirname($dir);
|
||||
$import_path = substr($import_path, 3);
|
||||
}
|
||||
$import_path = ($dir != '/' ? $dir : '').'/'.$import_path;
|
||||
}
|
||||
self::resolve_css_includes($import_path, $pathes);
|
||||
}
|
||||
}
|
||||
$pathes[] = $path;
|
||||
|
||||
return $pathes;
|
||||
}
|
||||
}
|
183
api/src/Framework/Extra.php
Normal file
183
api/src/Framework/Extra.php
Normal file
@ -0,0 +1,183 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware API - Framework extra
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage framework
|
||||
* @access public
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Framework;
|
||||
|
||||
use EGroupware\Api\Link;
|
||||
use EGroupware\Api\Json;
|
||||
|
||||
/**
|
||||
* Framework extra - handling of server-responses either send via data attribute
|
||||
*/
|
||||
abstract class Extra
|
||||
{
|
||||
/**
|
||||
* Extra values send as data attributes to script tag of egw.js
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $extra = array();
|
||||
|
||||
/**
|
||||
* Refresh given application $targetapp display of entry $app $id, incl. outputting $msg
|
||||
*
|
||||
* Calling egw_refresh and egw_message on opener in a content security save way
|
||||
*
|
||||
* To provide more information about necessary refresh an automatic 9th parameter is added
|
||||
* containing an object with application-name as attributes containing an array of linked ids
|
||||
* (adding happens in get_extras to give apps time to link new entries!).
|
||||
*
|
||||
* @param string $msg message (already translated) to show, eg. 'Entry deleted'
|
||||
* @param string $app application name
|
||||
* @param string|int $id =null id of entry to refresh
|
||||
* @param string $type =null either 'update', 'edit', 'delete', 'add' or null
|
||||
* - update: request just modified data from given rows.
|
||||
* Sorting and filtering are not considered, so if the sort field is changed,
|
||||
* the row will not be moved. If the current filtering could include or exclude
|
||||
* the record, use edit.
|
||||
* - edit: rows changed, but sorting or filtering may be affected. Requires full reload.
|
||||
* - delete: just delete the given rows clientside (no server interaction neccessary)
|
||||
* - add: requires full reload for proper sorting
|
||||
* - null: full reload
|
||||
* @param string $targetapp =null which app's window should be refreshed, default current
|
||||
* @param string|RegExp $replace =null regular expression to replace in url
|
||||
* @param string $with =null
|
||||
* @param string $msg_type =null 'error', 'warning' or 'success' (default)
|
||||
*/
|
||||
public static function refresh_opener($msg, $app, $id=null, $type=null, $targetapp=null, $replace=null, $with=null, $msg_type=null)
|
||||
{
|
||||
//error_log(__METHOD__.'('.array2string(func_get_args()).')');
|
||||
self::$extra['refresh-opener'] = func_get_args();
|
||||
|
||||
unset($msg, $app, $id, $type, $targetapp, $replace, $with, $msg_type); // used only via func_get_args();
|
||||
}
|
||||
|
||||
/**
|
||||
* Display an error or regular message
|
||||
*
|
||||
* Calls egw_message on client-side in a content security save way
|
||||
*
|
||||
* @param string $msg message to show
|
||||
* @param string $type ='success' 'error', 'warning' or 'success' (default)
|
||||
*/
|
||||
public static function message($msg, $type='success')
|
||||
{
|
||||
self::$extra['message'] = func_get_args();
|
||||
|
||||
unset($msg, $type); // used only via func_get_args();
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a popup independent if we run as json or regular request
|
||||
*
|
||||
* @param string $link
|
||||
* @param string $target
|
||||
* @param string $popup
|
||||
*/
|
||||
public static function popup($link, $target='_blank', $popup='640x480')
|
||||
{
|
||||
// default params are not returned by func_get_args!
|
||||
$args = func_get_args()+array(null, '_blank', '640x480');
|
||||
|
||||
unset($link, $target, $popup); // used only via func_get_args()
|
||||
|
||||
if (Json\Request::isJSONRequest())
|
||||
{
|
||||
Json\Response::get()->apply('egw.open_link', $args);
|
||||
}
|
||||
else
|
||||
{
|
||||
self::$extra['popup'] = $args;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close (popup) window, use to replace egw_framework::onload('window.close()') in a content security save way
|
||||
*
|
||||
* @param string $alert_msg ='' optional message to display as alert, before closing the window
|
||||
*/
|
||||
public static function window_close($alert_msg='')
|
||||
{
|
||||
//error_log(__METHOD__."()");
|
||||
self::$extra['window-close'] = $alert_msg ? $alert_msg : true;
|
||||
|
||||
// are we in ajax_process_content -> just return extra data, with close instructions
|
||||
if (preg_match('/etemplate(_new)?(::|\.)ajax_process_content/', $_GET['menuaction']))
|
||||
{
|
||||
$response = Json\Response::get();
|
||||
$response->generic('et2_load', self::get_extra());
|
||||
}
|
||||
else
|
||||
{
|
||||
$GLOBALS['egw']->framework->render('', false, false);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close (popup) window, use to replace egw_framework::onload('window.close()') in a content security save way
|
||||
*/
|
||||
public static function window_focus()
|
||||
{
|
||||
//error_log(__METHOD__."()");
|
||||
self::$extra['window-focus'] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow app to store arbitray values in egw script tag
|
||||
*
|
||||
* Attribute name will be "data-$app-$name" and value will be json serialized, if not scalar.
|
||||
*
|
||||
* @param string $app
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
*/
|
||||
public static function set_extra($app, $name, $value)
|
||||
{
|
||||
self::$extra[$app.'-'.$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all extra data
|
||||
*/
|
||||
public static function clear_extra()
|
||||
{
|
||||
self::$extra = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow eg. ajax to query content set via refresh_opener or window_close
|
||||
*
|
||||
* @return array content of egw_framework::$extra
|
||||
*/
|
||||
public static function get_extra()
|
||||
{
|
||||
// adding links of refreshed entry, to give others apps more information about necessity to refresh
|
||||
if (isset(self::$extra['refresh-opener']) && count(self::$extra['refresh-opener']) <= 8 && // do not run twice
|
||||
!empty(self::$extra['refresh-opener'][1]) && !empty(self::$extra['refresh-opener'][2])) // app/id given
|
||||
{
|
||||
$links = Link::get_links(self::$extra['refresh-opener'][1], self::$extra['refresh-opener'][2]);
|
||||
$apps = array();
|
||||
foreach($links as $link)
|
||||
{
|
||||
$apps[$link['app']][] = $link['id'];
|
||||
}
|
||||
while (count(self::$extra['refresh-opener']) < 8)
|
||||
{
|
||||
self::$extra['refresh-opener'][] = null;
|
||||
}
|
||||
self::$extra['refresh-opener'][] = $apps;
|
||||
}
|
||||
return self::$extra;
|
||||
}
|
||||
}
|
260
api/src/Framework/Favorites.php
Normal file
260
api/src/Framework/Favorites.php
Normal file
@ -0,0 +1,260 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware API - Favorites server-side
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @author Nathan Gray <ng@stylite.de>
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage framework
|
||||
* @access public
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Framework;
|
||||
|
||||
use EGroupware\Api;
|
||||
|
||||
/**
|
||||
* Favorites service-side:
|
||||
*
|
||||
* Favorites are generated on serverside by following code in apps sidebox hook:
|
||||
*
|
||||
* display_sidebox($appname, lang('Favorites'), Api\Framework\Favorites::favorite_list($appname));
|
||||
*
|
||||
* Clientside code resides in:
|
||||
* - api/js/jsapi/app_base.js
|
||||
* - api/js/etemplate/et2_widget_favorites.js
|
||||
*
|
||||
* Favorites are stored with prefix "favorite_" in app preferences.
|
||||
*/
|
||||
class Favorites
|
||||
{
|
||||
/**
|
||||
* Include favorites when generating the page server-side
|
||||
*
|
||||
* Use this function in your sidebox (or anywhere else, I suppose) to
|
||||
* get the favorite list when a nextmatch is _not_ on the page. If
|
||||
* a nextmatch is on the page, it will update / replace this list.
|
||||
*
|
||||
* @param string $app application, needed to find preferences
|
||||
* @param string $default preference name for default favorite, default "nextmatch-$app.index.rows-favorite"
|
||||
*
|
||||
* @return array with a single sidebox menu item (array) containing html for favorites
|
||||
*/
|
||||
public static function list_favorites($app, $default=null)
|
||||
{
|
||||
if (!$app)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!$default)
|
||||
{
|
||||
$default = "nextmatch-$app.index.rows-favorite";
|
||||
}
|
||||
|
||||
// This target is used client-side to find & enable adding new favorites
|
||||
$target = 'favorite_sidebox_'.$app;
|
||||
|
||||
/* @var $filters array an array of favorites*/
|
||||
$filters = self::get_favorites($app);
|
||||
$is_admin = $GLOBALS['egw_info']['user']['apps']['admin'];
|
||||
$html = "<span id='$target' class='ui-helper-clearfix sidebox-favorites'><ul class='ui-menu ui-widget-content ui-corner-all favorites' role='listbox'>\n";
|
||||
|
||||
$default_filter = $GLOBALS['egw_info']['user']['preferences'][$app][$default];
|
||||
if (!isset($default_filter) || !isset($filters[$default_filter]))
|
||||
{
|
||||
$default_filter = "blank";
|
||||
}
|
||||
|
||||
// Get link for if there is no nextmatch - this is the fallback
|
||||
$registry = Api\Link::get_registry($app,'list');
|
||||
if (!$registry)
|
||||
{
|
||||
$registry = Api\Link::get_registry($app, 'index');
|
||||
}
|
||||
foreach($filters as $name => $filter)
|
||||
{
|
||||
//filter must not be empty if there's one, ignore it at the moment but it need to be checked how it got there in database
|
||||
if (!$filter)
|
||||
{
|
||||
error_log(__METHOD__.'Favorite filter "'.$name.'" is not supposed to be empty, it should be an array. Skipping, more investigation needed. filter = '. array2string($filters[$name]));
|
||||
continue;
|
||||
}
|
||||
$li = "<li data-id='$name' data-group='{$filter['group']}' class='ui-menu-item' role='menuitem'>\n";
|
||||
$li .= '<a href="#" class="ui-corner-all" tabindex="-1">';
|
||||
$li .= "<div class='" . ((string)$name === (string)$default_filter ? 'ui-icon ui-icon-heart' : 'sideboxstar') . "'></div>".
|
||||
$filter['name'];
|
||||
$li .= ($filter['group'] != false && !$is_admin || $name === 'blank' ? "" :
|
||||
"<div class='ui-icon ui-icon-trash' title='" . lang('Delete') . "'></div>");
|
||||
$li .= "</a></li>\n";
|
||||
//error_log(__METHOD__."() $name, filter=".array2string($filter)." --> ".$li);
|
||||
$html .= $li;
|
||||
}
|
||||
|
||||
// If were're here, the app supports favorites, so add a 'Add' link too
|
||||
$html .= "<li data-id='add' class='ui-menu-item' role='menuitem'><a href='javascript:app.$app.add_favorite()' class='ui-corner-all'>";
|
||||
$html .= Api\Html::image($app, 'new') . lang('Add current'). '</a></li>';
|
||||
|
||||
$html .= '</ul></span>';
|
||||
|
||||
return array(
|
||||
array(
|
||||
'no_lang' => true,
|
||||
'text' => $html,
|
||||
'link' => false,
|
||||
'icon' => false,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get preferenced favorites sorted list
|
||||
*
|
||||
* @param string $app Application name as string
|
||||
*
|
||||
* @return (array|boolean) An array of sorted favorites or False if there's no preferenced sorted list
|
||||
*
|
||||
*/
|
||||
public static function get_fav_sort_pref ($app)
|
||||
{
|
||||
$fav_sorted_list = array();
|
||||
|
||||
if (($fav_sorted_list = $GLOBALS['egw_info']['user']['preferences'][$app]['fav_sort_pref']))
|
||||
{
|
||||
return $fav_sorted_list;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of actual user favorites
|
||||
* The default 'Blank' favorite is not included here
|
||||
*
|
||||
* @param string $app Current application
|
||||
*
|
||||
* @return array Favorite information
|
||||
*/
|
||||
public static function get_favorites($app)
|
||||
{
|
||||
$favorites = array(
|
||||
'blank' => array(
|
||||
'name' => lang('No filters'),
|
||||
// Old
|
||||
'filter' => array(),
|
||||
// New
|
||||
'state' => array(),
|
||||
'group' => true
|
||||
)
|
||||
);
|
||||
$pref_prefix = 'favorite_';
|
||||
|
||||
$sorted_list = array();
|
||||
$fav_sort_pref = self::get_fav_sort_pref($app);
|
||||
|
||||
// Look through all preferences & pull out favorites
|
||||
foreach((array)$GLOBALS['egw_info']['user']['preferences'][$app] as $pref_name => $pref)
|
||||
{
|
||||
if(strpos($pref_name, $pref_prefix) === 0)
|
||||
{
|
||||
if(!is_array($pref)) continue; // old favorite
|
||||
|
||||
$favorites[(string)substr($pref_name,strlen($pref_prefix))] = $pref;
|
||||
}
|
||||
}
|
||||
if (is_array($fav_sort_pref))
|
||||
{
|
||||
foreach ($fav_sort_pref as $key)
|
||||
{
|
||||
$sorted_list[$key] = $favorites[$key];
|
||||
}
|
||||
$favorites = array_merge($sorted_list,$favorites);
|
||||
}
|
||||
return $favorites;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create or delete a favorite for multiple users
|
||||
*
|
||||
* Current user needs to be an admin or it will just do nothing quietly
|
||||
*
|
||||
* @param string $app Current application, needed to save preference
|
||||
* @param string $_name Name of the favorite
|
||||
* @param string $action "add" or "delete"
|
||||
* @param boolean|int|String $group ID of the group to create the favorite for, or 'all' for all users
|
||||
* @param array $filters key => value pairs for the filter
|
||||
* @return boolean Success
|
||||
*/
|
||||
public static function set_favorite($app, $_name, $action, $group, $filters = array())
|
||||
{
|
||||
// Only use alphanumeric for preference name, so it can be used directly as DOM ID
|
||||
$name = strip_tags($_name);
|
||||
$pref_name = "favorite_".$name;
|
||||
|
||||
// older group-favorites have just true as their group and are not deletable, if we dont find correct group
|
||||
if ($group === true || $group === '1')
|
||||
{
|
||||
if (isset($GLOBALS['egw']->preferences->default[$app][$pref_name]))
|
||||
{
|
||||
$group = 'all';
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach($GLOBALS['egw']->accounts->memberships($GLOBALS['egw_info']['user']['account_id'], true) as $gid)
|
||||
{
|
||||
$prefs = new Api\Preferences($gid);
|
||||
$prefs->read_repository();
|
||||
if (isset($prefs->user[$app][$pref_name]))
|
||||
{
|
||||
$group = $gid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if($group && $GLOBALS['egw_info']['apps']['admin'] && $group !== 'all')
|
||||
{
|
||||
$prefs = new Api\Preferences(is_numeric($group) ? $group : $GLOBALS['egw_info']['user']['account_id']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$prefs = $GLOBALS['egw']->preferences;
|
||||
}
|
||||
$prefs->read_repository();
|
||||
$type = $group === "all" ? "default" : "user";
|
||||
//error_log(__METHOD__."('$app', '$name', '$action', ".array2string($group).", ...) pref_name=$pref_name, type=$type");
|
||||
if($action == "add")
|
||||
{
|
||||
$filters = array(
|
||||
// This is the name as user entered it, minus tags
|
||||
'name' => $name,
|
||||
'group' => $group ? $group : false,
|
||||
'state' => $filters
|
||||
);
|
||||
$pref_name = "favorite_".preg_replace('/[^A-Za-z0-9-_]/','_',$name);
|
||||
$result = $prefs->add($app,$pref_name,$filters,$type);
|
||||
$pref = $prefs->save_repository(false,$type);
|
||||
|
||||
// Update preferences client side, or it could disappear
|
||||
Api\Json\Responseget()->call('egw.set_preferences', (array)$pref[$app], $app);
|
||||
|
||||
Api\Json\Responseget()->data(isset($result[$app][$pref_name]));
|
||||
return isset($result[$app][$pref_name]);
|
||||
}
|
||||
else if ($action == "delete")
|
||||
{
|
||||
$result = $prefs->delete($app,$pref_name, $type);
|
||||
$pref = $prefs->save_repository(false,$type);
|
||||
|
||||
// Update preferences client side, or it could come back
|
||||
Api\Json\Responseget()->call('egw.set_preferences', (array)$pref[$app], $app);
|
||||
|
||||
Api\Json\Responseget()->data(!isset($result[$app][$pref_name]));
|
||||
return !isset($result[$app][$pref_name]);
|
||||
}
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage groupdav
|
||||
* @subpackage framework
|
||||
* @author Andreas Stöckel
|
||||
* @copyright (c) 2011 Stylite
|
||||
* @version $Id$
|
||||
|
247
api/src/Framework/Login.php
Normal file
247
api/src/Framework/Login.php
Normal file
@ -0,0 +1,247 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware API - Render (deny-)login screen
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de> rewrite in 12/2006
|
||||
* @author Pim Snel <pim@lingewoud.nl> author of the idots template set
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage framework
|
||||
* @access public
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Framework;
|
||||
|
||||
use EGroupware\Api;
|
||||
|
||||
// explicitly import old, not yet ported api classes
|
||||
use Template;
|
||||
|
||||
/**
|
||||
* Render (deny-)login screen
|
||||
*/
|
||||
class Login
|
||||
{
|
||||
/**
|
||||
* Framework object
|
||||
*
|
||||
* @var Api\Framework
|
||||
*/
|
||||
protected $framework;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Api\Framework $framework
|
||||
*/
|
||||
function __construct(Api\Framework $framework)
|
||||
{
|
||||
$this->framework = $framework;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the login screen
|
||||
*
|
||||
* @param string $extra_vars for login url
|
||||
* @param string $change_passwd =null string with message to render input fields for password change
|
||||
*/
|
||||
function screen($extra_vars, $change_passwd=null)
|
||||
{
|
||||
Api\Header\ContentSecurityPolicy::add('frame-src', array()); // array() no external frame-sources
|
||||
|
||||
//error_log(__METHOD__."() this->template=$this->framework->template, this->template_dir=$this->framework->template_dir, get_class(this)=".get_class($this));
|
||||
$tmpl = new Template(EGW_SERVER_ROOT.$this->framework->template_dir);
|
||||
|
||||
$tmpl->set_file(array('login_form' => Api\Header\UserAgent::mobile()?'login_mobile.tpl':'login.tpl'));
|
||||
|
||||
$tmpl->set_var('lang_message',$GLOBALS['loginscreenmessage']);
|
||||
|
||||
// hide change-password fields, if not requested
|
||||
if (!$change_passwd)
|
||||
{
|
||||
$tmpl->set_block('login_form','change_password');
|
||||
$tmpl->set_var('change_password', '');
|
||||
$tmpl->set_var('lang_password',lang('password'));
|
||||
$tmpl->set_var('cd',check_logoutcode($_GET['cd']));
|
||||
$tmpl->set_var('cd_class', isset($_GET['cd']) && $_GET['cd'] != 1 ? 'error' : '');
|
||||
$last_loginid = $_COOKIE['last_loginid'];
|
||||
$last_domain = $_COOKIE['last_domain'];
|
||||
$tmpl->set_var('passwd', '');
|
||||
$tmpl->set_var('autofocus_login', 'autofocus');
|
||||
}
|
||||
else
|
||||
{
|
||||
$tmpl->set_var('lang_password',lang('Old password'));
|
||||
$tmpl->set_var('lang_new_password',lang('New password'));
|
||||
$tmpl->set_var('lang_repeat_password',lang('Repeat password'));
|
||||
$tmpl->set_var('cd', $change_passwd);
|
||||
$tmpl->set_var('cd_class', 'error');
|
||||
$last_loginid = $_POST['login'];
|
||||
$last_domain = $_POST['domain'];
|
||||
$tmpl->set_var('passwd', $_POST['passwd']);
|
||||
$tmpl->set_var('autofocus_login', '');
|
||||
$tmpl->set_var('autofocus_new_passwd', 'autofocus');
|
||||
}
|
||||
if($GLOBALS['egw_info']['server']['show_domain_selectbox'])
|
||||
{
|
||||
foreach(array_keys($GLOBALS['egw_domain']) as $domain)
|
||||
{
|
||||
$domains[$domain] = $domain;
|
||||
}
|
||||
$tmpl->set_var(array(
|
||||
'lang_domain' => lang('domain'),
|
||||
'select_domain' => Api\Html::select('logindomain',$last_domain,$domains,true,'tabindex="2"',0,false),
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* trick to make domain section disapear */
|
||||
$tmpl->set_block('login_form','domain_selection');
|
||||
$tmpl->set_var('domain_selection',$GLOBALS['egw_info']['user']['domain'] ?
|
||||
Api\Html::input_hidden('logindomain',$GLOBALS['egw_info']['user']['domain']) : '');
|
||||
|
||||
if($last_loginid !== '')
|
||||
{
|
||||
reset($GLOBALS['egw_domain']);
|
||||
list($default_domain) = each($GLOBALS['egw_domain']);
|
||||
|
||||
if(!empty ($last_domain) && $last_domain != $default_domain)
|
||||
{
|
||||
$last_loginid .= '@' . $last_domain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$config_reg = Api\Config::read('registration');
|
||||
|
||||
if($config_reg['enable_registration'])
|
||||
{
|
||||
if ($config_reg['register_link'])
|
||||
{
|
||||
$reg_link=' <a href="'. $this->framework->link('/registration/index.php','lang_code='.$_GET['lang']). '">'.lang('Not a user yet? Register now').'</a><br/>';
|
||||
}
|
||||
if ($config_reg['lostpassword_link'])
|
||||
{
|
||||
$lostpw_link=' <a href="'. $this->framework->link('/registration/index.php','menuaction=registration.registration_ui.lost_password&lang_code='.$_GET['lang']). '">'.lang('Lost password').'</a><br/>';
|
||||
}
|
||||
if ($config_reg['lostid_link'])
|
||||
{
|
||||
$lostid_link=' <a href="'. $this->framework->link('/registration/index.php','menuaction=registration.registration_ui.lost_username&lang_code='.$_GET['lang']). '">'.lang('Lost Login Id').'</a><br/>';
|
||||
}
|
||||
|
||||
/* if at least one option of "registration" is activated display the registration section */
|
||||
if($config_reg['register_link'] || $config_reg['lostpassword_link'] || $config_reg['lostid_link'] )
|
||||
{
|
||||
$tmpl->set_var(array(
|
||||
'register_link' => $reg_link,
|
||||
'lostpassword_link' => $lostpw_link,
|
||||
'lostid_link' => $lostid_link,
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* trick to make registration section disapear */
|
||||
$tmpl->set_block('login_form','registration');
|
||||
$tmpl->set_var('registration','');
|
||||
}
|
||||
}
|
||||
|
||||
$tmpl->set_var('login_url', $GLOBALS['egw_info']['server']['webserver_url'] . '/login.php' . $extra_vars);
|
||||
$tmpl->set_var('version', $GLOBALS['egw_info']['server']['versions']['phpgwapi']);
|
||||
$tmpl->set_var('login', $last_loginid);
|
||||
|
||||
$tmpl->set_var('lang_username',lang('username'));
|
||||
$tmpl->set_var('lang_login',lang('login'));
|
||||
|
||||
$tmpl->set_var('website_title', $GLOBALS['egw_info']['server']['site_title']);
|
||||
$tmpl->set_var('template_set',$this->framework->template);
|
||||
|
||||
if (substr($GLOBALS['egw_info']['server']['login_logo_file'], 0, 4) == 'http' ||
|
||||
$GLOBALS['egw_info']['server']['login_logo_file'][0] == '/')
|
||||
{
|
||||
$var['logo_file'] = $GLOBALS['egw_info']['server']['login_logo_file'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$var['logo_file'] = Api\Image::find('phpgwapi',$GLOBALS['egw_info']['server']['login_logo_file']?$GLOBALS['egw_info']['server']['login_logo_file']:'logo', '', null); // null=explicit allow svg
|
||||
}
|
||||
$var['logo_url'] = $GLOBALS['egw_info']['server']['login_logo_url']?$GLOBALS['egw_info']['server']['login_logo_url']:'http://www.egroupware.org';
|
||||
if (substr($var['logo_url'],0,4) != 'http')
|
||||
{
|
||||
$var['logo_url'] = 'http://'.$var['logo_url'];
|
||||
}
|
||||
$var['logo_title'] = $GLOBALS['egw_info']['server']['login_logo_title']?$GLOBALS['egw_info']['server']['login_logo_title']:'www.eGroupWare.org';
|
||||
$tmpl->set_var($var);
|
||||
|
||||
/* language section if activated in site Config */
|
||||
if (@$GLOBALS['egw_info']['server']['login_show_language_selection'])
|
||||
{
|
||||
$tmpl->set_var(array(
|
||||
'lang_language' => lang('Language'),
|
||||
'select_language' => Api\Html::select('lang',$GLOBALS['egw_info']['user']['preferences']['common']['lang'],
|
||||
Api\Translation::get_installed_langs(),true,'tabindex="1"',0,false),
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
$tmpl->set_block('login_form','language_select');
|
||||
$tmpl->set_var('language_select','');
|
||||
}
|
||||
|
||||
/********************************************************\
|
||||
* Check if authentification via cookies is allowed *
|
||||
* and place a time selectbox, how long cookie is valid *
|
||||
\********************************************************/
|
||||
|
||||
if($GLOBALS['egw_info']['server']['allow_cookie_auth'])
|
||||
{
|
||||
$tmpl->set_block('login_form','remember_me_selection');
|
||||
$tmpl->set_var('lang_remember_me',lang('Remember me'));
|
||||
$tmpl->set_var('select_remember_me',Api\Html::select('remember_me', '', array(
|
||||
'' => lang('not'),
|
||||
'1hour' => lang('1 Hour'),
|
||||
'1day' => lang('1 Day'),
|
||||
'1week'=> lang('1 Week'),
|
||||
'1month' => lang('1 Month'),
|
||||
'forever' => lang('Forever'),
|
||||
),true,'tabindex="3"',0,false));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* trick to make remember_me section disapear */
|
||||
$tmpl->set_block('login_form','remember_me_selection');
|
||||
$tmpl->set_var('remember_me_selection','');
|
||||
}
|
||||
$tmpl->set_var('autocomplete', ($GLOBALS['egw_info']['server']['autocomplete_login'] ? 'autocomplete="off"' : ''));
|
||||
|
||||
// load jquery for login screen too
|
||||
Api\Framework::includeJS('jquery', 'jquery');
|
||||
|
||||
$this->framework->render($tmpl->fp('loginout','login_form'),false,false);
|
||||
}
|
||||
|
||||
/**
|
||||
* displays a login denied message
|
||||
*/
|
||||
function denylogin_screen()
|
||||
{
|
||||
$tmpl = new Template(EGW_SERVER_ROOT.$this->framework->template_dir);
|
||||
|
||||
$tmpl->set_file(array(
|
||||
'login_form' => 'login_denylogin.tpl'
|
||||
));
|
||||
|
||||
$tmpl->set_var(array(
|
||||
'template_set' => 'default',
|
||||
'deny_msg' => lang('Oops! You caught us in the middle of system maintainance.').
|
||||
'<br />'.lang('Please, check back with us shortly.'),
|
||||
));
|
||||
|
||||
// load jquery for deny-login screen too
|
||||
Api\Framework::includeJS('jquery', 'jquery');
|
||||
|
||||
$this->framework->render($tmpl->fp('loginout','login_form'),false,false);
|
||||
}
|
||||
}
|
147
api/src/Framework/Updates.php
Normal file
147
api/src/Framework/Updates.php
Normal file
@ -0,0 +1,147 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware API - Check for updates
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage framework
|
||||
* @access public
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Framework;
|
||||
|
||||
use EGroupware\Api\Html;
|
||||
use EGroupware\Api\Cache;
|
||||
use EGroupware\Api;
|
||||
|
||||
/**
|
||||
* Check for updates
|
||||
*/
|
||||
class Updates
|
||||
{
|
||||
/**
|
||||
* URL to check for security or maintenance updates
|
||||
*/
|
||||
const CURRENT_VERSION_URL = 'http://www.egroupware.org/currentversion';
|
||||
/**
|
||||
* How long to cache (in secs) / often to check for updates
|
||||
*/
|
||||
const VERSIONS_CACHE_TIMEOUT = 7200;
|
||||
/**
|
||||
* After how many days of not applied security updates, start warning non-admins too
|
||||
*/
|
||||
const WARN_USERS_DAYS = 3;
|
||||
|
||||
/**
|
||||
* Get versions of available updates
|
||||
*
|
||||
* @return array verions for keys "current" and "security"
|
||||
*/
|
||||
public static function available()
|
||||
{
|
||||
$versions = Cache::getTree(__CLASS__, 'versions', function()
|
||||
{
|
||||
$versions = array();
|
||||
$security = null;
|
||||
if (($remote = file_get_contents(self::CURRENT_VERSION_URL, false, Api\Framework::proxy_context())))
|
||||
{
|
||||
list($current, $security) = explode("\n", $remote);
|
||||
if (empty($security)) $security = $current;
|
||||
$versions = array(
|
||||
'current' => $current, // last maintenance update
|
||||
'security' => $security, // last security update
|
||||
);
|
||||
}
|
||||
return $versions;
|
||||
}, array(), self::VERSIONS_CACHE_TIMEOUT);
|
||||
|
||||
return $versions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check update status
|
||||
*
|
||||
* @return string
|
||||
* @todo Check from client-side, if server-side check fails
|
||||
*/
|
||||
public static function notification()
|
||||
{
|
||||
$versions = self::available();
|
||||
|
||||
$api = self::api_version();
|
||||
|
||||
if ($versions)
|
||||
{
|
||||
if (version_compare($api, $versions['security'], '<'))
|
||||
{
|
||||
if (!$GLOBALS['egw_info']['user']['apps']['admin'] && !self::update_older($versions['security'], self::WARN_USERS_DAYS))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return Html::a_href(Html::image('phpgwapi', 'security-update', lang('EGroupware security update %1 needs to be installed!', $versions['security'])),
|
||||
'http://www.egroupware.org/changelog', null, ' target="_blank"');
|
||||
}
|
||||
if ($GLOBALS['egw_info']['user']['apps']['admin'] && version_compare($api, $versions['current'], '<'))
|
||||
{
|
||||
return Html::a_href(Html::image('phpgwapi', 'update', lang('EGroupware maintenance update %1 available', $versions['current'])),
|
||||
'http://www.egroupware.org/changelog', null, ' target="_blank"');
|
||||
}
|
||||
}
|
||||
elseif ($GLOBALS['egw_info']['user']['apps']['admin'])
|
||||
{
|
||||
$error = lang('Automatic update check failed, you need to check manually!');
|
||||
if (!ini_get('allow_url_fopen'))
|
||||
{
|
||||
$error .= "\n".lang('%1 setting "%2" = %3 disallows access via http!',
|
||||
'php.ini', 'allow_url_fopen', array2string(ini_get('allow_url_fopen')));
|
||||
}
|
||||
return Html::a_href(Html::image('phpgwapi', 'update', $error),
|
||||
'http://www.egroupware.org/changelog', null, ' target="_blank" data-api-version="'.$api.'"');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if version is older then $days days
|
||||
*
|
||||
* @param string $version eg. "14.1.20140715" last part is checked (only if > 20140000!)
|
||||
* @param int $days
|
||||
* @return boolean
|
||||
*/
|
||||
protected static function update_older($version, $days)
|
||||
{
|
||||
list(,,$date) = explode('.', $version);
|
||||
if ($date < 20140000) return false;
|
||||
$version_timestamp = mktime(0, 0, 0, (int)substr($date, 4, 2), (int)substr($date, -2), (int)substr($date, 0, 4));
|
||||
|
||||
return (time() - $version_timestamp) / 86400 > $days;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current API version from changelog or database, whichever is bigger
|
||||
*
|
||||
* @param string &$changelog on return path to changelog
|
||||
* @return string
|
||||
*/
|
||||
public static function api_version(&$changelog=null)
|
||||
{
|
||||
$changelog = EGW_SERVER_ROOT.'/doc/rpm-build/debian.changes';
|
||||
|
||||
return Cache::getTree(__CLASS__, 'api_version', function() use ($changelog)
|
||||
{
|
||||
$version = preg_replace('/[^0-9.]/', '', $GLOBALS['egw_info']['server']['versions']['phpgwapi']);
|
||||
// parse version from changelog
|
||||
$matches = null;
|
||||
if (($f = fopen($changelog, 'r')) && preg_match('/egroupware-epl \(([0-9.]+)/', fread($f, 80), $matches) &&
|
||||
version_compare($version, $matches[1], '<'))
|
||||
{
|
||||
$version = $matches[1];
|
||||
fclose($f);
|
||||
}
|
||||
return $version;
|
||||
}, array(), 300);
|
||||
}
|
||||
}
|
@ -14,10 +14,6 @@
|
||||
|
||||
namespace EGroupware\Api;
|
||||
|
||||
// explicitly import classes not yet imported into Api
|
||||
use egw_framework; // validate_file, includeCSS
|
||||
use egw; // link
|
||||
|
||||
/**
|
||||
* Generates html with methods representing html-tags or higher widgets
|
||||
*
|
||||
@ -197,8 +193,8 @@ class Html
|
||||
$out .= "</select>\n";
|
||||
|
||||
if($enhanced) {
|
||||
egw_framework::validate_file('/api/js/jquery/chosen/chosen.jquery.js');
|
||||
egw_framework::includeCSS('/api/js/jquery/chosen/chosen.css',null,false);
|
||||
Framework::includeJS('/api/js/jquery/chosen/chosen.jquery.js');
|
||||
Framework::includeCSS('/api/js/jquery/chosen/chosen.css',null,false);
|
||||
$out .= "<script>var lab = egw_LAB || \$LAB; lab.wait(function() {\$j(function() {if(\$j().chosen) \$j('select[name=\"$name\"]').chosen({width: '100%'});});})</script>\n";
|
||||
}
|
||||
return $out;
|
||||
@ -433,7 +429,7 @@ class Html
|
||||
}
|
||||
|
||||
//include the ckeditor js file
|
||||
egw_framework::validate_file('ckeditor','ckeditor','phpgwapi');
|
||||
Framework::includeJS('ckeditor','ckeditor','phpgwapi');
|
||||
|
||||
// run content through htmlpurifier
|
||||
if ($_purify && !empty($_content))
|
||||
@ -675,7 +671,7 @@ egw_LAB.wait(function() {
|
||||
parse_str($v,$v);
|
||||
$vars += $v;
|
||||
}
|
||||
return egw::link($url,$vars);
|
||||
return Framework::link($url,$vars);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -890,7 +886,7 @@ egw_LAB.wait(function() {
|
||||
}
|
||||
if (substr($name,0,5) == 'vfs:/') // vfs pseudo protocoll
|
||||
{
|
||||
$name = egw::link(Vfs::download_url(substr($name,4)));
|
||||
$name = Framework::link(Vfs::download_url(substr($name,4)));
|
||||
}
|
||||
if ($name[0] == '/' || substr($name,0,7) == 'http://' || substr($name,0,8) == 'https://' || stripos($name,'api/thumbnail.php') )
|
||||
{
|
||||
@ -1087,7 +1083,7 @@ egw_LAB.wait(function() {
|
||||
* @param boolean|string $_onCheckHandler =false string with handler-name to display a checkbox for each folder, or false (default), 'null' switches checkboxes on without an handler!
|
||||
* @param string $delimiter ='/' path-delimiter, default /
|
||||
* @param string $folderImageDir =null string path to the tree menu images, null uses default path
|
||||
* @param string|array $autoLoading =null EGw relative path or array with get parameter, both send through egw::link
|
||||
* @param string|array $autoLoading =null EGw relative path or array with get parameter, both send through Framework::link
|
||||
* @param string $dataMode ='JSON' data type for autoloading: XML, JSON, CSV
|
||||
* @param boolean $dragndrop =false true to enable drag-n-drop (must be before autoloading get enabled!)
|
||||
*
|
||||
@ -1121,10 +1117,10 @@ egw_LAB.wait(function() {
|
||||
static $tree_initialised=false;
|
||||
if (!$tree_initialised)
|
||||
{
|
||||
egw_framework::includeCSS('/api/js/dhtmlxtree/codebase/dhtmlxtree.css');
|
||||
egw_framework::validate_file('/api/js/dhtmlxtree/codebase/dhtmlxcommon.js');
|
||||
egw_framework::validate_file('/api/js/dhtmlxtree/sources/dhtmlxtree.js');
|
||||
if ($autoLoading && $dataMode != 'XML') egw_framework::validate_file('/api/js/dhtmlxtree/sources/ext/dhtmlxtree_json.js');
|
||||
Framework::includeCSS('/api/js/dhtmlxtree/codebase/dhtmlxtree.css');
|
||||
Framework::includeJS('/api/js/dhtmlxtree/codebase/dhtmlxcommon.js');
|
||||
Framework::includeJS('/api/js/dhtmlxtree/sources/dhtmlxtree.js');
|
||||
if ($autoLoading && $dataMode != 'XML') Framework::includeJS('/api/js/dhtmlxtree/sources/ext/dhtmlxtree_json.js');
|
||||
$tree_initialised = true;
|
||||
if (!$_folders && !$autoLoading) return null;
|
||||
}
|
||||
@ -1148,7 +1144,7 @@ egw_LAB.wait(function() {
|
||||
if ($autoLoading)
|
||||
{
|
||||
$autoLoading = is_array($autoLoading) ?
|
||||
egw::link('/index.php',$autoLoading) : egw::link($autoLoading);
|
||||
Framework::link('/index.php',$autoLoading) : Framework::link($autoLoading);
|
||||
$html .= "$tree.setXMLAutoLoading('$autoLoading');\n";
|
||||
if ($dataMode != 'XML') $html .= "$tree.setDataMode('$dataMode');\n";
|
||||
|
||||
|
@ -18,7 +18,6 @@ use EGroupware\Api;
|
||||
|
||||
// explicitly import old, not yet ported api classes
|
||||
use notifications_push;
|
||||
use egw_framework;
|
||||
|
||||
/**
|
||||
* Class handling JSON requests to the server
|
||||
@ -174,7 +173,7 @@ class Request
|
||||
|
||||
// for Ajax: no need to load the "standard" javascript files,
|
||||
// they are already loaded, in fact jquery has a problem if loaded twice
|
||||
egw_framework::js_files(array());
|
||||
Api\Framework::js_files(array());
|
||||
|
||||
call_user_func_array(array($ajaxClass, $functionName),
|
||||
Api\Translation::convert($parameters, 'utf-8'));
|
||||
|
@ -23,7 +23,6 @@ use ZipArchive;
|
||||
|
||||
// explicit import old, non-namespaced phpgwapi classes
|
||||
use uiaccountsel;
|
||||
use egw; // link
|
||||
|
||||
/**
|
||||
* Document merge print
|
||||
@ -345,11 +344,11 @@ abstract class Merge
|
||||
if($link_info['app'] != Api\Link::VFS_APPNAME)
|
||||
{
|
||||
// Set app to false so we always get an external link
|
||||
$link = str_replace(',','%2C',egw::link('/index.php',$link, false));
|
||||
$link = str_replace(',', '%2C', $GLOBALS['egw']->framework->link('/index.php',$link, false));
|
||||
}
|
||||
else
|
||||
{
|
||||
$link = egw::link($link, array());
|
||||
$link = Api\Framework::link($link, array());
|
||||
}
|
||||
// Prepend site
|
||||
if ($link{0} == '/')
|
||||
@ -404,11 +403,11 @@ abstract class Merge
|
||||
if($app != Api\Link::VFS_APPNAME)
|
||||
{
|
||||
// Set app to false so we always get an external link
|
||||
$link = str_replace(',','%2C',egw::link('/index.php',$link, false));
|
||||
$link = str_replace(',', '%2C', $GLOBALS['egw']->framework->link('/index.php',$link, false));
|
||||
}
|
||||
else
|
||||
{
|
||||
$link = egw::link($link, array());
|
||||
$link = Api\Framework::link($link, array());
|
||||
}
|
||||
// Prepend site
|
||||
if ($link{0} == '/')
|
||||
|
@ -16,10 +16,6 @@ namespace EGroupware\Api\Vfs;
|
||||
use EGroupware\Api;
|
||||
use EGroupware\Api\Vfs;
|
||||
|
||||
// explicitly list old, not yet ported api classes
|
||||
use egw_framework;
|
||||
use egw; // link
|
||||
|
||||
use filemanager_ui;
|
||||
|
||||
/**
|
||||
@ -357,7 +353,7 @@ class Sharing
|
||||
$GLOBALS['egw_info']['user']['preferences']['filemanager']['nm_view'] = 'tile';
|
||||
$_GET['cd'] = 'no';
|
||||
$GLOBALS['egw_info']['flags']['js_link_registry'] = true;
|
||||
egw_framework::includeCSS('filemanager', 'sharing');
|
||||
Api\Framework::includeCSS('filemanager', 'sharing');
|
||||
$ui = new SharingUi();
|
||||
$ui->index();
|
||||
}
|
||||
@ -657,7 +653,7 @@ class Sharing
|
||||
{
|
||||
if (is_array($share)) $share = $share['share_token'];
|
||||
|
||||
$link = egw::link('/share.php').'/'.$share;
|
||||
$link = Api\Framework::link('/share.php').'/'.$share;
|
||||
if ($link[0] == '/')
|
||||
{
|
||||
$link = ($_SERVER['HTTPS'] ? 'https://' : 'http://').
|
||||
|
@ -29,11 +29,16 @@ $replace = array(
|
||||
"#\\\$GLOBALS\['egw'\]->session->appsession\(([^,]+),\s*('[^']+'),\s*#" => 'Api\\Cache::setSession($2, $1, ',
|
||||
"#\\\$GLOBALS\['egw'\]->common->#" => 'common::',
|
||||
"#\\\$GLOBALS\['egw'\]->hooks->#" => 'Api\\Hooks::',
|
||||
'#Api\\Hooks::hook_implemented#' => 'Api\\Hooks::implemented',
|
||||
"#\\\$GLOBALS\['egw'\]->translation->#" => 'Api\\Translation::',
|
||||
'#egw_framework::csp_script_src_attrs\((.*)\);#' => "Api\\Header\\ContentSecurityPolicy::add('script-src', \$1);",
|
||||
'#egw_framework::csp_style_src_attrs\((.*)\);#' => "Api\\Header\\ContentSecurityPolicy::add('style-src', \$1);",
|
||||
'#egw_framework::csp_connect_src_attrs\((.*)\);#' => "Api\\Header\\ContentSecurityPolicy::add('connect-src', \$1);",
|
||||
'#egw_framework::csp_frame_src_attrs\((.*)\);#' => "Api\\Header\\ContentSecurityPolicy::add('frame-src', \$1);",
|
||||
);
|
||||
// enclose class-names and static methods with some syntax check
|
||||
$class_start = '#([\[\s,;(])';
|
||||
$class_end = '(::|\\(|;|\?|:|\\s|$)#';
|
||||
$class_start = '#([\[\s,;(.!])';
|
||||
$class_end = '(::|\\(|\\)|;|\?|:|\\s|,|$)#';
|
||||
foreach(array(
|
||||
'accounts' => 'Api\\Accounts',
|
||||
'acl' => 'Api\\Acl',
|
||||
@ -88,8 +93,10 @@ foreach(array(
|
||||
'egw_exception_db' => 'Api\\Db\\Exception',
|
||||
'egw_exception_db_invalid_sql' => 'Api\\Db\\Exception\\InvalidSql',
|
||||
'egw_exception_redirect' => 'Api\\Exception\\Redirect',
|
||||
//'egw_favorites' =>
|
||||
//'egw_framework' =>
|
||||
'egw_favorites' => 'Api\\Framework\\Favorites',
|
||||
'egw_framework::validate_file' => 'Api\\Framework::includeJS',
|
||||
'egw_framework::favorite_list' => 'Api\\Framework\\Favorites::list_favorites',
|
||||
'egw_framework' => 'Api\\Framework',
|
||||
'egw_json_request' => 'Api\\Json\\Request',
|
||||
'egw_json_response' => 'Api\\Json\\Response',
|
||||
'egw_link' => 'Api\\Link',
|
||||
@ -156,14 +163,15 @@ foreach(array(
|
||||
* Check namespace usage in converted code
|
||||
*
|
||||
* @param string $file filename
|
||||
* @param boolean $dry_run =false true: only echo fixed file, not fix it
|
||||
* @return boolean false on error
|
||||
*/
|
||||
function fix_api($file)
|
||||
function fix_api($file, $dry_run=false)
|
||||
{
|
||||
global $prog, $replace;
|
||||
if (basename($file) == $prog) return true; // dont fix ourself ;-)
|
||||
|
||||
if (($content = file_get_contents($file)) === false) return false;
|
||||
if (($content = $content_in = file_get_contents($file)) === false) return false;
|
||||
|
||||
if (!preg_match("|<\?php\n/\*\*.*\*/|msU", $content))
|
||||
{
|
||||
@ -184,9 +192,15 @@ function fix_api($file)
|
||||
}
|
||||
}
|
||||
|
||||
die($content);
|
||||
if ($dry_run)
|
||||
{
|
||||
echo $content;
|
||||
}
|
||||
elseif ($content_in != $content)
|
||||
{
|
||||
file_put_contents($file, $content);
|
||||
}
|
||||
|
||||
//print_r($use);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -194,9 +208,10 @@ function fix_api($file)
|
||||
* Loop recursive through directory and call fix_api for each php file
|
||||
*
|
||||
* @param string $dir
|
||||
* @param boolean $dry_run =false true: only echo fixed file, not fix it
|
||||
* @return boolean false on error
|
||||
*/
|
||||
function fix_api_recursive($dir)
|
||||
function fix_api_recursive($dir, $dry_run=false)
|
||||
{
|
||||
if (!is_dir($dir)) return false;
|
||||
|
||||
@ -206,12 +221,12 @@ function fix_api_recursive($dir)
|
||||
|
||||
if (is_dir($dir.'/'.$file))
|
||||
{
|
||||
fix_api_recursive($dir.'/'.$file);
|
||||
fix_api_recursive($dir.'/'.$file, $dry_run);
|
||||
}
|
||||
elseif(substr($file,-4) == '.php')
|
||||
{
|
||||
echo "\r".str_repeat(' ',100)."\r".$dir.'/'.$file.': ';
|
||||
fix_api($dir.'/'.$file);
|
||||
fix_api($dir.'/'.$file, $dry_run);
|
||||
}
|
||||
}
|
||||
echo "\r".str_repeat(' ',100)."\r";
|
||||
@ -226,7 +241,7 @@ function fix_api_recursive($dir)
|
||||
function usage($error=null)
|
||||
{
|
||||
global $prog;
|
||||
echo "Usage: $prog [-h|--help] file or dir\n\n";
|
||||
echo "Usage: $prog [-h|--help] [-d|--dry-run] file or dir\n\n";
|
||||
if ($error) echo $error."\n\n";
|
||||
exit($error ? 1 : 0);
|
||||
}
|
||||
@ -236,7 +251,7 @@ $prog = basename(array_shift($args));
|
||||
|
||||
if (!$args) usage();
|
||||
|
||||
$replace_file = false;
|
||||
$dry_run = false;
|
||||
while(($arg = array_shift($args)))
|
||||
{
|
||||
switch($arg)
|
||||
@ -246,6 +261,11 @@ while(($arg = array_shift($args)))
|
||||
usage();
|
||||
break;
|
||||
|
||||
case '-d':
|
||||
case '--dry-run':
|
||||
$dry_run = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
if ($args) // not last argument
|
||||
{
|
||||
@ -259,9 +279,9 @@ if (!file_exists($arg)) usage("Error: $arg not found!");
|
||||
|
||||
if (!is_dir($arg))
|
||||
{
|
||||
fix_api($arg,$replace_file);
|
||||
fix_api($arg, $dry_run);
|
||||
}
|
||||
else
|
||||
{
|
||||
fix_api_recursive($arg,$replace_file);
|
||||
fix_api_recursive($arg, $dry_run);
|
||||
}
|
@ -479,45 +479,7 @@ class egw extends egw_minimal
|
||||
*/
|
||||
static function redirect($url, $link_app=null)
|
||||
{
|
||||
// Determines whether the current output buffer should be flushed
|
||||
$do_flush = true;
|
||||
|
||||
if (egw_json_response::isJSONResponse() || egw_json_request::isJSONRequest())
|
||||
{
|
||||
$response = egw_json_response::get();
|
||||
$response->redirect($url, false, $link_app);
|
||||
|
||||
// If we are in a json request, we should not flush the current output!
|
||||
$do_flush = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$file = $line = null;
|
||||
if (headers_sent($file,$line))
|
||||
{
|
||||
throw new Api\Exception\AssertionFailed(__METHOD__."('".htmlspecialchars($url)."') can NOT redirect, output already started at $file line $line!");
|
||||
}
|
||||
if ($GLOBALS['egw']->framework instanceof jdots_framework && !empty($link_app))
|
||||
{
|
||||
egw_framework::set_extra('egw', 'redirect', array($url, $link_app));
|
||||
$GLOBALS['egw']->framework->render('');
|
||||
}
|
||||
else
|
||||
{
|
||||
Header("Location: $url");
|
||||
print("\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
if ($do_flush)
|
||||
{
|
||||
@ob_flush(); flush();
|
||||
}
|
||||
|
||||
// commit session (if existing), to fix timing problems sometimes preventing session creation ("Your session can not be verified")
|
||||
if (isset($GLOBALS['egw']->session)) $GLOBALS['egw']->session->commit_session();
|
||||
|
||||
exit;
|
||||
Api\Framework::redirect($url, $link_app);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware API - favorites
|
||||
* EGroupware API - Favorites server-side
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @author Nathan Gray <ng@stylite.de>
|
||||
@ -11,246 +11,11 @@
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
use EGroupware\Api\Framework\Favorites;
|
||||
|
||||
/**
|
||||
* EGroupware favorites service-side:
|
||||
* Favorites service-side
|
||||
*
|
||||
* Favorites are generated on serverside by following code in apps sidebox hook:
|
||||
*
|
||||
* display_sidebox($appname, lang('Favorites'), egw_favorites::favorite_list($appname));
|
||||
*
|
||||
* Clientside code resides in:
|
||||
* - phpgwapi/js/jsapi/app_base.js
|
||||
* - etemplate/js/et2_widget_favorites.js
|
||||
*
|
||||
* Favorites are stored with prefix "favorite_" in app preferences.
|
||||
* @deprecated use Api\Framework\Favorites
|
||||
*/
|
||||
class egw_favorites
|
||||
{
|
||||
/**
|
||||
* Include favorites when generating the page server-side
|
||||
*
|
||||
* Use this function in your sidebox (or anywhere else, I suppose) to
|
||||
* get the favorite list when a nextmatch is _not_ on the page. If
|
||||
* a nextmatch is on the page, it will update / replace this list.
|
||||
*
|
||||
* @param string $app application, needed to find preferences
|
||||
* @param string $default preference name for default favorite, default "nextmatch-$app.index.rows-favorite"
|
||||
*
|
||||
* @return array with a single sidebox menu item (array) containing html for favorites
|
||||
*/
|
||||
public static function list_favorites($app, $default=null)
|
||||
{
|
||||
if (!$app)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!$default)
|
||||
{
|
||||
$default = "nextmatch-$app.index.rows-favorite";
|
||||
}
|
||||
|
||||
// This target is used client-side to find & enable adding new favorites
|
||||
$target = 'favorite_sidebox_'.$app;
|
||||
|
||||
/* @var $filters array an array of favorites*/
|
||||
$filters = self::get_favorites($app);
|
||||
$is_admin = $GLOBALS['egw_info']['user']['apps']['admin'];
|
||||
$html = "<span id='$target' class='ui-helper-clearfix sidebox-favorites'><ul class='ui-menu ui-widget-content ui-corner-all favorites' role='listbox'>\n";
|
||||
|
||||
$default_filter = $GLOBALS['egw_info']['user']['preferences'][$app][$default];
|
||||
if (!isset($default_filter) || !isset($filters[$default_filter]))
|
||||
{
|
||||
$default_filter = "blank";
|
||||
}
|
||||
|
||||
// Get link for if there is no nextmatch - this is the fallback
|
||||
$registry = egw_link::get_registry($app,'list');
|
||||
if (!$registry)
|
||||
{
|
||||
$registry = egw_link::get_registry($app, 'index');
|
||||
}
|
||||
foreach($filters as $name => $filter)
|
||||
{
|
||||
//filter must not be empty if there's one, ignore it at the moment but it need to be checked how it got there in database
|
||||
if (!$filter)
|
||||
{
|
||||
error_log(__METHOD__.'Favorite filter "'.$name.'" is not supposed to be empty, it should be an array. Skipping, more investigation needed. filter = '. array2string($filters[$name]));
|
||||
continue;
|
||||
}
|
||||
$li = "<li data-id='$name' data-group='{$filter['group']}' class='ui-menu-item' role='menuitem'>\n";
|
||||
$li .= '<a href="#" class="ui-corner-all" tabindex="-1">';
|
||||
$li .= "<div class='" . ((string)$name === (string)$default_filter ? 'ui-icon ui-icon-heart' : 'sideboxstar') . "'></div>".
|
||||
$filter['name'];
|
||||
$li .= ($filter['group'] != false && !$is_admin || $name === 'blank' ? "" :
|
||||
"<div class='ui-icon ui-icon-trash' title='" . lang('Delete') . "'></div>");
|
||||
$li .= "</a></li>\n";
|
||||
//error_log(__METHOD__."() $name, filter=".array2string($filter)." --> ".$li);
|
||||
$html .= $li;
|
||||
}
|
||||
|
||||
// If were're here, the app supports favorites, so add a 'Add' link too
|
||||
$html .= "<li data-id='add' class='ui-menu-item' role='menuitem'><a href='javascript:app.$app.add_favorite()' class='ui-corner-all'>";
|
||||
$html .= html::image($app, 'new') . lang('Add current'). '</a></li>';
|
||||
|
||||
$html .= '</ul></span>';
|
||||
|
||||
return array(
|
||||
array(
|
||||
'no_lang' => true,
|
||||
'text' => $html,
|
||||
'link' => false,
|
||||
'icon' => false,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get preferenced favorites sorted list
|
||||
*
|
||||
* @param string $app Application name as string
|
||||
*
|
||||
* @return (array|boolean) An array of sorted favorites or False if there's no preferenced sorted list
|
||||
*
|
||||
*/
|
||||
public static function get_fav_sort_pref ($app)
|
||||
{
|
||||
$fav_sorted_list = array();
|
||||
|
||||
if (($fav_sorted_list = $GLOBALS['egw_info']['user']['preferences'][$app]['fav_sort_pref']))
|
||||
{
|
||||
return $fav_sorted_list;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of actual user favorites
|
||||
* The default 'Blank' favorite is not included here
|
||||
*
|
||||
* @param string $app Current application
|
||||
*
|
||||
* @return array Favorite information
|
||||
*/
|
||||
public static function get_favorites($app)
|
||||
{
|
||||
$favorites = array(
|
||||
'blank' => array(
|
||||
'name' => lang('No filters'),
|
||||
// Old
|
||||
'filter' => array(),
|
||||
// New
|
||||
'state' => array(),
|
||||
'group' => true
|
||||
)
|
||||
);
|
||||
$pref_prefix = 'favorite_';
|
||||
|
||||
$sorted_list = array();
|
||||
$fav_sort_pref = self::get_fav_sort_pref($app);
|
||||
|
||||
// Look through all preferences & pull out favorites
|
||||
foreach((array)$GLOBALS['egw_info']['user']['preferences'][$app] as $pref_name => $pref)
|
||||
{
|
||||
if(strpos($pref_name, $pref_prefix) === 0)
|
||||
{
|
||||
if(!is_array($pref)) continue; // old favorite
|
||||
|
||||
$favorites[(string)substr($pref_name,strlen($pref_prefix))] = $pref;
|
||||
}
|
||||
}
|
||||
if (is_array($fav_sort_pref))
|
||||
{
|
||||
foreach ($fav_sort_pref as $key)
|
||||
{
|
||||
$sorted_list[$key] = $favorites[$key];
|
||||
}
|
||||
$favorites = array_merge($sorted_list,$favorites);
|
||||
}
|
||||
return $favorites;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create or delete a favorite for multiple users
|
||||
*
|
||||
* Current user needs to be an admin or it will just do nothing quietly
|
||||
*
|
||||
* @param string $app Current application, needed to save preference
|
||||
* @param string $_name Name of the favorite
|
||||
* @param string $action "add" or "delete"
|
||||
* @param boolean|int|String $group ID of the group to create the favorite for, or 'all' for all users
|
||||
* @param array $filters key => value pairs for the filter
|
||||
* @return boolean Success
|
||||
*/
|
||||
public static function set_favorite($app, $_name, $action, $group, $filters = array())
|
||||
{
|
||||
// Only use alphanumeric for preference name, so it can be used directly as DOM ID
|
||||
$name = strip_tags($_name);
|
||||
$pref_name = "favorite_".$name;
|
||||
|
||||
// older group-favorites have just true as their group and are not deletable, if we dont find correct group
|
||||
if ($group === true || $group === '1')
|
||||
{
|
||||
if (isset($GLOBALS['egw']->preferences->default[$app][$pref_name]))
|
||||
{
|
||||
$group = 'all';
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach($GLOBALS['egw']->accounts->memberships($GLOBALS['egw_info']['user']['account_id'], true) as $gid)
|
||||
{
|
||||
$prefs = new preferences($gid);
|
||||
$prefs->read_repository();
|
||||
if (isset($prefs->user[$app][$pref_name]))
|
||||
{
|
||||
$group = $gid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if($group && $GLOBALS['egw_info']['apps']['admin'] && $group !== 'all')
|
||||
{
|
||||
$prefs = new preferences(is_numeric($group) ? $group : $GLOBALS['egw_info']['user']['account_id']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$prefs = $GLOBALS['egw']->preferences;
|
||||
}
|
||||
$prefs->read_repository();
|
||||
$type = $group === "all" ? "default" : "user";
|
||||
//error_log(__METHOD__."('$app', '$name', '$action', ".array2string($group).", ...) pref_name=$pref_name, type=$type");
|
||||
if($action == "add")
|
||||
{
|
||||
$filters = array(
|
||||
// This is the name as user entered it, minus tags
|
||||
'name' => $name,
|
||||
'group' => $group ? $group : false,
|
||||
'state' => $filters
|
||||
);
|
||||
$pref_name = "favorite_".preg_replace('/[^A-Za-z0-9-_]/','_',$name);
|
||||
$result = $prefs->add($app,$pref_name,$filters,$type);
|
||||
$pref = $prefs->save_repository(false,$type);
|
||||
|
||||
// Update preferences client side, or it could disappear
|
||||
egw_json_response::get()->call('egw.set_preferences', (array)$pref[$app], $app);
|
||||
|
||||
egw_json_response::get()->data(isset($result[$app][$pref_name]));
|
||||
return isset($result[$app][$pref_name]);
|
||||
}
|
||||
else if ($action == "delete")
|
||||
{
|
||||
$result = $prefs->delete($app,$pref_name, $type);
|
||||
$pref = $prefs->save_repository(false,$type);
|
||||
|
||||
// Update preferences client side, or it could come back
|
||||
egw_json_response::get()->call('egw.set_preferences', (array)$pref[$app], $app);
|
||||
|
||||
egw_json_response::get()->data(!isset($result[$app][$pref_name]));
|
||||
return !isset($result[$app][$pref_name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
class egw_favorites extends Favorites {}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -13,6 +13,8 @@
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
use EGroupware\Api;
|
||||
|
||||
/**
|
||||
* Stylite Pixelegg template
|
||||
*/
|
||||
@ -46,7 +48,7 @@ class pixelegg_framework extends jdots_framework
|
||||
parent::__construct($template); // call the constructor of the extended class
|
||||
|
||||
// search 'mobile' dirs first
|
||||
if (html::$ua_mobile) array_unshift ($this->template_dirs, 'mobile');
|
||||
if (Api\Header\UserAgent::mobile()) array_unshift ($this->template_dirs, 'mobile');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -61,9 +63,9 @@ class pixelegg_framework extends jdots_framework
|
||||
{
|
||||
// load our slider.js, but only if framework requested
|
||||
if (!self::$header_done && $_GET['cd'] === 'yes' &&
|
||||
!(html::$ua_mobile || $GLOBALS['egw_info']['user']['preferences']['common']['theme'] == 'mobile'))
|
||||
!(Api\Header\UserAgent::mobile() || $GLOBALS['egw_info']['user']['preferences']['common']['theme'] == 'mobile'))
|
||||
{
|
||||
self::validate_file('/pixelegg/js/slider.js');
|
||||
self::includeJS('/pixelegg/js/slider.js');
|
||||
}
|
||||
return parent::header($extra);
|
||||
}
|
||||
@ -97,7 +99,7 @@ class pixelegg_framework extends jdots_framework
|
||||
/**
|
||||
* Overwrite to NOT add customizable colors from jDots
|
||||
*
|
||||
* @see egw_framework::_get_css()
|
||||
* @see Api\Framework::_get_css()
|
||||
* @return array
|
||||
*/
|
||||
public function _get_css()
|
||||
@ -131,7 +133,7 @@ class pixelegg_framework extends jdots_framework
|
||||
|
||||
if (preg_match('/^(#[0-9A-F]+|[A-Z]+)$/i',$color)) // a little xss check
|
||||
{
|
||||
if (!html::$ua_mobile)
|
||||
if (!Api\Header\UserAgent::mobile())
|
||||
{
|
||||
$ret['app_css'] .= "
|
||||
/**
|
||||
|
@ -10,6 +10,8 @@
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
use EGroupware\Api\Framework\Bundle;
|
||||
|
||||
if (php_sapi_name() !== 'cli') die("This is a commandline ONLY tool!\n");
|
||||
|
||||
$GLOBALS['egw_info'] = array(
|
||||
@ -35,7 +37,7 @@ if (!preg_match('/grunt\.initConfig\(({.+})\);/s', $content, $matches) ||
|
||||
|
||||
$uglify =& $config['uglify'];
|
||||
|
||||
foreach(egw_framework::get_bundles() as $name => $files)
|
||||
foreach(Bundle::all() as $name => $files)
|
||||
{
|
||||
if ($name == '.ts') continue; // ignore timestamp
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user