public function callByPackage($app, $call, array $args = array(), array $options = array())
{
/* Note: calling hasMethod() makes sure that we've cached
* $app's services and included the API file, so we don't try
* to do it again explicitly in this method. */
if (!$this->hasMethod($call, $app)) {
throw new Horde_Exception(sprintf('The method "%s" is not defined in the API for %s.', $call, $app));
}
/* Load the API now. */
$methods = ($api_ob = $this->_loadApi($app)) ? $api_ob->methods() : array();
/* Make sure that the function actually exists. */
if (!in_array($call, $methods)) {
throw new Horde_Exception('The function implementing ' . $call . ' is not defined in ' . $app . '\'s API.');
}
/* Switch application contexts now, if necessary, before
* including any files which might do it for us. Return an
* error immediately if pushApp() fails. */
$pushed = $this->pushApp($app, array('check_perms' => !in_array($call, $api_ob->noPerms()) && empty($options['noperms']) && $this->currentProcessAuth()));
try {
$result = call_user_func_array(array($api_ob, $call), $args);
if ($result instanceof PEAR_Error) {
$result = new Horde_Exception_Wrapped($result);
}
} catch (Horde_Exception $e) {
$result = $e;
}
/* If we changed application context in the course of this
* call, undo that change now. */
if ($pushed === true) {
$this->popApp();
}
if ($result instanceof Horde_Exception) {
throw $result;
}
return $result;
}