Author: ralfbecker
New Revision: 55603
URL: http://svn.stylite.de/viewvc/egroupware?rev=55603&view=rev
Log:
move hooks class to api and only cache hooks in instance cache (instead of database: filesystem scan takes ~4ms, cache ~0.2ms)
Added:
trunk/egroupware/api/setup/
trunk/egroupware/api/setup/setup.inc.php
- copied, changed from r55602, trunk/phpgwapi/setup/setup.inc.php
trunk/egroupware/api/src/Hooks.php
- copied, changed from r55599, trunk/phpgwapi/inc/class.hooks.inc.php
trunk/egroupware/api/src/Mail/Hooks.php
- copied, changed from r55599, trunk/emailadmin/inc/class.emailadmin_hooks.inc.php
trunk/egroupware/api/src/Vfs/Hooks.php
- copied, changed from r55599, trunk/phpgwapi/inc/class.vfs_home_hooks.inc.php
Removed:
trunk/emailadmin/inc/class.emailadmin_hooks.inc.php
trunk/phpgwapi/inc/class.vfs_home_hooks.inc.php
Modified:
trunk/admin/inc/class.admin_hooks.inc.php
trunk/emailadmin/setup/setup.inc.php
trunk/phpgwapi/inc/class.hooks.inc.php
trunk/phpgwapi/setup/setup.inc.php
trunk/phpgwapi/setup/tables_current.inc.php
trunk/phpgwapi/setup/tables_update.inc.php
trunk/setup/inc/class.setup.inc.php
trunk/setup/inc/class.setup_cmd_ldap.inc.php
— trunk/admin/inc/class.admin_hooks.inc.php (original)
+++ trunk/admin/inc/class.admin_hooks.inc.php Sat Apr 2 16:16:20 2016
@@ -20,10 +20,10 @@
/**
* Functions callable via menuaction
*
-
-
@var array
*/
var $public_functions = array(
-
'ajax_clear_cache' => True,
);
/**
@@ -118,7 +118,7 @@
‘id’ => ‘admin/clear_cache’,
‘no_lang’ => true,
‘link’ => “javascript:egw.message(’”.lang(‘Clear cache and register hooks’) . “
” .lang(‘Please wait…’)."’,‘info’); " .
@@ -159,9 +159,9 @@
}
/**
-
- */
- function ajax_register_all_hooks()
-
- Clears instance cache (and thereby also refreshes hooks)
- */
- function ajax_clear_cache()
{
if ($GLOBALS[‘egw’]->acl->check(‘applications_acc’,16,‘admin’))
{
@@ -169,8 +169,6 @@
}
Api\Cache::flush(Api\Cache::INSTANCE);
-
$GLOBALS['egw']->hooks->register_all_hooks();
-
Api\Image::invalidate();
if (method_exists($GLOBALS['egw'],'invalidate_session_cache')) // egw object in setup is limited
@@ -178,9 +176,9 @@
$GLOBALS[‘egw’]->invalidate_session_cache(); // in case with cache the egw_info array in the session
}
// allow apps to hook into “Admin >> Clear cache and register hooks”
-
$GLOBALS['egw']->hooks->process('clear_cache', array(), true);
-
-
egw_json_response::get()->apply('egw.message', array(lang('Done'),'success'));
-
Api\Hooks::process('clear_cache', array(), true);
-
-
Api\Json\Response::get()->apply('egw.message', array(lang('Done'), 'success'));
}
/**
— trunk/phpgwapi/setup/setup.inc.php (original)
+++ trunk/egroupware/api/setup/setup.inc.php Sat Apr 2 16:16:20 2016
@@ -10,61 +10,111 @@
*/
/* Basic information about this app */
-$setup_info[‘phpgwapi’][‘name’] = ‘phpgwapi’;
-$setup_info[‘phpgwapi’][‘title’] = ‘EGroupware API’;
-$setup_info[‘phpgwapi’][‘version’] = ‘14.3.906’;
-$setup_info[‘phpgwapi’][‘versions’][‘current_header’] = ‘1.29’;
-$setup_info[‘phpgwapi’][‘enable’] = 3;
-$setup_info[‘phpgwapi’][‘app_order’] = 1;
-$setup_info[‘phpgwapi’][‘license’] = ‘GPL’;
-$setup_info[‘phpgwapi’][‘maintainer’] = $setup_info[‘phpgwapi’][‘author’] = array(
+$setup_info[‘api’][‘name’] = ‘api’;
+$setup_info[‘api’][‘title’] = ‘EGroupware API’;
+$setup_info[‘api’][‘version’] = ‘14.3.907’;
+$setup_info[‘api’][‘versions’][‘current_header’] = ‘1.29’;
+$setup_info[‘api’][‘enable’] = 3;
+$setup_info[‘api’][‘app_order’] = 1;
+$setup_info[‘api’][‘license’] = ‘GPL’;
+$setup_info[‘api’][‘maintainer’] = $setup_info[‘api’][‘author’] = array(
‘name’ => ‘EGroupware coreteam’,
‘email’ => ‘egroupware-developers@lists.sourceforge.net’,
);
-/* The tables this app creates /
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_config’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_applications’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_acl’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_accounts’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_preferences’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_access_log’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_hooks’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_languages’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_lang’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_nextid’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_categories’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_history_log’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_async’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_links’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_addressbook’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_addressbook_extra’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_addressbook_lists’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_addressbook2list’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_sqlfs’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_index_keywords’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_index’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_cat2entry’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_locks’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_sqlfs_props’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_customfields’;
-$setup_info[‘phpgwapi’][‘tables’][] = ‘egw_sharing’;
+/ The tables this app creates
+$setup_info[‘api’][‘tables’][] = ‘egw_config’;
+$setup_info[‘api’][‘tables’][] = ‘egw_applications’;
+$setup_info[‘api’][‘tables’][] = ‘egw_acl’;
+$setup_info[‘api’][‘tables’][] = ‘egw_accounts’;
+$setup_info[‘api’][‘tables’][] = ‘egw_preferences’;
+$setup_info[‘api’][‘tables’][] = ‘egw_access_log’;
+$setup_info[‘api’][‘tables’][] = ‘egw_languages’;
+$setup_info[‘api’][‘tables’][] = ‘egw_lang’;
+$setup_info[‘api’][‘tables’][] = ‘egw_nextid’;
+$setup_info[‘api’][‘tables’][] = ‘egw_categories’;
+$setup_info[‘api’][‘tables’][] = ‘egw_history_log’;
+$setup_info[‘api’][‘tables’][] = ‘egw_async’;
+$setup_info[‘api’][‘tables’][] = ‘egw_links’;
+$setup_info[‘api’][‘tables’][] = ‘egw_addressbook’;
+$setup_info[‘api’][‘tables’][] = ‘egw_addressbook_extra’;
+$setup_info[‘api’][‘tables’][] = ‘egw_addressbook_lists’;
+$setup_info[‘api’][‘tables’][] = ‘egw_addressbook2list’;
+$setup_info[‘api’][‘tables’][] = ‘egw_sqlfs’;
+$setup_info[‘api’][‘tables’][] = ‘egw_locks’;
+$setup_info[‘api’][‘tables’][] = ‘egw_sqlfs_props’;
+$setup_info[‘api’][‘tables’][] = ‘egw_customfields’;
+$setup_info[‘api’][‘tables’][] = ‘egw_sharing’;
+*/
+// hooks used by vfs_home_hooks to manage user- and group-directories for the new stream based VFS
+$setup_info[‘api’][‘hooks’][‘addaccount’] = array(‘EGroupware\Api\Vfs\Hooks::addAccount’, ‘EGroupware\Api\Mail\Hooks::addaccount’);
+$setup_info[‘api’][‘hooks’][‘deleteaccount’] = array(‘EGroupware\Api\Vfs\Hooks::deleteAccount’, ‘EGroupware\Api\Mail\Hooks::deleteaccount’);
+$setup_info[‘api’][‘hooks’][‘editaccount’] = array(‘EGroupware\Api\Vfs\Hooks::editAccount’, ‘EGroupware\Api\Mail\Hooks::addaccount’);
+$setup_info[‘api’][‘hooks’][‘addgroup’] = ‘EGroupware\Api\Vfs\Hooks::addGroup’;
+$setup_info[‘api’][‘hooks’][‘deletegroup’] = array(‘EGroupware\Api\Vfs\Hooks::deleteGroup’, ‘EGroupware\Api\Mail\Hooks::deletegroup’);
+$setup_info[‘api’][‘hooks’][‘editgroup’] = ‘EGroupware\Api\Vfs\Hooks::editGroup’;
+$setup_info[‘api’][‘hooks’][‘changepassword’] = ‘EGroupware\Api\Mail\Hooks::changepassword’;
-// hooks used by vfs_home_hooks to manage user- and group-directories for the new stream based VFS
-$setup_info[‘phpgwapi’][‘hooks’][‘addaccount’] = ‘phpgwapi.vfs_home_hooks.addAccount’;
-$setup_info[‘phpgwapi’][‘hooks’][‘deleteaccount’] = ‘phpgwapi.vfs_home_hooks.deleteAccount’;
-$setup_info[‘phpgwapi’][‘hooks’][‘editaccount’] = ‘phpgwapi.vfs_home_hooks.editAccount’;
-$setup_info[‘phpgwapi’][‘hooks’][‘addgroup’] = ‘phpgwapi.vfs_home_hooks.addGroup’;
-$setup_info[‘phpgwapi’][‘hooks’][‘deletegroup’] = ‘phpgwapi.vfs_home_hooks.deleteGroup’;
-$setup_info[‘phpgwapi’][‘hooks’][‘editgroup’] = ‘phpgwapi.vfs_home_hooks.editGroup’;
+// installation checks
+$setup_info[‘api’][‘check_install’] = array(
-/* CalDAV/CardDAV/GroupDAV app */
+// CalDAV / CardDAV Sync
$setup_info[‘groupdav’][‘name’] = ‘groupdav’;
$setup_info[‘groupdav’][‘version’] = ‘14.1’;
$setup_info[‘groupdav’][‘enable’] = 2;
$setup_info[‘groupdav’][‘app_order’] = 1;
$setup_info[‘groupdav’][‘icon’] = ‘groupdav’;
-$setup_info[‘groupdav’][‘icon_app’] = ‘phpgwapi’;
+$setup_info[‘groupdav’][‘icon_app’] = ‘api’;
$setup_info[‘groupdav’][‘author’] = $setup_info[‘groupdav’][‘maintainer’] = array(
‘name’ => ‘Ralf Becker’,
‘email’ => ‘RalfBecker@outdoor-training.de’
@@ -72,5 +122,3 @@
$setup_info[‘groupdav’][‘license’] = ‘GPL’;
$setup_info[‘groupdav’][‘hooks’][‘preferences’] = ‘EGroupware\Api\CalDAV\Hooks::menus’;
$setup_info[‘groupdav’][‘hooks’][‘settings’] = ‘EGroupware\Api\CalDAV\Hooks::settings’;
— trunk/phpgwapi/inc/class.hooks.inc.php (original)
+++ trunk/egroupware/api/src/Hooks.php Sat Apr 2 16:16:20 2016
@@ -1,6 +1,6 @@
<?php
/**
- * eGroupWare API - Hooks
+ * EGroupware API - Hooks
*
* @link http://www.egroupware.org
* @author Dan Kuykendall
@@ -12,15 +12,18 @@
* @version $Id$
*/
+namespace EGroupware\Api;
+
+// explicitly import old not namespaced api classes
+use applications;
+
/**
- * class which gives ability for applications to set and use hooks to communicate with each other
- *
- * Hooks need to be declared in the app's setup.inc.php file and they have to be registered
- * (copied into the database) by
- * - installing or updating the app via setup or
- * - running Admin >> register all hooks
- * As the hooks-class can get cached in the session (session-type PHP_RESTORE), you also have to log
- * out and in again, that your changes take effect.
+ * Allow applications to set and use hooks to communicate with each other
+ *
+ * Hooks need to be declared in the app's setup.inc.php file and
+ * are cached in instance cache for 1h.
+ *
+ * Clearing instance cache or calling Api\Hooks::read(true) forces a new scan.
*
* Hooks can have one of the following formats:
* - static class method hooks are declared as:
@@ -32,38 +35,14 @@
* Old declaration in setup.inc.php:
* $setup_info['appname']['hooks'][] = 'location';
*/
-class hooks
+class Hooks
{
/**
- * Reference to the global db object
- *
- * @var egw_db
- */
- var $db;
- var $table = 'egw_hooks';
- /**
* Hooks by location and appname
*
- * @var array $location => $app => $file
- */
- var $locations;
-
- /**
- * constructor, reads and caches the complete hooks table
- *
- * @param egw_db $db =null database class, if null we use $GLOBALS['egw']->db
- */
- function __construct($db=null)
- {
- $this->db = $db ? $db : $GLOBALS['egw']->db; // this is to allow setup to set the db
-
- // sort hooks by app-order
- foreach($this->db->select($this->table,'hook_appname,hook_location,hook_filename',false,__LINE__,__FILE__,false,'ORDER BY app_order','phpgwapi',0,'JOIN egw_applications ON hook_appname=app_name') as $row)
- {
- $this->locations[$row['hook_location']][$row['hook_appname']] = $row['hook_filename'];
- }
- //_debug_array($this->locations);
- }
+ * @var array $location => $app => array($file, ...)
+ */
+ protected static $locations;
/**
* Executes all the hooks (the user has rights to) for a given location
@@ -78,14 +57,16 @@
* @return array with results of each hook call (with appname as key) and value:
* - False if no hook exists (should no longer be the case),
* - True if old hook exists and
- * - whatever the new method-hook returns (can be True or False too!).
- */
- function process($args, $order = array(), $no_permission_check = False)
+ * - array of return-values, if an app implements more then one hook
+ * - whatever the new method-hook returns (can be True or False too!)
+ */
+ public static function process($args, $order = array(), $no_permission_check = False)
{
//echo "
".__METHOD__.'('.array2string($args).','.array2string($order).','.array2string($no_permission_check).")
\n";
$location = is_array($args) ? (isset($args['hook_location']) ? $args['hook_location'] : $args['location']) : $args;
- $hooks = $this->locations[$location];
+ if (!isset(self::$locations)) self::read();
+ $hooks = self::$locations[$location];
if (!isset($hooks) || empty($hooks)) return array(); // not a single app implements that hook
$apps = array_keys($hooks);
@@ -101,13 +82,13 @@
$results = array();
foreach((array)$apps as $appname)
{
- $results[$appname] = $this->single($args,$appname,$no_permission_check);
+ $results[$appname] = self::single($args,$appname,$no_permission_check);
}
return $results;
}
/**
- * executes a single hook of a given location and application
+ * Executes a single hook of a given location and application
*
* @param string|array $args location-name as string or array with keys location, appname and
* further data to be passed to the hook, if its a new method-hook
@@ -117,9 +98,12 @@
* @param boolean $try_unregistered =false If true, try to include old file-hook anyway (for setup)
* @return mixed False if no hook exists, True if old hook exists and whatever the new method-hook returns (can be True or False too!).
*/
- function single($args, $appname = '', $no_permission_check = False,$try_unregistered = False)
- {
- //echo "
hooks::single(".array2string($args).",'$appname','$no_permission_check','$try_unregistered')
\n";
+ public static function single($args, $appname = '', $no_permission_check = False)//,$try_unregistered = False)
+ {
+ //error_log(__METHOD__."(".array2string($args).",'$appname','$no_permission_check','$try_unregistered')");
+
+ if (!isset(self::$locations)) self::read();
+
if (!is_array($args)) $args = array('location' => $args);
$location = isset($args['hook_location']) ? $args['hook_location'] : $args['location'];
@@ -132,54 +116,57 @@
{
return false;
}
- $SEP = filesystem_separator();
-
- /* First include the ordered apps hook file */
- if (isset($this->locations[$location][$appname]) || $try_unregistered)
- {
- $parts = explode('.',$method = $this->locations[$location][$appname]);
-
- if (strpos($method,'::') !== false || count($parts) == 3 && $parts[1] != 'inc' && $parts[2] != 'php')
- {
- // new style hook with method string or static method (eg. 'class::method')
- try
- {
- return ExecMethod($method,$args);
- }
- catch(egw_exception_assertion_failed $e)
- {
- if (substr($e->getMessage(),-19) == '.inc.php not found!')
+
+ $ret = array();
+ foreach((array)self::$locations[$location][$appname] as $hook)
+ {
+ try {
+ // old style file hook
+ if ($hook[0] == '/')
+ {
+ if (!file_exists(EGW_SERVER_ROOT.$hook))
{
- return false; // fail gracefully if hook class-file does not exists (like the old hooks do, eg. if app got removed)
+ error_log(__METHOD__."() old style hook file '$hook' not found --> ignored!");
+ continue;
}
- throw $e;
- }
- }
- // old style hook, with an include file
- if ($try_unregistered && empty($method))
- {
- $method = 'hook_'.$location.'.inc.php';
- }
- $f = EGW_SERVER_ROOT . $SEP . $appname . $SEP . 'inc' . $SEP . $method;
- if (file_exists($f) &&
- ( $GLOBALS['egw_info']['user']['apps'][$appname] || (($no_permission_check || $location == 'config' || $appname == 'phpgwapi') && $appname)) )
- {
- include($f);
- return True;
- }
- }
- return False;
- }
-
- /**
- * loop through the applications and count the hooks
+ include(EGW_SERVER_ROOT.$hook);
+ return true;
+ }
+
+ list($class, $method) = explode('::', $hook);
+
+ // static method of an autoloadable class
+ if (isset($method) && class_exists($class))
+ {
+ if (is_callable($hook)) $ret[] = call_user_func($hook, $args);
+ }
+ // app.class.method or not autoloadable class
+ else
+ {
+ $ret[] = ExecMethod2($hook, $args);
+ }
+ }
+ catch (\Exception $e) {
+ _egw_log_exception($e);
+ }
+ }
+
+ if (!$ret) return false;
+
+ return count($ret) == 1 ? $ret[0] : $ret;
+ }
+
+ /**
+ * loop through the applications and count the apps implementing a hooks
*
* @param string $location location-name
* @return int the number of found hooks
*/
function count($location)
{
- return count($this->locations[$location]);
+ if (!isset(self::$locations)) self::read();
+
+ return count(self::$locations[$location]);
}
/**
@@ -187,12 +174,15 @@
*
* @param string $location location-name
* @param string $app appname
- * @return int the number of found hooks
- */
- function hook_exists($location, $app)
- {
- //error_log(__METHOD__.__LINE__.array2string($this->locations[$location]));
- return count($this->locations[$location][$app]);
+ * @param boolean $return_methods =false true: return hook-method(s)
+ * @return int|array the number of found hooks or for $return_methods array with methods
+ */
+ public static function exists($location, $app, $return_methods=false)
+ {
+ if (!isset(self::$locations)) self::read();
+
+ //error_log(__METHOD__.__LINE__.array2string(self::$locations[$location]));
+ return $return_methods ? self::$locations[$location][$app] : count(self::$locations[$location][$app]);
}
/**
@@ -201,159 +191,61 @@
* @param string $location location-name
* @return array of apps implementing given hook
*/
- function hook_implemented($location)
- {
- //error_log(__METHOD__.__LINE__.array2string($this->locations[$location]));
- return isset($this->locations[$location]) ? array_keys($this->locations[$location]) : array();
- }
-
- /**
- * Register and/or de-register an application's hooks
- *
- * First all existing hooks of $appname get deleted in the db and then the given ones get registered.
- *
- * @param string $appname Application 'name'
- * @param array $hooks =null hooks to register, eg $setup_info[$app]['hooks'] or not used for only deregister the hooks
- * @return boolean|int false on error, true if new hooks are supplied and registed or number of removed hooks
- */
- function register_hooks($appname,$hooks=null)
- {
- if(!$appname)
- {
- return False;
- }
- $this->db->delete($this->table,array('hook_appname' => $appname),__LINE__,__FILE__);
-
- if (!is_array($hooks) || !count($hooks)) // only deregister
- {
- return $this->db->affected_rows();
- }
- //echo "
ADDING hooks for: $appname
";
- foreach($hooks as $key => $hook)
- {
- if (!is_numeric($key)) // new method-hook
+ public static function implemented($location)
+ {
+ if (!isset(self::$locations)) self::read();
+
+ //error_log(__METHOD__.__LINE__.array2string(self::$locations[$location]));
+ return isset(self::$locations[$location]) ? array_keys(self::$locations[$location]) : array();
+ }
+
+ /**
+ * Read all hooks into self::$locations
+ *
+ * @param boolan $force_rescan =false true: do not use instance cache
+ */
+ protected static function read($force_rescan=false)
+ {
+ //$starttime = microtime(true);
+ if ($force_rescan) Cache::unsetInstance(__CLASS__, 'locations');
+
+ self::$locations = Cache::getInstance(__CLASS__, 'locations', function()
+ {
+ // if we run in setup, we need to read installed apps first
+ if (!$GLOBALS['egw_info']['apps'])
{
- $location = $key;
- $filename = $hook;
- }
- else
+ $applications = new applications();
+ $applications->read_installed_apps();
+ }
+
+ // read all apps using just filesystem data
+ $locations = array();
+ foreach(array_merge(array('api'), array_keys($GLOBALS['egw_info']['apps'])) as $appname)
{
- $location = $hook;
- $filename = "hook_$hook.inc.php";
- }
- $this->db->insert($this->table,array(
- 'hook_filename' => $filename,
- ),array(
- 'hook_appname' => $appname,
- 'hook_location' => $location,
- ),__LINE__,__FILE__);
- $this->locations[$location][$appname] = $filename;
- }
- return True;
- }
-
- /**
- * Add or/update a single application hook
- *
- * setup file of app will be included and the hook required will be added/or updated
- *
- * @param string $appname Application 'name'
- * @param string $location is required, the hook itself
- * @return boolean|int false on error, true if new hooks are supplied and registed or number of removed hooks
- */
- function register_single_app_hook($appname, $location)
- {
- if(!$appname || empty($location))
- {
- return False;
- }
- $SEP = filesystem_separator();
- // now register the rest again
- $f = EGW_SERVER_ROOT . $SEP . $appname . $SEP . 'setup' . $SEP . 'setup.inc.php';
- $setup_info = array($appname => array());
- if(@file_exists($f)) include($f);
- // some apps have setup_info for more then themselfs (eg. phpgwapi for groupdav)
- $hdata = array();
- foreach($setup_info as $appname => $data)
- {
- if ($data['hooks'])
- {
- if ($hdata[$appname])
- {
- $hdata[$appname]['hooks'] = array_merge($hdata[$appname]['hooks'],$data['hooks']);
- }
- else
- {
- $hdata[$appname]['hooks'] = $data['hooks'];
- }
- }
- }
- //error_log(__METHOD__.__LINE__.array2string($hdata));
- foreach((array)$hdata as $appname => $data)
- {
- if (array_key_exists($location,$data['hooks'])) $method = $data['hooks'][$location];
- }
- if (!empty($method))
- {
- //echo "
ADDING hooks for: $appname
";
- $this->db->insert($this->table,array(
- 'hook_appname' => $appname,
- 'hook_filename' => $method,
- 'hook_location' => $location,
- ),array(
- 'hook_appname' => $appname,
- 'hook_location' => $location,
- ),__LINE__,__FILE__);
- $this->locations[$location][$appname] = $method;
- return True;
- }
- return false;
- }
-
- /**
- * Register the hooks of all applications (used by admin)
- */
- function register_all_hooks()
- {
- // deleting hooks, to get ride of no longer existing apps
- $this->db->delete($this->table,'1=1',__LINE__,__FILE__);
-
- // if we run in setup, we need to read installed apps first
- if (!$GLOBALS['egw_info']['apps'])
- {
- $applications = new applications();
- $applications->read_installed_apps();
- }
-
- // now register all apps using just filesystem data
- foreach(array_keys($GLOBALS['egw_info']['apps']) as $appname)
- {
- if ($appname[0] == '.' || !is_dir(EGW_SERVER_ROOT.'/'.$appname)) continue;
-
- $f = EGW_SERVER_ROOT . '/' . $appname . '/setup/setup.inc.php';
- $setup_info = array($appname => array());
- if(@file_exists($f)) include($f);
- // some apps have setup_info for more then themselfs (eg. phpgwapi for groupdav)
- $hdata = array();
- foreach($setup_info as $appname => $data)
- {
- if ($data['hooks'])
- {
- if ($hdata[$appname])
+ if ($appname[0] == '.' || !is_dir(EGW_SERVER_ROOT.'/'.$appname)) continue;
+
+ $f = EGW_SERVER_ROOT . '/' . $appname . '/setup/setup.inc.php';
+ $setup_info = array($appname => array());
+ if(@file_exists($f)) include($f);
+
+ // some apps have setup_info for more then themselfs (eg. api for groupdav)
+ foreach($setup_info as $appname => $data)
+ {
+ foreach((array)$data['hooks'] as $location => $methods)
{
- $hdata[$appname]['hooks'] = array_merge($hdata[$appname]['hooks'],$data['hooks']);
+ if (is_int($location))
+ {
+ $location = $methods;
+ $methods = '/'.$appname.'/inc/hook_'.$methods.'.inc.php';
+ }
+ $locations[$location][$appname] = (array)$methods;
}
- else
- {
- $hdata[$appname]['hooks'] = $data['hooks'];
- }
- }
- }
- foreach((array)$hdata as $appname => $data)
- {
- if ($data['hooks']) $this->register_hooks($appname,$data['hooks']);
- }
- }
+ }
+ }
+ return $locations;
+ }, array(), 3600);
+
+ //error_log(__METHOD__."() took ".number_format(1000*(microtime(true)-$starttime), 1)."ms, size=".Vfs::hsize(strlen(json_encode(self::$locations))));
}
/**
@@ -362,21 +254,12 @@
*/
public static function pgp_encryption_menu($appname)
{
- if (html::$ua_mobile) return;
+ if (Header\UserAgent::mobile()) return;
+
// PGP Encryption (Mailvelope plugin) restore/backup menu
$file = Array(
'Backup/Restore ...' => 'javascript:app.'.$appname.'.mailvelopeCreateBackupRestoreDialog();',
);
display_sidebox($appname, lang('PGP Encryption'), $file);
}
-
- /**
- * Static function to build egw tutorial sidebox menu
- *
- * @deprecated can be removed 2016, as replaced by home_tutorial_ui::tutorial_menu
- */
- public static function egw_tutorial_menu()
- {
- home_tutorial_ui::tutorial_menu();
- }
}
Copied: trunk/egroupware/api/src/Mail/Hooks.php (from r55599, trunk/emailadmin/inc/class.emailadmin_hooks.inc.php)
URL: http://svn.stylite.de/viewvc/egroupware/trunk/egroupware/api/src/Mail/Hooks.php?p2=trunk/egroupware/api/src/Mail/Hooks.php&p1=trunk/emailadmin/inc/class.emailadmin_hooks.inc.php&r1=55599&r2=55603&rev=55603&view=diff
==============================================================================
--- trunk/emailadmin/inc/class.emailadmin_hooks.inc.php (original)
+++ trunk/egroupware/api/src/Mail/Hooks.php Sat Apr 2 16:16:20 2016
@@ -1,23 +1,23 @@
<?php
/**
- * EGroupware - eMailAdmin hooks
+ * EGroupware - Mail hooks
*
* @link http://www.egroupware.org
- * @package emailadmin
+ * @package api
+ * @subpackage amil
* @author Klaus Leithoff
* @author Ralf Becker
- * @copyright (c) 2008-14 by leithoff-At-stylite.de
+ * @copyright (c) 2008-16 by leithoff-At-stylite.de
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id$
*/
-use EGroupware\Api\Mail\Account as emailadmin_account;
-use EGroupware\Api\Mail\Credentials as emailadmin_credentials;
+namespace EGroupware\Api\Mail;
/**
- * diverse static emailadmin hooks
+ * diverse static Mail hooks
*/
-class emailadmin_hooks
+class Hooks
{
/**
* Password changed hook --> unset cached objects, as password might be used for email connection
@@ -28,7 +28,7 @@
{
if (!empty($hook_data['old_passwd']))
{
- emailadmin_credentials::changepassword($hook_data);
+ Credentials::changepassword($hook_data);
}
}
@@ -45,7 +45,7 @@
self::run_plugin_hooks('deleteAccount', $data);
// as mail accounts contain credentials, we do NOT assign them to user users
- emailadmin_account::delete(0, $data['account_id']);
+ Account::delete(0, $data['account_id']);
}
/**
@@ -57,7 +57,7 @@
*/
static function deletegroup(array $data)
{
- emailadmin_account::delete(0, $data['account_id']);
+ Account::delete(0, $data['account_id']);
}
/**
@@ -82,12 +82,12 @@
*/
protected static function run_plugin_hooks($method, array $data)
{
- foreach(emailadmin_account::search((int)$data['account_id'], 'params') as $params)
+ foreach(Account::search((int)$data['account_id'], 'params') as $params)
{
- if (!emailadmin_account::is_multiple($params)) continue; // no need to waste time on personal accounts
+ if (!Account::is_multiple($params)) continue; // no need to waste time on personal accounts
try {
- $account = new emailadmin_account($params);
+ $account = new Account($params);
if ($account->acc_smtp_type != 'emailadmin_smtp' && ($smtp = $account->smtpServer(true)) &&
is_a($smtp, 'emailadmin_smtp') && get_class($smtp) != 'emailadmin_smtp')
{
@@ -100,7 +100,7 @@
$imap->$method($data);
}
}
- catch(Exception $e) {
+ catch(\Exception $e) {
_egw_log_exception($e);
// ignore exception, without stalling other hooks
}
Copied: trunk/egroupware/api/src/Vfs/Hooks.php (from r55599, trunk/phpgwapi/inc/class.vfs_home_hooks.inc.php)
URL: http://svn.stylite.de/viewvc/egroupware/trunk/egroupware/api/src/Vfs/Hooks.php?p2=trunk/egroupware/api/src/Vfs/Hooks.php&p1=trunk/phpgwapi/inc/class.vfs_home_hooks.inc.php&r1=55599&r2=55603&rev=55603&view=diff
==============================================================================
--- trunk/phpgwapi/inc/class.vfs_home_hooks.inc.php (original)
+++ trunk/egroupware/api/src/Vfs/Hooks.php Sat Apr 2 16:16:20 2016
@@ -1,18 +1,22 @@
<?php
/**
- * eGroupWare API: VFS - Hooks to add/rename/delete user and group home-directories
+ * EGroup2are API: VFS - Hooks to add/rename/delete user and group home-directories
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage vfs
* @author Ralf Becker
- * @copyright (c) 2008-9 by Ralf Becker
+ * @copyright (c) 2008-16 by Ralf Becker
* @version $Id$
*/
+namespace EGroupware\Api\Vfs;
+
+use EGroupware\Api;
+
/**
- * eGroupWare API: VFS - Hooks to add/rename/delete user and group home-directories
+ * VFS - Hooks to add/rename/delete user and group home-directories
*
* This class implements the creation, renaming or deletion of home-dirs via some hooks from admin:
* - create the homedir if a new user gets created
@@ -20,7 +24,7 @@
* - delete the homedir or copy its content to an other users homedir, if a user gets deleted
* --> these hooks are registered via phpgwapi/setup/setup.inc.php and called by the admin app
*/
-class vfs_home_hooks
+class Hooks
{
/**
* Should we log our calls to the error_log
@@ -40,14 +44,14 @@
{
if (self::LOG_LEVEL > 0) error_log(__METHOD__.'('.array2string($data).')');
// create a user-dir
- egw_vfs::$is_root = true;
- if (egw_vfs::mkdir($dir='/home/'.$data['account_lid'],0700,0))
+ Api\Vfs::$is_root = true;
+ if (Api\Vfs::mkdir($dir='/home/'.$data['account_lid'],0700,0))
{
- egw_vfs::chown($dir,$data['account_id']);
- egw_vfs::chgrp($dir,0);
- egw_vfs::chmod($dir,0700); // only user has access
+ Api\Vfs::chown($dir,$data['account_id']);
+ Api\Vfs::chgrp($dir,0);
+ Api\Vfs::chmod($dir,0700); // only user has access
}
- egw_vfs::$is_root = false;
+ Api\Vfs::$is_root = false;
}
/**
@@ -66,9 +70,9 @@
return; // nothing to do here
}
// rename the user-dir
- egw_vfs::$is_root = true;
- egw_vfs::rename('/home/'.$data['old_loginid'],'/home/'.$data['account_lid']);
- egw_vfs::$is_root = false;
+ Api\Vfs::$is_root = true;
+ Api\Vfs::rename('/home/'.$data['old_loginid'],'/home/'.$data['account_lid']);
+ Api\Vfs::$is_root = false;
}
/**
@@ -82,25 +86,28 @@
static function deleteAccount($data)
{
if (self::LOG_LEVEL > 0) error_log(__METHOD__.'('.array2string($data).')');
- egw_vfs::$is_root = true;
+ Api\Vfs::$is_root = true;
if ($data['new_owner'] && ($new_lid = $GLOBALS['egw']->accounts->id2name($data['new_owner'])))
{
// copy content of user-dir to new owner's user-dir as old-home-$name
- for ($i=''; file_exists(egw_vfs::PREFIX.($new_dir = '/home/'.$new_lid.'/old-home-'.$data['account_lid'].$i)); $i++);
- egw_vfs::rename('/home/'.$data['account_lid'],$new_dir);
+ for ($i=''; file_exists(Api\Vfs::PREFIX.($new_dir = '/home/'.$new_lid.'/old-home-'.$data['account_lid'].$i)); $i++)
+ {
+
+ }
+ Api\Vfs::rename('/home/'.$data['account_lid'],$new_dir);
// make the new owner the owner of the dir and it's content
- egw_vfs::find($new_dir,array(),array('egw_vfs','chown'),$data['new_owner']);
+ Api\Vfs::find($new_dir,array(),array('egw_vfs','chown'),$data['new_owner']);
}
elseif(!empty($data['account_lid']) && $data['account_lid'] != '/')
{
// delete the user-directory
- egw_vfs::remove('/home/'.$data['account_lid']);
+ Api\Vfs::remove('/home/'.$data['account_lid']);
}
else
{
- throw new egw_exception_assertion_failed(__METHOD__.'('.array2string($data).') account_lid NOT set!');
+ throw new Api\Exception\AssertionFailed(__METHOD__.'('.array2string($data).') account_lid NOT set!');
}
- egw_vfs::$is_root = false;
+ Api\Vfs::$is_root = false;
}
/**
@@ -113,17 +120,17 @@
static function addGroup($data)
{
if (self::LOG_LEVEL > 0) error_log(__METHOD__.'('.array2string($data).')');
- if (empty($data['account_lid'])) throw new egw_exception_wrong_parameter('account_lid must not be empty!');
+ if (empty($data['account_lid'])) throw new Api\Exception\WrongParameter('account_lid must not be empty!');
// create a group-dir
- egw_vfs::$is_root = true;
- if (egw_vfs::mkdir($dir='/home/'.$data['account_lid'],0070,0))
+ Api\Vfs::$is_root = true;
+ if (Api\Vfs::mkdir($dir='/home/'.$data['account_lid'],0070,0))
{
- egw_vfs::chown($dir,0);
- egw_vfs::chgrp($dir,abs($data['account_id'])); // gid in Vfs is positiv!
- egw_vfs::chmod($dir,0070); // only group has access
+ Api\Vfs::chown($dir,0);
+ Api\Vfs::chgrp($dir,abs($data['account_id'])); // gid in Vfs is positiv!
+ Api\Vfs::chmod($dir,0070); // only group has access
}
- egw_vfs::$is_root = false;
+ Api\Vfs::$is_root = false;
}
/**
@@ -145,7 +152,7 @@
if ($data['account_lid'] == $data['old_name'])
{
// check if group directory exists and create it if not (by calling addGroup hook)
- if (!egw_vfs::stat('/home/'.$data['account_lid']))
+ if (!Api\Vfs::stat('/home/'.$data['account_lid']))
{
self::addGroup($data);
}
@@ -153,9 +160,9 @@
else
{
// rename the group-dir
- egw_vfs::$is_root = true;
- egw_vfs::rename('/home/'.$data['old_name'],'/home/'.$data['account_lid']);
- egw_vfs::$is_root = false;
+ Api\Vfs::$is_root = true;
+ Api\Vfs::rename('/home/'.$data['old_name'],'/home/'.$data['account_lid']);
+ Api\Vfs::$is_root = false;
}
}
@@ -172,11 +179,11 @@
if(empty($data['account_lid']) || $data['account_lid'] == '/')
{
- throw new egw_exception_assertion_failed(__METHOD__.'('.array2string($data).') account_lid NOT set!');
+ throw new Api\Exception\AssertionFailed(__METHOD__.'('.array2string($data).') account_lid NOT set!');
}
// delete the group-directory
- egw_vfs::$is_root = true;
- egw_vfs::remove('/home/'.$data['account_lid']);
- egw_vfs::$is_root = false;
+ Api\Vfs::$is_root = true;
+ Api\Vfs::remove('/home/'.$data['account_lid']);
+ Api\Vfs::$is_root = false;
}
}
Modified: trunk/emailadmin/setup/setup.inc.php
URL: http://svn.stylite.de/viewvc/egroupware/trunk/emailadmin/setup/setup.inc.php?rev=55603&r1=55602&r2=55603&view=diff
==============================================================================
--- trunk/emailadmin/setup/setup.inc.php (original)
+++ trunk/emailadmin/setup/setup.inc.php Sat Apr 2 16:16:20 2016
@@ -35,70 +35,4 @@
$setup_info['emailadmin']['tables'][] = 'egw_ea_notifications';
/* The hooks this app includes, needed for hooks registration */
-$setup_info['emailadmin']['hooks']['deleteaccount'] = 'emailadmin_hooks::deleteaccount';
-$setup_info['emailadmin']['hooks']['addaccount'] = 'emailadmin_hooks::addaccount';
-$setup_info['emailadmin']['hooks']['editaccount'] = 'emailadmin_hooks::addaccount';
-$setup_info['emailadmin']['hooks']['deletegroup'] = 'emailadmin_hooks::deletegroup';
-$setup_info['emailadmin']['hooks']['changepassword'] = 'emailadmin_hooks::changepassword';
-/* Dependencies for this app to work */
-$setup_info['emailadmin']['depends'][] = array(
- 'appname' => 'phpgwapi',
- 'versions' => Array('14.1')
-);
-$setup_info['emailadmin']['depends'][] = array(
- 'appname' => 'etemplate',
- 'versions' => Array('14.1')
-);
-// installation checks
-$setup_info['emailadmin']['check_install'] = array(
- '' => array(
- 'func' => 'pear_check',
- 'from' => 'EMailAdmin',
- ),
- 'pear.horde.org/Horde_Imap_Client' => array(
- 'func' => 'pear_check',
- 'from' => 'EMailAdmin',
- 'version' => '2.24.2',
- ),
- 'pear.horde.org/Horde_Nls' => array(
- 'func' => 'pear_check',
- 'from' => 'EMailAdmin',
- 'version' => '2.0.3',
- ),
- 'pear.horde.org/Horde_Mail' => array(
- 'func' => 'pear_check',
- 'from' => 'EMailAdmin',
- 'version' => '2.1.2',
- ),
- 'pear.horde.org/Horde_Smtp' => array(
- 'func' => 'pear_check',
- 'from' => 'EMailAdmin',
- 'version' => '1.3.0',
- ),
- 'pear.horde.org/Horde_ManageSieve' => array(
- 'func' => 'pear_check',
- 'from' => 'EMailAdmin',
- 'version' => '1.0.1',
- ),
- // next 4 are required for TNEF support
- 'pear.horde.org/Horde_Compress' => array(
- 'func' => 'pear_check',
- 'from' => 'EMailAdmin',
- 'version' => '2.0.8',
- ),
- 'pear.horde.org/Horde_Icalendar' => array(
- 'func' => 'pear_check',
- 'from' => 'EMailAdmin',
- 'version' => '2.0.0',
- ),
- 'pear.horde.org/Horde_Mapi' => array(
- 'func' => 'pear_check',
- 'from' => 'EMailAdmin',
- 'version' => '1.0.0',
- ),
- 'bcmath' => array(
- 'func' => 'extension_check',
- 'from' => 'EMailAdmin',
- ),
-);
Modified: trunk/phpgwapi/inc/class.hooks.inc.php
URL: http://svn.stylite.de/viewvc/egroupware/trunk/phpgwapi/inc/class.hooks.inc.php?rev=55603&r1=55602&r2=55603&view=diff
==============================================================================
--- trunk/phpgwapi/inc/class.hooks.inc.php (original)
+++ trunk/phpgwapi/inc/class.hooks.inc.php Sat Apr 2 16:16:20 2016
@@ -12,199 +12,38 @@
* @version $Id$
*/
+use EGroupware\Api;
+
/**
* class which gives ability for applications to set and use hooks to communicate with each other
*
- * Hooks need to be declared in the app's setup.inc.php file and they have to be registered
- * (copied into the database) by
- * - installing or updating the app via setup or
- * - running Admin >> register all hooks
- * As the hooks-class can get cached in the session (session-type PHP_RESTORE), you also have to log
- * out and in again, that your changes take effect.
- *
- * Hooks can have one of the following formats:
- * - static class method hooks are declared as:
- * $setup_info['appname']['hooks']['location'] = 'class::method';
- * - method hooks, which are methods of a class. You can pass parameters to the call and
- * they can return values. They get declared in setup.inc.php as:
- * $setup_info['appname']['hooks']['location'] = 'app.class.method';
- * - old type, which are included files. Values can only be passed by global values and they cant return anything.
- * Old declaration in setup.inc.php:
- * $setup_info['appname']['hooks'][] = 'location';
+ * @deprecated use static methods of Api\Hooks::process() and Api\Hooks::single
*/
-class hooks
+class hooks extends Api\Hooks
{
- /**
- * Reference to the global db object
- *
- * @var egw_db
- */
- var $db;
- var $table = 'egw_hooks';
- /**
- * Hooks by location and appname
- *
- * @var array $location => $app => $file
- */
- var $locations;
-
- /**
- * constructor, reads and caches the complete hooks table
- *
- * @param egw_db $db =null database class, if null we use $GLOBALS['egw']->db
- */
- function __construct($db=null)
- {
- $this->db = $db ? $db : $GLOBALS['egw']->db; // this is to allow setup to set the db
-
- // sort hooks by app-order
- foreach($this->db->select($this->table,'hook_appname,hook_location,hook_filename',false,__LINE__,__FILE__,false,'ORDER BY app_order','phpgwapi',0,'JOIN egw_applications ON hook_appname=app_name') as $row)
- {
- $this->locations[$row['hook_location']][$row['hook_appname']] = $row['hook_filename'];
- }
- //_debug_array($this->locations);
- }
-
- /**
- * Executes all the hooks (the user has rights to) for a given location
- *
- * If no $order given, hooks are executed in the order of the applications!
- *
- * @param string|array $args location-name as string or array with keys location and
- * further data to be passed to the hook, if its a new method-hook
- * @param string|array $order appname(s as value), which should be executes first
- * @param boolean $no_permission_check if True execute all hooks, not only the ones a user has rights to
- * $no_permission_check should *ONLY* be used when it *HAS* to be. (jengo)
- * @return array with results of each hook call (with appname as key) and value:
- * - False if no hook exists (should no longer be the case),
- * - True if old hook exists and
- * - whatever the new method-hook returns (can be True or False too!).
- */
- function process($args, $order = array(), $no_permission_check = False)
- {
- //echo "
".__METHOD__.'('.array2string($args).','.array2string($order).','.array2string($no_permission_check).")
\n";
- $location = is_array($args) ? (isset($args['hook_location']) ? $args['hook_location'] : $args['location']) : $args;
-
- $hooks = $this->locations[$location];
- if (!isset($hooks) || empty($hooks)) return array(); // not a single app implements that hook
-
- $apps = array_keys($hooks);
- if (!$no_permission_check)
- {
- // on install of a new egroupware both hook-apps and user apps may be empty/not set
- $apps = array_intersect((array)$apps,array_keys((array)$GLOBALS['egw_info']['user']['apps']));
- }
- if ($order)
- {
- $apps = array_unique(array_merge((array)$order,$apps));
- }
- $results = array();
- foreach((array)$apps as $appname)
- {
- $results[$appname] = $this->single($args,$appname,$no_permission_check);
- }
- return $results;
- }
-
- /**
- * executes a single hook of a given location and application
- *
- * @param string|array $args location-name as string or array with keys location, appname and
- * further data to be passed to the hook, if its a new method-hook
- * @param string $appname name of the app, which's hook to execute, if empty the current app is used
- * @param boolean $no_permission_check =false if True execute all hooks, not only the ones a user has rights to
- * $no_permission_check should *ONLY* be used when it *HAS* to be. (jengo)
- * @param boolean $try_unregistered =false If true, try to include old file-hook anyway (for setup)
- * @return mixed False if no hook exists, True if old hook exists and whatever the new method-hook returns (can be True or False too!).
- */
- function single($args, $appname = '', $no_permission_check = False,$try_unregistered = False)
- {
- //echo "
hooks::single(".array2string($args).",'$appname','$no_permission_check','$try_unregistered')
\n";
- if (!is_array($args)) $args = array('location' => $args);
- $location = isset($args['hook_location']) ? $args['hook_location'] : $args['location'];
-
- if (!$appname)
- {
- $appname = is_array($args) && isset($args['appname']) ? $args['appname'] : $GLOBALS['egw_info']['flags']['currentapp'];
- }
- // excute hook only if $no_permission_check or user has run-rights for app
- if (!($no_permission_check || isset($GLOBALS['egw_info']['user']['apps'][$appname])))
- {
- return false;
- }
- $SEP = filesystem_separator();
-
- /* First include the ordered apps hook file */
- if (isset($this->locations[$location][$appname]) || $try_unregistered)
- {
- $parts = explode('.',$method = $this->locations[$location][$appname]);
-
- if (strpos($method,'::') !== false || count($parts