mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-24 15:49:06 +01:00
move egw_json_(request|response|push) to api
This commit is contained in:
parent
7b58daae42
commit
52a7f2198a
@ -16,7 +16,6 @@ namespace EGroupware\Api;
|
||||
// explicitly import old not yet ported classes
|
||||
use egw;
|
||||
use egw_framework;
|
||||
use egw_json_response;
|
||||
use categories; // css
|
||||
|
||||
/**
|
||||
@ -147,7 +146,7 @@ class Etemplate extends Etemplate\Widget\Template
|
||||
if ($output_mode == 4)
|
||||
{
|
||||
$output_mode = 0;
|
||||
self::$response = egw_json_response::get();
|
||||
self::$response = Json\Response::get();
|
||||
}
|
||||
self::$request->output_mode = $output_mode; // let extensions "know" they are run eg. in a popup
|
||||
self::$request->content = self::$cont = $content;
|
||||
@ -274,13 +273,13 @@ class Etemplate extends Etemplate\Widget\Template
|
||||
echo '<div id="popupMainDiv" class="popupMainDiv">'."\n";
|
||||
}
|
||||
// Send any accumulated json responses - after flush to avoid sending the buffer as a response
|
||||
if(egw_json_response::isJSONResponse())
|
||||
if(Json\Response::isJSONResponse())
|
||||
{
|
||||
$load_array['response'] = egw_json_response::get()->returnResult();
|
||||
$load_array['response'] = Json\Response::get()->returnResult();
|
||||
}
|
||||
// <iframe> and <form> tags added only to get browser autocomplete handling working again
|
||||
echo '<form target="egw_iframe_autocomplete_helper" action="'.$form_action.'" id="'.$dom_id.'" class="et2_container" data-etemplate="'.
|
||||
htmlspecialchars(egw_json_response::json_encode($load_array), ENT_COMPAT, Translation::charset(), true).'"></form>'."\n".
|
||||
htmlspecialchars(Json\Response::json_encode($load_array), ENT_COMPAT, Translation::charset(), true).'"></form>'."\n".
|
||||
'<iframe name="egw_iframe_autocomplete_helper" style="width:0;height:0;position: absolute;visibility:hidden;"></iframe>';
|
||||
|
||||
if ($output_mode == 2)
|
||||
@ -331,7 +330,7 @@ class Etemplate extends Etemplate\Widget\Template
|
||||
self::$request = Etemplate\Request::read($etemplate_exec_id);
|
||||
//error_log('request='.array2string(self::$request));
|
||||
|
||||
self::$response = egw_json_response::get();
|
||||
self::$response = Json\Response::get();
|
||||
|
||||
if (!($template = self::instance(self::$request->template['name'], self::$request->template['template_set'],
|
||||
self::$request->template['version'], self::$request->template['load_via'])))
|
||||
@ -418,7 +417,7 @@ class Etemplate extends Etemplate\Widget\Template
|
||||
// Strip out any script tags
|
||||
$GLOBALS['egw_info']['flags']['java_script'] = preg_replace(array('/(<script[^>]*>)([^<]*)/is','/<\/script>/'),array('$2',''),$GLOBALS['egw_info']['flags']['java_script']);
|
||||
self::$response->script($GLOBALS['egw_info']['flags']['java_script']);
|
||||
//error_log($app .' added javascript to $GLOBALS[egw_info][flags][java_script] - use egw_json_response->script() instead.');
|
||||
//error_log($app .' added javascript to $GLOBALS[egw_info][flags][java_script] - use Json\Response->script() instead.');
|
||||
}
|
||||
|
||||
return $content;
|
||||
|
@ -13,10 +13,10 @@
|
||||
|
||||
namespace EGroupware\Api\Etemplate;
|
||||
|
||||
use EGroupware\Api;
|
||||
|
||||
// explicitly import old not yet ported classes
|
||||
use egw_framework;
|
||||
use egw_json_response;
|
||||
use egw_json_request;
|
||||
use common; // egw_exit
|
||||
|
||||
/**
|
||||
@ -59,7 +59,7 @@ use common; // egw_exit
|
||||
*
|
||||
* if (($new_id = $request->id()) != $exec_id)
|
||||
* {
|
||||
* egw_json_response::get()->generic('assign', array(
|
||||
* Api\Json\Response::get()->generic('assign', array(
|
||||
* 'etemplate_exec_id' => $id,
|
||||
* 'id' => '',
|
||||
* 'key' => 'etemplate_exec_id',
|
||||
@ -71,7 +71,7 @@ use common; // egw_exit
|
||||
*
|
||||
* if (($new_id = $request->id()) != $exec_id)
|
||||
* {
|
||||
* egw_json_response::get()->assign('etemplate_exec_id','value',$new_id);
|
||||
* Api\Json\Response::get()->assign('etemplate_exec_id','value',$new_id);
|
||||
* }
|
||||
*
|
||||
* For an example look in link_widget::ajax_search()
|
||||
@ -200,13 +200,13 @@ class Request
|
||||
'/index.php?menuaction='.$GLOBALS['egw_info']['apps'][$app]['index'] : '/'.$app.'/index.php';
|
||||
// add a unique token to redirect to avoid client-side framework tries refreshing via nextmatch
|
||||
$index_url .= (strpos($index_url, '?') ? '&' : '?').'redirect='.microtime(true);
|
||||
error_log(__METHOD__."('$id', ...) eT2 request not found / expired --> redirecting app $app to $index_url (_GET[menuaction]=$_GET[menuaction], isJSONRequest()=".array2string(egw_json_request::isJSONRequest()).')');
|
||||
if (egw_json_request::isJSONRequest())
|
||||
error_log(__METHOD__."('$id', ...) eT2 request not found / expired --> redirecting app $app to $index_url (_GET[menuaction]=$_GET[menuaction], isJSONRequest()=".array2string(Api\Json\Request::isJSONRequest()).')');
|
||||
if (Api\Json\Request::isJSONRequest())
|
||||
{
|
||||
// we must not redirect ajax_destroy_session calls, as they might originate from our own redirect!
|
||||
if (strpos($_GET['menuaction'], '.ajax_destroy_session.etemplate') === false)
|
||||
{
|
||||
$response = egw_json_response::get();
|
||||
$response = Api\Json\Response::get();
|
||||
$response->redirect($index_url, false, $app);
|
||||
common::egw_exit();
|
||||
}
|
||||
|
@ -17,10 +17,6 @@ use EGroupware\Api;
|
||||
use XMLReader;
|
||||
use ReflectionMethod;
|
||||
|
||||
// explicitly import old not yet ported classes
|
||||
use egw_json_response;
|
||||
|
||||
|
||||
/**
|
||||
* eTemplate widget baseclass
|
||||
*/
|
||||
@ -73,7 +69,7 @@ class Widget
|
||||
/**
|
||||
* JSON response object, if we run via a JSON request
|
||||
*
|
||||
* @var egw_json_response
|
||||
* @var Api\Json\Response
|
||||
*/
|
||||
static protected $response;
|
||||
|
||||
|
@ -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_json_response;
|
||||
|
||||
/**
|
||||
* eTemplate file upload widget
|
||||
* Uses AJAX to send file(s) to server, and stores for submit
|
||||
@ -52,7 +49,7 @@ class File extends Etemplate\Widget
|
||||
* @note Currently, no attempt is made to clean up files automatically.
|
||||
*/
|
||||
public static function ajax_upload() {
|
||||
$response = egw_json_response::get();
|
||||
$response = Api\Json\Response::get();
|
||||
$request_id = str_replace(' ', '+', rawurldecode($_REQUEST['request_id']));
|
||||
$widget_id = $_REQUEST['widget_id'];
|
||||
if(!self::$request = Etemplate\Request::read($request_id)) {
|
||||
|
@ -18,9 +18,6 @@ namespace EGroupware\Api\Etemplate\Widget;
|
||||
use EGroupware\Api\Etemplate;
|
||||
use EGroupware\Api;
|
||||
|
||||
// explicitly import old not yet ported classes
|
||||
use egw_json_response;
|
||||
|
||||
/**
|
||||
* eTemplate itempicker widget
|
||||
*/
|
||||
@ -48,7 +45,7 @@ class ItemPicker extends Etemplate\Widget
|
||||
$options['type'] = $type ? $type : $options['type'];
|
||||
$items = Api\Link::query($app, $pattern, $options);
|
||||
|
||||
$response = egw_json_response::get();
|
||||
$response = Api\Json\Response::get();
|
||||
$response->data($items);
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ use EGroupware\Api\Etemplate;
|
||||
use EGroupware\Api;
|
||||
|
||||
// explicitly import old not yet ported classes
|
||||
use egw_json_response;
|
||||
use common; // egw_exit
|
||||
|
||||
/**
|
||||
@ -109,7 +108,7 @@ class Link extends Etemplate\Widget
|
||||
if(!$options['num_rows']) $options['num_rows'] = 1000;
|
||||
$links = Api\Link::query($app, $pattern, $options);
|
||||
$linksc = array_combine(array_map(create_function('$k', 'return (string)" ".$k;'), array_keys($links)), $links);
|
||||
$response = egw_json_response::get();
|
||||
$response = Api\Json\Response::get();
|
||||
$response->data($linksc);
|
||||
}
|
||||
|
||||
@ -124,7 +123,7 @@ class Link extends Etemplate\Widget
|
||||
{
|
||||
$title = Api\Link::title($app, $id);
|
||||
//error_log(__METHOD__."('$app', '$id') = ".array2string($title));
|
||||
egw_json_response::get()->data($title);
|
||||
Api\Json\Response::get()->data($title);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -147,7 +146,7 @@ class Link extends Etemplate\Widget
|
||||
error_log(__METHOD__."(".array2string($app_ids).") got invalid title request: app=$app, ids=" . array2string($ids));
|
||||
}
|
||||
}
|
||||
egw_json_response::get()->data($response);
|
||||
Api\Json\Response::get()->data($response);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -172,7 +171,7 @@ class Link extends Etemplate\Widget
|
||||
}
|
||||
$result = Api\Link::link($app, $id, $links);
|
||||
|
||||
$response = egw_json_response::get();
|
||||
$response = Api\Json\Response::get();
|
||||
$response->data(is_array($id) ? $id : $result !== false);
|
||||
}
|
||||
|
||||
@ -207,7 +206,7 @@ class Link extends Etemplate\Widget
|
||||
}
|
||||
}
|
||||
|
||||
$response = egw_json_response::get();
|
||||
$response = Api\Json\Response::get();
|
||||
// Strip keys, unneeded and cause index problems on the client side
|
||||
$response->data(array_values($links));
|
||||
}
|
||||
@ -234,7 +233,7 @@ class Link extends Etemplate\Widget
|
||||
$result = Api\Vfs::proppatch($path, array(array('name' => 'comment', 'val' => $comment)));
|
||||
}
|
||||
}
|
||||
$response = egw_json_response::get();
|
||||
$response = Api\Json\Response::get();
|
||||
$response->data($result !== false);
|
||||
}
|
||||
|
||||
@ -258,7 +257,7 @@ class Link extends Etemplate\Widget
|
||||
|
||||
public static function ajax_delete($value)
|
||||
{
|
||||
$response = egw_json_response::get();
|
||||
$response = Api\Json\Response::get();
|
||||
$response->data(Api\Link::unlink($value));
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,6 @@ use EGroupware\Api\Etemplate;
|
||||
use EGroupware\Api;
|
||||
|
||||
// explicitly import old not yet ported classes
|
||||
use egw_json_response;
|
||||
use egw;
|
||||
use egw_framework; // includeCSS
|
||||
use categories;
|
||||
@ -291,7 +290,7 @@ class Nextmatch extends Etemplate\Widget
|
||||
{
|
||||
self::$request->content = array($form_name => array());
|
||||
}
|
||||
self::$response = egw_json_response::get();
|
||||
self::$response = Api\Json\Response::get();
|
||||
|
||||
$value = self::get_array(self::$request->content, $form_name, true);
|
||||
if(!is_array($value))
|
||||
@ -362,7 +361,7 @@ class Nextmatch extends Etemplate\Widget
|
||||
if (isset($GLOBALS['egw_info']['flags']['app_header']) && self::$request->app_header != $GLOBALS['egw_info']['flags']['app_header'])
|
||||
{
|
||||
self::$request->app_header = $GLOBALS['egw_info']['flags']['app_header'];
|
||||
egw_json_response::get()->apply('egw_app_header', array($GLOBALS['egw_info']['flags']['app_header']));
|
||||
Api\Json\Response::get()->apply('egw_app_header', array($GLOBALS['egw_info']['flags']['app_header']));
|
||||
}
|
||||
|
||||
$row_id = isset($value['row_id']) ? $value['row_id'] : 'id';
|
||||
@ -502,7 +501,7 @@ class Nextmatch extends Etemplate\Widget
|
||||
$changes = true;
|
||||
$request_value[$key] = $value[$key];
|
||||
|
||||
egw_json_response::get()->generic('assign', array(
|
||||
Api\Json\Response::get()->generic('assign', array(
|
||||
'etemplate_exec_id' => $exec_id,
|
||||
'id' => $form_name,
|
||||
'key' => $key,
|
||||
@ -519,12 +518,12 @@ class Nextmatch extends Etemplate\Widget
|
||||
|
||||
// Send back data
|
||||
//foreach($result as $name => $value) if ($name != 'readonlys') error_log(__METHOD__."() result['$name']=".array2string($name == 'data' ? array_keys($value) : $value));
|
||||
egw_json_response::get()->data($result);
|
||||
Api\Json\Response::get()->data($result);
|
||||
|
||||
// If etemplate_exec_id has changed, update the client side
|
||||
if (($new_id = self::$request->id()) != $exec_id)
|
||||
{
|
||||
egw_json_response::get()->generic('assign', array(
|
||||
Api\Json\Response::get()->generic('assign', array(
|
||||
'etemplate_exec_id' => $exec_id,
|
||||
'id' => '',
|
||||
'key' => 'etemplate_exec_id',
|
||||
|
@ -19,7 +19,6 @@ use EGroupware\Api;
|
||||
// explicitly import old not yet ported classes
|
||||
use categories;
|
||||
use calendar_timezones;
|
||||
use egw_json_response;
|
||||
|
||||
/**
|
||||
* eTemplate select widget
|
||||
@ -861,7 +860,7 @@ class Select extends Etemplate\Widget
|
||||
$no_lang = false;
|
||||
$options = self::typeOptions($type, $attributes,$no_lang,false,$value);
|
||||
self::fix_encoded_options($options,true);
|
||||
$response = egw_json_response::get();
|
||||
$response = Api\Json\Response::get();
|
||||
$response->data($options);
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ use EGroupware\Api\Etemplate;
|
||||
use EGroupware\Api;
|
||||
|
||||
// explicitly import old not yet ported classes
|
||||
use egw_json_request;
|
||||
use common;
|
||||
use mail_compose;
|
||||
|
||||
@ -74,7 +73,7 @@ class Taglist extends Etemplate\Widget
|
||||
$results[] = array('id' => $id, 'label' => $name);
|
||||
}
|
||||
// switch regular JSON response handling off
|
||||
egw_json_request::isJSONRequest(false);
|
||||
Api\Json\Request::isJSONRequest(false);
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
echo json_encode($results);
|
||||
|
@ -17,7 +17,6 @@ use EGroupware\Api\Etemplate;
|
||||
use EGroupware\Api;
|
||||
|
||||
// explicitly import old not yet ported classes
|
||||
use egw_json_request;
|
||||
use common; // egw_exit
|
||||
use categories;
|
||||
use egw_framework;
|
||||
@ -152,7 +151,7 @@ class Tree extends Etemplate\Widget
|
||||
public static function send_quote_json(array $data)
|
||||
{
|
||||
// switch regular JSON response handling off
|
||||
egw_json_request::isJSONRequest(false);
|
||||
Api\Json\Request::isJSONRequest(false);
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
echo json_encode(self::htmlencode_node($data));
|
||||
|
@ -17,7 +17,6 @@ use EGroupware\Api\Etemplate;
|
||||
use EGroupware\Api;
|
||||
|
||||
// explicitly import old not yet ported classes
|
||||
use egw_json_request;
|
||||
use common; // egw_exit
|
||||
use egw; // link
|
||||
|
||||
@ -162,7 +161,7 @@ class Vfs extends File
|
||||
}
|
||||
}
|
||||
// switch regular JSON response handling off
|
||||
egw_json_request::isJSONRequest(false);
|
||||
Api\Json\Request::isJSONRequest(false);
|
||||
|
||||
$file = array(
|
||||
"uploaded" => (int)empty($error),
|
||||
|
23
api/src/Json/Exception.php
Normal file
23
api/src/Json/Exception.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware API - Json Exceptions
|
||||
*
|
||||
* @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 json
|
||||
* @access public
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Json;
|
||||
|
||||
use EGroupware\Api;
|
||||
|
||||
/**
|
||||
* A method or function was called with a wrong or missing parameter
|
||||
*
|
||||
* As you get this only by an error in the code or during development, the message does not need to be translated
|
||||
*/
|
||||
class Exception extends Api\Exception\WrongParameter { }
|
23
api/src/Json/Exception/InvalidName.php
Normal file
23
api/src/Json/Exception/InvalidName.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware API - Json Exceptions
|
||||
*
|
||||
* @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 json
|
||||
* @access public
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Json\Exception;
|
||||
|
||||
use EGroupware\Api\Exception;
|
||||
|
||||
/**
|
||||
* A method or function was called with a wrong or missing parameter
|
||||
*
|
||||
* As you get this only by an error in the code or during development, the message does not need to be translated
|
||||
*/
|
||||
class InvalidName extends Exception\NoPermission { }
|
23
api/src/Json/Exception/NotOnline.php
Normal file
23
api/src/Json/Exception/NotOnline.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware API: push JSON commands to client
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage json
|
||||
* @author Ralf Becker <rb@stylite.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Json\Exception;
|
||||
|
||||
use EGroupware\Api\Json;
|
||||
|
||||
/**
|
||||
* Exception thrown, if message can not be pushed
|
||||
*/
|
||||
class NotOnline extends Json\Exception
|
||||
{
|
||||
|
||||
}
|
23
api/src/Json/Exception/ScriptTags.php
Normal file
23
api/src/Json/Exception/ScriptTags.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware API: push JSON commands to client
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage json
|
||||
* @author Ralf Becker <rb@stylite.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Json\Exception;
|
||||
|
||||
use EGroupware\Api\Json;
|
||||
|
||||
/**
|
||||
* Exception thrown, if request contains script tags
|
||||
*/
|
||||
class ScriptTags extends Json\Exception
|
||||
{
|
||||
|
||||
}
|
229
api/src/Json/Msg.php
Normal file
229
api/src/Json/Msg.php
Normal file
@ -0,0 +1,229 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware API: JSON - Contains functions and classes for doing JSON requests.
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage json
|
||||
* @author Andreas Stoeckel <as@stylite.de>
|
||||
* @author Ralf Becker <ralfbecker@outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Json;
|
||||
|
||||
/**
|
||||
* Abstract class implementing different type of JSON messages understood by client-side
|
||||
*/
|
||||
abstract class Msg
|
||||
{
|
||||
/**
|
||||
* Adds an "alert" to the response which can be handeled on the client side.
|
||||
*
|
||||
* The default implementation simply displays the text supplied here with the JavaScript function "alert".
|
||||
*
|
||||
* @param string $message contains the actual message being sent to the client.
|
||||
* @param string $details (optional) can be used to inform the user on the client side about additional details about the error. This might be information how the error can be resolved/why it was raised or simply some debug data.
|
||||
*/
|
||||
public function alert($message, $details = '')
|
||||
{
|
||||
if (is_string($message) && is_string($details))
|
||||
{
|
||||
$this->addGeneric('alert', array(
|
||||
"message" => $message,
|
||||
"details" => $details));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Invalid parameters supplied.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to add a generic java script to the response which will be executed upon the request gets received.
|
||||
*
|
||||
* @deprecated
|
||||
* @param string $script the script code which should be executed upon receiving
|
||||
*/
|
||||
public function script($script)
|
||||
{
|
||||
if (is_string($script))
|
||||
{
|
||||
$this->addGeneric('script', $script);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Invalid parameters supplied.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to call a global javascript function with given parameters: window[$func].apply(window, $parameters)
|
||||
*
|
||||
* @param string $function name of the global (window) javascript function to call
|
||||
* @param array $parameters =array()
|
||||
*/
|
||||
public function apply($function,array $parameters=array())
|
||||
{
|
||||
if (is_string($function))
|
||||
{
|
||||
$this->addGeneric('apply', array(
|
||||
'func' => $function,
|
||||
'parms' => $parameters,
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Invalid parameters supplied.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to call a global javascript function with given parameters: window[$func].call(window[, $param1[, ...]])
|
||||
*
|
||||
* @param string $func name of the global (window) javascript function to call
|
||||
* @param mixed $parameters variable number of parameters
|
||||
*/
|
||||
public function call($function)
|
||||
{
|
||||
$parameters = func_get_args();
|
||||
array_shift($parameters); // shift off $function
|
||||
|
||||
if (is_string($function))
|
||||
{
|
||||
$this->addGeneric('apply', array(
|
||||
'func' => $function,
|
||||
'parms' => $parameters,
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Invalid parameters supplied.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to call a jquery function on a selector with given parameters: $j($selector).$func($parmeters)
|
||||
*
|
||||
* @param string $selector jquery selector
|
||||
* @param string $method name of the jquery to call
|
||||
* @param array $parameters =array()
|
||||
*/
|
||||
public function jquery($selector,$method,array $parameters=array())
|
||||
{
|
||||
if (is_string($selector) && is_string($method))
|
||||
{
|
||||
$this->addGeneric('jquery', array(
|
||||
'select' => $selector,
|
||||
'func' => $method,
|
||||
'parms' => $parameters,
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Invalid parameters supplied.");
|
||||
}
|
||||
}
|
||||
|
||||
public function generic($type, array $parameters = array())
|
||||
{
|
||||
if (is_string($type))
|
||||
{
|
||||
$this->addGeneric($type, $parameters);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Invalid parameters supplied.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an html assign to the response, which is excecuted upon the request is received.
|
||||
*
|
||||
* @param string $id id of dom element to modify
|
||||
* @param string $key attribute name of dom element which should be modified
|
||||
* @param string $value the value which should be assigned to the given attribute
|
||||
*/
|
||||
public function assign($id, $key, $value)
|
||||
{
|
||||
if (is_string($id) && is_string($key) && (is_string($value) || is_numeric($value) || is_null($value)))
|
||||
{
|
||||
$this->addGeneric('assign', array(
|
||||
'id' => $id,
|
||||
'key' => $key,
|
||||
'value' => $value,
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Invalid parameters supplied");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect to given url
|
||||
*
|
||||
* @param string $url
|
||||
* @param boolean $global specifies whether to redirect the whole framework
|
||||
* @param string $app =null default current app from flags
|
||||
* or only the current application
|
||||
*/
|
||||
public function redirect($url, $global = false, $app=null)
|
||||
{
|
||||
if (is_string($url) && is_bool($global))
|
||||
{
|
||||
//self::script("location.href = '$url';");
|
||||
$this->addGeneric('redirect', array(
|
||||
'url' => $url,
|
||||
'global' => $global,
|
||||
'app' => $app ? $app : $GLOBALS['egw_info']['flags']['currentapp'],
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays an error message on the client
|
||||
*/
|
||||
public function error($msg)
|
||||
{
|
||||
if (is_string($msg))
|
||||
{
|
||||
$this->addGeneric('error', $msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Includes the given CSS file. Every url can only be included once.
|
||||
*
|
||||
* @param string $url specifies the url to the css file to include
|
||||
*/
|
||||
public function includeCSS($url)
|
||||
{
|
||||
if (is_string($url))
|
||||
{
|
||||
$this->addGeneric('css', $url);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Includes the given JS file. Every url can only be included once.
|
||||
*
|
||||
* @param string $url specifies the url to the css file to include
|
||||
*/
|
||||
public function includeScript($url)
|
||||
{
|
||||
if (is_string($url))
|
||||
{
|
||||
$this->addGeneric('js', $url);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds any type of data to the message
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $data
|
||||
*/
|
||||
abstract protected function addGeneric($key, $data);
|
||||
}
|
@ -5,15 +5,17 @@
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage ajax
|
||||
* @subpackage json
|
||||
* @author Ralf Becker <rb@stylite.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Json;
|
||||
|
||||
/**
|
||||
* Class to push JSON commands to client
|
||||
*/
|
||||
class egw_json_push extends egw_json_msg
|
||||
class Push extends Msg
|
||||
{
|
||||
/**
|
||||
* Available backends to try
|
||||
@ -51,7 +53,7 @@ class egw_json_push extends egw_json_msg
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $data
|
||||
* @throws egw_json_push_exception_not_online if $account_id is not online
|
||||
* @throws Exception\NotOnline if $account_id is not online
|
||||
*/
|
||||
protected function addGeneric($key, $data)
|
||||
{
|
||||
@ -65,41 +67,17 @@ class egw_json_push extends egw_json_msg
|
||||
self::$backend = new $class;
|
||||
break;
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// ignore exception
|
||||
catch (\Exception $e) {
|
||||
// ignore all exceptions
|
||||
unset($e, self::$backend);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isset(self::$backend))
|
||||
{
|
||||
throw new egw_json_push_exception_not_online('No valid push-backend found!');
|
||||
throw new Exception\NotOnline('No valid push-backend found!');
|
||||
}
|
||||
}
|
||||
self::$backend->addGeneric($this->account_id, $key, $data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for push backends
|
||||
*/
|
||||
interface egw_json_push_backend
|
||||
{
|
||||
/**
|
||||
* Adds any type of data to the message
|
||||
*
|
||||
* @param int $account_id account_id to push message too
|
||||
* @param string $key
|
||||
* @param mixed $data
|
||||
* @throws egw_json_push_exception_not_online if $account_id is not online
|
||||
*/
|
||||
public function addGeneric($account_id, $key, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception thrown, if message can not be pushed
|
||||
*/
|
||||
class egw_json_push_exception_not_online extends egw_exception_not_found
|
||||
{
|
||||
|
||||
}
|
29
api/src/Json/PushBackend.php
Normal file
29
api/src/Json/PushBackend.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware API: push JSON commands to client
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage json
|
||||
* @author Ralf Becker <rb@stylite.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Json;
|
||||
|
||||
/**
|
||||
* Interface for push backends
|
||||
*/
|
||||
interface PushBackend
|
||||
{
|
||||
/**
|
||||
* Adds any type of data to the message
|
||||
*
|
||||
* @param int $account_id account_id to push message too
|
||||
* @param string $key
|
||||
* @param mixed $data
|
||||
* @throws Exception\NotOnline if $account_id is not online
|
||||
*/
|
||||
public function addGeneric($account_id, $key, $data);
|
||||
}
|
185
api/src/Json/Request.php
Normal file
185
api/src/Json/Request.php
Normal file
@ -0,0 +1,185 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware API: JSON - Contains functions and classes for doing JSON requests.
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage json
|
||||
* @author Andreas Stoeckel <as@stylite.de>
|
||||
* @author Ralf Becker <ralfbecker@outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Json;
|
||||
|
||||
use ReflectionMethod;
|
||||
use EGroupware\Api;
|
||||
|
||||
// explicitly import old, not yet ported api classes
|
||||
use notifications_push;
|
||||
use egw_framework;
|
||||
|
||||
/**
|
||||
* Class handling JSON requests to the server
|
||||
*/
|
||||
class Request
|
||||
{
|
||||
private static $_hadJSONRequest = false;
|
||||
|
||||
/**
|
||||
* Check if JSON request running or (re)set JSON request flag
|
||||
*
|
||||
* Can be used to:
|
||||
* - detect regular JSON request:
|
||||
* Api\Json\Request::isJSONRequest()
|
||||
* - switch regular JSON response handling off, which would send arbitrary output via response method "html".
|
||||
* Neccessary if json.php is used to send arbitrary JSON data eg. nodes for foldertree!
|
||||
* Api\Json\Request::isJSONRequest(false)
|
||||
*
|
||||
* @param boolean $set =null
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isJSONRequest($set=null)
|
||||
{
|
||||
$ret = self::$_hadJSONRequest;
|
||||
if (isset($set)) self::$_hadJSONRequest = $set;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the raw input data supplied with the input_data parameter and calls the menuaction
|
||||
* passing all parameters supplied in the request to it.
|
||||
*
|
||||
* Also handle queued requests (menuaction == 'home.queue') containing multiple requests
|
||||
*
|
||||
* @param string menuaction to call
|
||||
* @param string $input_data is the RAW input data as it was received from the client
|
||||
*/
|
||||
public function parseRequest($menuaction, $input_data)
|
||||
{
|
||||
// Remember that we currently are in a JSON request - e.g. used in the redirect code
|
||||
self::$_hadJSONRequest = true;
|
||||
|
||||
if (get_magic_quotes_gpc()) $input_data = stripslashes($input_data);
|
||||
|
||||
$json_data = json_decode($input_data,true);
|
||||
if (is_array($json_data) && isset($json_data['request']) && isset($json_data['request']['parameters']) && is_array($json_data['request']['parameters']))
|
||||
{
|
||||
//error_log(__METHOD__.__LINE__.array2string($json_data['request']).function_backtrace());
|
||||
$parameters =& $json_data['request']['parameters'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$parameters = array();
|
||||
}
|
||||
// do we have a single request or an array of queued requests
|
||||
if ($menuaction == 'home.queue')
|
||||
{
|
||||
$responses = array();
|
||||
$response = Response::get();
|
||||
foreach($parameters[0] as $uid => $data)
|
||||
{
|
||||
//error_log("$uid: menuaction=$data[menuaction], parameters=".array2string($data['parameters']));
|
||||
$this->handleRequest($data['menuaction'], (array)$data['parameters']);
|
||||
$responses[$uid] = $response->initResponseArray();
|
||||
//error_log("responses[$uid]=".array2string($responses[$uid]));
|
||||
}
|
||||
$response->data($responses); // send all responses as data
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->handleRequest($menuaction, $parameters);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request handler
|
||||
*
|
||||
* @param string $menuaction
|
||||
* @param array $parameters
|
||||
*/
|
||||
public function handleRequest($menuaction, array $parameters)
|
||||
{
|
||||
if (strpos($menuaction,'::') !== false && strpos($menuaction,'.') === false) // static method name app_something::method
|
||||
{
|
||||
@list($className,$functionName,$handler) = explode('::',$menuaction);
|
||||
if (substr($className, 0, 11) == 'EGroupware\\')
|
||||
{
|
||||
list(,$appName) = explode('\\', strtolower($className));
|
||||
}
|
||||
else
|
||||
{
|
||||
list($appName) = explode('_',$className);
|
||||
}
|
||||
|
||||
// Check for a real static method, avoid instanciation if it is
|
||||
$m = new ReflectionMethod($menuaction);
|
||||
if($m->isStatic())
|
||||
{
|
||||
$ajaxClass = $className;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@list($appName, $className, $functionName, $handler) = explode('.',$menuaction);
|
||||
}
|
||||
//error_log("json.php: appName=$appName, className=$className, functionName=$functionName, handler=$handler");
|
||||
|
||||
switch($handler)
|
||||
{
|
||||
case '/etemplate/process_exec':
|
||||
$_GET['menuaction'] = $appName.'.'.$className.'.'.$functionName;
|
||||
$appName = $className = 'etemplate';
|
||||
$functionName = 'process_exec';
|
||||
$menuaction = 'etemplate.etemplate.process_exec';
|
||||
|
||||
$parameters = array(
|
||||
$parameters[0]['etemplate_exec_id'],
|
||||
$parameters[0]['submit_button'],
|
||||
$parameters[0],
|
||||
'xajaxResponse',
|
||||
);
|
||||
//error_log("xajax_doXMLHTTP() /etemplate/process_exec handler: arg0='$menuaction', menuaction='$_GET[menuaction]'");
|
||||
break;
|
||||
case 'etemplate': // eg. ajax code in an eTemplate widget
|
||||
$menuaction = ($appName = 'etemplate').'.'.$className.'.'.$functionName;
|
||||
break;
|
||||
case 'template': // calling current template / framework object
|
||||
$menuaction = $appName.'.'.$className.'.'.$functionName;
|
||||
$className = get_class($GLOBALS['egw']->framework);
|
||||
list($template) = explode('_', $className);
|
||||
break;
|
||||
}
|
||||
|
||||
if(substr($className,0,4) != 'ajax' && substr($className,-4) != 'ajax' &&
|
||||
$menuaction != 'etemplate.etemplate.process_exec' && substr($functionName,0,4) != 'ajax' ||
|
||||
!preg_match('/^[A-Za-z0-9_\\\\-]+(\.[A-Za-z0-9_\\\\]+\.|::)[A-Za-z0-9_]+$/',$menuaction))
|
||||
{
|
||||
// stopped for security reasons
|
||||
error_log("className='$className', functionName='$functionName', menuaction='$menuaction'");
|
||||
error_log($_SERVER['PHP_SELF']. ' stopped for security reason. '.$menuaction.' is not valid. class- or function-name must start with ajax!!!');
|
||||
// send message also to the user
|
||||
throw new Exception\InvalidName($_SERVER['PHP_SELF']. ' stopped for security reason. '.$menuaction.' is not valid. class- or function-name must start with ajax!!!');
|
||||
}
|
||||
|
||||
if (isset($template))
|
||||
{
|
||||
$ajaxClass = $GLOBALS['egw']->framework;
|
||||
}
|
||||
else if (!$ajaxClass)
|
||||
{
|
||||
$ajaxClass = class_exists($className) ? new $className() : CreateObject($appName.'.'.$className);
|
||||
}
|
||||
|
||||
// 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());
|
||||
|
||||
call_user_func_array(array($ajaxClass, $functionName),
|
||||
Api\Translation::convert($parameters, 'utf-8'));
|
||||
|
||||
// check if we have push notifications, if notifications app available
|
||||
if (class_exists('notifications_push')) notifications_push::get();
|
||||
}
|
||||
}
|
309
api/src/Json/Response.php
Normal file
309
api/src/Json/Response.php
Normal file
@ -0,0 +1,309 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware API: JSON - Contains functions and classes for doing JSON requests.
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage json
|
||||
* @author Andreas Stoeckel <as@stylite.de>
|
||||
* @author Ralf Becker <ralfbecker@outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Json;
|
||||
|
||||
use EGroupware\Api;
|
||||
|
||||
/**
|
||||
* Class used to send ajax responses
|
||||
*/
|
||||
class Response extends Msg
|
||||
{
|
||||
/**
|
||||
* A response can only contain one generic data part.
|
||||
* This variable is used to store, whether a data part had already been added to the response.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
private $hasData = false;
|
||||
|
||||
/**
|
||||
* Array containing all beforeSendData callbacks
|
||||
*/
|
||||
protected $beforeSendDataProcs = array();
|
||||
|
||||
/**
|
||||
* Holds the actual response data which is then encoded to JSON
|
||||
* once the "getJSON" function is called
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $responseArray = array();
|
||||
|
||||
/**
|
||||
* Holding instance of class for singelton Response::get()
|
||||
*
|
||||
* @var Response
|
||||
*/
|
||||
private static $response = null;
|
||||
|
||||
/**
|
||||
* Force use of singleton: $response = Response::get();
|
||||
*/
|
||||
protected function __construct()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Singelton for class
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public static function get()
|
||||
{
|
||||
if (!isset(self::$response))
|
||||
{
|
||||
self::$response = new Response();
|
||||
self::sendHeader();
|
||||
}
|
||||
return self::$response;
|
||||
}
|
||||
|
||||
public static function isJSONResponse()
|
||||
{
|
||||
return isset(self::$response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do we have a JSON response to send back
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function haveJSONResponse()
|
||||
{
|
||||
return $this->responseArray || $this->beforeSendDataProcs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private function used to send the HTTP header of the JSON response
|
||||
*/
|
||||
private static function sendHeader()
|
||||
{
|
||||
$file = $line = null;
|
||||
if (headers_sent($file, $line))
|
||||
{
|
||||
error_log(__METHOD__."() header already sent by $file line $line: ".function_backtrace());
|
||||
}
|
||||
else
|
||||
{
|
||||
//Send the character encoding header
|
||||
header('content-type: application/json; charset='.Api\Translation::charset());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Private function which is used to send the result via HTTP
|
||||
*/
|
||||
public static function sendResult()
|
||||
{
|
||||
$inst = self::get();
|
||||
|
||||
//Call each attached before send data proc
|
||||
foreach ($inst->beforeSendDataProcs as $proc)
|
||||
{
|
||||
call_user_func_array($proc['proc'], $proc['params']);
|
||||
}
|
||||
|
||||
// check if application made some direct output
|
||||
if (($output = ob_get_clean()))
|
||||
{
|
||||
if (!$inst->haveJSONResponse())
|
||||
{
|
||||
error_log(__METHOD__."() adding output with inst->addGeneric('html', '$output')");
|
||||
$inst->addGeneric('html', $output);
|
||||
}
|
||||
else
|
||||
{
|
||||
$inst->alert('Application echoed something', $output);
|
||||
}
|
||||
}
|
||||
|
||||
echo $inst->getJSON();
|
||||
$inst->initResponseArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return json response data, after running beforeSendDataProcs
|
||||
*
|
||||
* Used to send json response with etemplate data in GET request
|
||||
*
|
||||
* @return array responseArray
|
||||
*/
|
||||
public static function returnResult()
|
||||
{
|
||||
$inst = self::get();
|
||||
|
||||
//Call each attached before send data proc
|
||||
foreach ($inst->beforeSendDataProcs as $proc)
|
||||
{
|
||||
call_user_func_array($proc['proc'], $proc['params']);
|
||||
}
|
||||
return $inst->initResponseArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* xAjax compatibility function
|
||||
*
|
||||
* @deprecated output is send by egw::__destruct()
|
||||
*/
|
||||
public function printOutput()
|
||||
{
|
||||
// do nothing, as output is triggered by egw::__destruct()
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds any type of data to the message
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $data
|
||||
*/
|
||||
protected function addGeneric($key, $data)
|
||||
{
|
||||
self::get()->responseArray[] = array(
|
||||
'type' => $key,
|
||||
'data' => $data,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init responseArray
|
||||
*
|
||||
* @param array $arr
|
||||
* @return array previous content
|
||||
*/
|
||||
public function initResponseArray()
|
||||
{
|
||||
$return = $this->responseArray;
|
||||
$this->responseArray = $this->beforeSendDataProcs = array();
|
||||
$this->hasData = false;
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a "data" response to the json response.
|
||||
*
|
||||
* This function may only be called once for a single JSON response object.
|
||||
*
|
||||
* @param object|array|string $data can be of any data type and will be added JSON Encoded to your response.
|
||||
*/
|
||||
public function data($data)
|
||||
{
|
||||
/* Only allow adding the data response once */
|
||||
$inst = self::get();
|
||||
if (!$inst->hasData)
|
||||
{
|
||||
$inst->addGeneric('data', $data);
|
||||
$inst->hasData = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Adding more than one data response to a JSON response is not allowed.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual JSON code generated by calling the above "add" function.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getJSON()
|
||||
{
|
||||
$inst = self::get();
|
||||
|
||||
/* Wrap the result array into a parent "response" Object */
|
||||
$res = array('response' => $inst->responseArray);
|
||||
|
||||
return self::json_encode($res); //PHP5.3+, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP);
|
||||
}
|
||||
|
||||
/**
|
||||
* More fault-tollerant version of json_encode removing everything that does not json_encode eg. because not utf-8
|
||||
*
|
||||
* @param mixed $var
|
||||
* @return string
|
||||
*/
|
||||
public static function json_encode($var)
|
||||
{
|
||||
$ret = json_encode($var);
|
||||
|
||||
if ($ret === false && ($err = json_last_error()))
|
||||
{
|
||||
static $json_err2str = array(
|
||||
JSON_ERROR_NONE => 'No errors',
|
||||
JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
|
||||
JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch',
|
||||
JSON_ERROR_CTRL_CHAR => 'Unexpected control character found',
|
||||
JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON',
|
||||
JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded',
|
||||
);
|
||||
error_log(__METHOD__.'('.array2string($var).') json_last_error()='.$err.'='.$json_err2str[$err]);
|
||||
|
||||
if (($var = self::fix_content($var)))
|
||||
{
|
||||
return self::json_encode($var);
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set everything in $var to null, that does not json_encode, eg. because no valid utf-8
|
||||
*
|
||||
* @param midex $var
|
||||
* @param string $prefix =''
|
||||
* @return mixed
|
||||
*/
|
||||
public static function fix_content($var, $prefix='')
|
||||
{
|
||||
if (json_encode($var) !== false) return $var;
|
||||
|
||||
if (is_scalar($var))
|
||||
{
|
||||
error_log(__METHOD__."() json_encode($prefix='$var') === false --> setting it to null");
|
||||
$var = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach($var as $name => &$value)
|
||||
{
|
||||
$value = self::fix_content($value, $prefix ? $prefix.'['.$name.']' : $name);
|
||||
}
|
||||
}
|
||||
return $var;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function which can be used to add an event listener callback function to
|
||||
* the "beforeSendData" callback. This callback might be used to add a response
|
||||
* which always has to be added after all other responses.
|
||||
* @param callback Callback function or method which should be called before the response gets sent
|
||||
* @param mixed n Optional parameters which get passed to the callback function.
|
||||
*/
|
||||
public function addBeforeSendDataCallback($proc)
|
||||
{
|
||||
//Get the current instance
|
||||
$inst = self::get();
|
||||
|
||||
//Get all parameters passed to the function and delete the first one
|
||||
$params = func_get_args();
|
||||
array_shift($params);
|
||||
|
||||
$inst->beforeSendDataProcs[] = array(
|
||||
'proc' => $proc,
|
||||
'params' => $params
|
||||
);
|
||||
}
|
||||
}
|
@ -19,7 +19,6 @@ namespace EGroupware\Api;
|
||||
|
||||
// explicitly reference classes still in phpgwapi
|
||||
use egw; // on_shutdown
|
||||
use egw_json_response;
|
||||
|
||||
/**
|
||||
* Generalized linking between entries of EGroupware apps
|
||||
@ -1474,10 +1473,10 @@ class Link extends Link\Storage
|
||||
{
|
||||
self::notify('update',$link['app'],$link['id'],$app,$id,$link_id,$data);
|
||||
}
|
||||
if($data[Link::OLD_LINK_TITLE] && egw_json_response::isJSONResponse())
|
||||
if($data[Link::OLD_LINK_TITLE] && Api\Json\Response::isJSONResponse())
|
||||
{
|
||||
// Update client side with new title
|
||||
egw_json_response::get()->apply('egw.link_title_callback',array(array($app => array($id => self::title($app, $id)))));
|
||||
Api\Json\Response::get()->apply('egw.link_title_callback',array(array($app => array($id => self::title($app, $id)))));
|
||||
}
|
||||
}
|
||||
|
||||
|
16
json.php
16
json.php
@ -10,6 +10,8 @@
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
use EGroupware\Api\Json;
|
||||
|
||||
/**
|
||||
* callback if the session-check fails, redirects to login.php
|
||||
*
|
||||
@ -19,8 +21,8 @@
|
||||
function login_redirect(&$anon_account)
|
||||
{
|
||||
unset($anon_account);
|
||||
egw_json_request::isJSONRequest(true); // because egw_json_request::parseRequest() is not (yet) called
|
||||
$response = egw_json_response::get();
|
||||
Json\Request::isJSONRequest(true); // because egw_json_request::parseRequest() is not (yet) called
|
||||
$response = Json\Response::get();
|
||||
$response->redirect($GLOBALS['egw_info']['server']['webserver_url'].'/login.php?cd=10', true);
|
||||
|
||||
common::egw_exit();
|
||||
@ -46,7 +48,7 @@ function ajax_exception_handler($e)
|
||||
{
|
||||
_egw_log_exception($e,$message);
|
||||
}
|
||||
$response = egw_json_response::get();
|
||||
$response = Json\Response::get();
|
||||
$message .= ($message ? "\n\n" : '').$e->getMessage();
|
||||
|
||||
// only show trace (incl. function arguments) if explicitly enabled, eg. on a development system
|
||||
@ -103,17 +105,17 @@ if (isset($_GET['menuaction']))
|
||||
|
||||
|
||||
//Create a new json handler
|
||||
$json = new egw_json_request();
|
||||
$json = new Json\Request();
|
||||
|
||||
//Check whether the request data is set
|
||||
if (isset($GLOBALS['egw_unset_vars']['_POST[json_data]']))
|
||||
{
|
||||
$json->isJSONRequest(true); // otherwise exception is not send back to client, as we have not yet called parseRequest()
|
||||
throw new egw_exception_assertion_failed("JSON Data contains script tags. Aborting...");
|
||||
throw new Json\Exception\ScriptTags("JSON Data contains script tags. Aborting...");
|
||||
}
|
||||
$json->parseRequest($_GET['menuaction'], $_REQUEST['json_data']);
|
||||
egw_json_response::get();
|
||||
Json\Response::get();
|
||||
common::egw_exit();
|
||||
}
|
||||
|
||||
throw new Exception($_SERVER['PHP_SELF'] . ' Invalid AJAX JSON Request');
|
||||
throw new Json\Exception($_SERVER['PHP_SELF'] . ' Invalid AJAX JSON Request');
|
||||
|
@ -10,523 +10,20 @@
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
use EGroupware\Api\Json;
|
||||
|
||||
/**
|
||||
* Class handling JSON requests to the server
|
||||
*
|
||||
* @deprecated use Api\Json\Request
|
||||
*/
|
||||
class egw_json_request
|
||||
{
|
||||
private static $_hadJSONRequest = false;
|
||||
|
||||
/**
|
||||
* Check if JSON request running or (re)set JSON request flag
|
||||
*
|
||||
* Can be used to:
|
||||
* - detect regular JSON request:
|
||||
* egw_json_request::isJSONRequest()
|
||||
* - switch regular JSON response handling off, which would send arbitrary output via response method "html".
|
||||
* Neccessary if json.php is used to send arbitrary JSON data eg. nodes for foldertree!
|
||||
* egw_json_request::isJSONRequest(false)
|
||||
*
|
||||
* @param boolean $set =null
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isJSONRequest($set=null)
|
||||
{
|
||||
$ret = self::$_hadJSONRequest;
|
||||
if (isset($set)) self::$_hadJSONRequest = $set;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the raw input data supplied with the input_data parameter and calls the menuaction
|
||||
* passing all parameters supplied in the request to it.
|
||||
*
|
||||
* Also handle queued requests (menuaction == 'home.queue') containing multiple requests
|
||||
*
|
||||
* @param string menuaction to call
|
||||
* @param string $input_data is the RAW input data as it was received from the client
|
||||
*/
|
||||
public function parseRequest($menuaction, $input_data)
|
||||
{
|
||||
// Remember that we currently are in a JSON request - e.g. used in the redirect code
|
||||
self::$_hadJSONRequest = true;
|
||||
|
||||
if (get_magic_quotes_gpc()) $input_data = stripslashes($input_data);
|
||||
|
||||
$json_data = json_decode($input_data,true);
|
||||
if (is_array($json_data) && isset($json_data['request']) && isset($json_data['request']['parameters']) && is_array($json_data['request']['parameters']))
|
||||
{
|
||||
//error_log(__METHOD__.__LINE__.array2string($json_data['request']).function_backtrace());
|
||||
$parameters =& $json_data['request']['parameters'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$parameters = array();
|
||||
}
|
||||
// do we have a single request or an array of queued requests
|
||||
if ($menuaction == 'home.queue')
|
||||
{
|
||||
$responses = array();
|
||||
$response = egw_json_response::get();
|
||||
foreach($parameters[0] as $uid => $data)
|
||||
{
|
||||
//error_log("$uid: menuaction=$data[menuaction], parameters=".array2string($data['parameters']));
|
||||
$this->handleRequest($data['menuaction'], (array)$data['parameters']);
|
||||
$responses[$uid] = $response->initResponseArray();
|
||||
//error_log("responses[$uid]=".array2string($responses[$uid]));
|
||||
}
|
||||
$response->data($responses); // send all responses as data
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->handleRequest($menuaction, $parameters);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request handler
|
||||
*
|
||||
* @param string $menuaction
|
||||
* @param array $parameters
|
||||
*/
|
||||
public function handleRequest($menuaction, array $parameters)
|
||||
{
|
||||
if (strpos($menuaction,'::') !== false && strpos($menuaction,'.') === false) // static method name app_something::method
|
||||
{
|
||||
@list($className,$functionName,$handler) = explode('::',$menuaction);
|
||||
if (substr($className, 0, 11) == 'EGroupware\\')
|
||||
{
|
||||
list(,$appName) = explode('\\', strtolower($className));
|
||||
}
|
||||
else
|
||||
{
|
||||
list($appName) = explode('_',$className);
|
||||
}
|
||||
|
||||
// Check for a real static method, avoid instanciation if it is
|
||||
$m = new ReflectionMethod($menuaction);
|
||||
if($m->isStatic())
|
||||
{
|
||||
$ajaxClass = $className;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@list($appName, $className, $functionName, $handler) = explode('.',$menuaction);
|
||||
}
|
||||
//error_log("json.php: appName=$appName, className=$className, functionName=$functionName, handler=$handler");
|
||||
|
||||
switch($handler)
|
||||
{
|
||||
case '/etemplate/process_exec':
|
||||
$_GET['menuaction'] = $appName.'.'.$className.'.'.$functionName;
|
||||
$appName = $className = 'etemplate';
|
||||
$functionName = 'process_exec';
|
||||
$menuaction = 'etemplate.etemplate.process_exec';
|
||||
|
||||
$parameters = array(
|
||||
$parameters[0]['etemplate_exec_id'],
|
||||
$parameters[0]['submit_button'],
|
||||
$parameters[0],
|
||||
'xajaxResponse',
|
||||
);
|
||||
//error_log("xajax_doXMLHTTP() /etemplate/process_exec handler: arg0='$menuaction', menuaction='$_GET[menuaction]'");
|
||||
break;
|
||||
case 'etemplate': // eg. ajax code in an eTemplate widget
|
||||
$menuaction = ($appName = 'etemplate').'.'.$className.'.'.$functionName;
|
||||
break;
|
||||
case 'template': // calling current template / framework object
|
||||
$menuaction = $appName.'.'.$className.'.'.$functionName;
|
||||
$className = get_class($GLOBALS['egw']->framework);
|
||||
list($template) = explode('_', $className);
|
||||
break;
|
||||
}
|
||||
|
||||
if(substr($className,0,4) != 'ajax' && substr($className,-4) != 'ajax' &&
|
||||
$menuaction != 'etemplate.etemplate.process_exec' && substr($functionName,0,4) != 'ajax' ||
|
||||
!preg_match('/^[A-Za-z0-9_\\\\-]+(\.[A-Za-z0-9_\\\\]+\.|::)[A-Za-z0-9_]+$/',$menuaction))
|
||||
{
|
||||
// stopped for security reasons
|
||||
error_log("className='$className', functionName='$functionName', menuaction='$menuaction'");
|
||||
error_log($_SERVER['PHP_SELF']. ' stopped for security reason. '.$menuaction.' is not valid. class- or function-name must start with ajax!!!');
|
||||
// send message also to the user
|
||||
throw new Exception($_SERVER['PHP_SELF']. ' stopped for security reason. '.$menuaction.' is not valid. class- or function-name must start with ajax!!!');
|
||||
}
|
||||
|
||||
if (isset($template))
|
||||
{
|
||||
$ajaxClass = $GLOBALS['egw']->framework;
|
||||
}
|
||||
else if (!$ajaxClass)
|
||||
{
|
||||
$ajaxClass = CreateObject($appName.'.'.$className);
|
||||
}
|
||||
|
||||
// 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());
|
||||
|
||||
call_user_func_array(array($ajaxClass, $functionName),
|
||||
translation::convert($parameters, 'utf-8'));
|
||||
|
||||
// check if we have push notifications, if notifications app available
|
||||
if (class_exists('notifications_push')) notifications_push::get();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract class implementing different type of JSON messages understood by client-side
|
||||
*/
|
||||
abstract class egw_json_msg
|
||||
{
|
||||
/**
|
||||
* Adds an "alert" to the response which can be handeled on the client side.
|
||||
*
|
||||
* The default implementation simply displays the text supplied here with the JavaScript function "alert".
|
||||
*
|
||||
* @param string $message contains the actual message being sent to the client.
|
||||
* @param string $details (optional) can be used to inform the user on the client side about additional details about the error. This might be information how the error can be resolved/why it was raised or simply some debug data.
|
||||
*/
|
||||
public function alert($message, $details = '')
|
||||
{
|
||||
if (is_string($message) && is_string($details))
|
||||
{
|
||||
$this->addGeneric('alert', array(
|
||||
"message" => $message,
|
||||
"details" => $details));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Invalid parameters supplied.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to add a generic java script to the response which will be executed upon the request gets received.
|
||||
*
|
||||
* @deprecated
|
||||
* @param string $script the script code which should be executed upon receiving
|
||||
*/
|
||||
public function script($script)
|
||||
{
|
||||
if (is_string($script))
|
||||
{
|
||||
$this->addGeneric('script', $script);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Invalid parameters supplied.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to call a global javascript function with given parameters: window[$func].apply(window, $parameters)
|
||||
*
|
||||
* @param string $function name of the global (window) javascript function to call
|
||||
* @param array $parameters =array()
|
||||
*/
|
||||
public function apply($function,array $parameters=array())
|
||||
{
|
||||
if (is_string($function))
|
||||
{
|
||||
$this->addGeneric('apply', array(
|
||||
'func' => $function,
|
||||
'parms' => $parameters,
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Invalid parameters supplied.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to call a global javascript function with given parameters: window[$func].call(window[, $param1[, ...]])
|
||||
*
|
||||
* @param string $func name of the global (window) javascript function to call
|
||||
* @param mixed $parameters variable number of parameters
|
||||
*/
|
||||
public function call($function)
|
||||
{
|
||||
$parameters = func_get_args();
|
||||
array_shift($parameters); // shift off $function
|
||||
|
||||
if (is_string($function))
|
||||
{
|
||||
$this->addGeneric('apply', array(
|
||||
'func' => $function,
|
||||
'parms' => $parameters,
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Invalid parameters supplied.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to call a jquery function on a selector with given parameters: $j($selector).$func($parmeters)
|
||||
*
|
||||
* @param string $selector jquery selector
|
||||
* @param string $method name of the jquery to call
|
||||
* @param array $parameters =array()
|
||||
*/
|
||||
public function jquery($selector,$method,array $parameters=array())
|
||||
{
|
||||
if (is_string($selector) && is_string($method))
|
||||
{
|
||||
$this->addGeneric('jquery', array(
|
||||
'select' => $selector,
|
||||
'func' => $method,
|
||||
'parms' => $parameters,
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Invalid parameters supplied.");
|
||||
}
|
||||
}
|
||||
|
||||
public function generic($type, array $parameters = array())
|
||||
{
|
||||
if (is_string($type))
|
||||
{
|
||||
$this->addGeneric($type, $parameters);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Invalid parameters supplied.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an html assign to the response, which is excecuted upon the request is received.
|
||||
*
|
||||
* @param string $id id of dom element to modify
|
||||
* @param string $key attribute name of dom element which should be modified
|
||||
* @param string $value the value which should be assigned to the given attribute
|
||||
*/
|
||||
public function assign($id, $key, $value)
|
||||
{
|
||||
if (is_string($id) && is_string($key) && (is_string($value) || is_numeric($value) || is_null($value)))
|
||||
{
|
||||
$this->addGeneric('assign', array(
|
||||
'id' => $id,
|
||||
'key' => $key,
|
||||
'value' => $value,
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Invalid parameters supplied");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect to given url
|
||||
*
|
||||
* @param string $url
|
||||
* @param boolean $global specifies whether to redirect the whole framework
|
||||
* @param string $app =null default current app from flags
|
||||
* or only the current application
|
||||
*/
|
||||
public function redirect($url, $global = false, $app=null)
|
||||
{
|
||||
if (is_string($url) && is_bool($global))
|
||||
{
|
||||
//self::script("location.href = '$url';");
|
||||
$this->addGeneric('redirect', array(
|
||||
'url' => $url,
|
||||
'global' => $global,
|
||||
'app' => $app ? $app : $GLOBALS['egw_info']['flags']['currentapp'],
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays an error message on the client
|
||||
*/
|
||||
public function error($msg)
|
||||
{
|
||||
if (is_string($msg))
|
||||
{
|
||||
$this->addGeneric('error', $msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Includes the given CSS file. Every url can only be included once.
|
||||
*
|
||||
* @param string $url specifies the url to the css file to include
|
||||
*/
|
||||
public function includeCSS($url)
|
||||
{
|
||||
if (is_string($url))
|
||||
{
|
||||
$this->addGeneric('css', $url);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Includes the given JS file. Every url can only be included once.
|
||||
*
|
||||
* @param string $url specifies the url to the css file to include
|
||||
*/
|
||||
public function includeScript($url)
|
||||
{
|
||||
if (is_string($url))
|
||||
{
|
||||
$this->addGeneric('js', $url);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds any type of data to the message
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $data
|
||||
*/
|
||||
abstract protected function addGeneric($key, $data);
|
||||
}
|
||||
class egw_json_request extends Json\Request {}
|
||||
|
||||
/**
|
||||
* Class used to send ajax responses
|
||||
*/
|
||||
class egw_json_response extends egw_json_msg
|
||||
class egw_json_response extends Json\Response
|
||||
{
|
||||
/**
|
||||
* A response can only contain one generic data part.
|
||||
* This variable is used to store, whether a data part had already been added to the response.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
private $hasData = false;
|
||||
|
||||
/**
|
||||
* Array containing all beforeSendData callbacks
|
||||
*/
|
||||
protected $beforeSendDataProcs = array();
|
||||
|
||||
/**
|
||||
* Holds the actual response data which is then encoded to JSON
|
||||
* once the "getJSON" function is called
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $responseArray = array();
|
||||
|
||||
/**
|
||||
* Holding instance of class for singelton egw_json_response::get()
|
||||
*
|
||||
* @var egw_json_response
|
||||
*/
|
||||
private static $response = null;
|
||||
|
||||
/**
|
||||
* Force use of singleton: $response = egw_json_response::get();
|
||||
*/
|
||||
protected function __construct()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Singelton for class
|
||||
*
|
||||
* @return egw_json_response
|
||||
*/
|
||||
public static function get()
|
||||
{
|
||||
if (!isset(self::$response))
|
||||
{
|
||||
self::$response = new egw_json_response();
|
||||
self::sendHeader();
|
||||
}
|
||||
return self::$response;
|
||||
}
|
||||
|
||||
public static function isJSONResponse()
|
||||
{
|
||||
return isset(self::$response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do we have a JSON response to send back
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function haveJSONResponse()
|
||||
{
|
||||
return $this->responseArray || $this->beforeSendDataProcs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private function used to send the HTTP header of the JSON response
|
||||
*/
|
||||
private static function sendHeader()
|
||||
{
|
||||
$file = $line = null;
|
||||
if (headers_sent($file, $line))
|
||||
{
|
||||
error_log(__METHOD__."() header already sent by $file line $line: ".function_backtrace());
|
||||
}
|
||||
else
|
||||
{
|
||||
//Send the character encoding header
|
||||
header('content-type: application/json; charset='.translation::charset());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Private function which is used to send the result via HTTP
|
||||
*/
|
||||
public static function sendResult()
|
||||
{
|
||||
$inst = self::get();
|
||||
|
||||
//Call each attached before send data proc
|
||||
foreach ($inst->beforeSendDataProcs as $proc)
|
||||
{
|
||||
call_user_func_array($proc['proc'], $proc['params']);
|
||||
}
|
||||
|
||||
// check if application made some direct output
|
||||
if (($output = ob_get_clean()))
|
||||
{
|
||||
if (!$inst->haveJSONResponse())
|
||||
{
|
||||
error_log(__METHOD__."() adding output with inst->addGeneric('html', '$output')");
|
||||
$inst->addGeneric('html', $output);
|
||||
}
|
||||
else
|
||||
{
|
||||
$inst->alert('Application echoed something', $output);
|
||||
}
|
||||
}
|
||||
|
||||
echo $inst->getJSON();
|
||||
$inst->initResponseArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return json response data, after running beforeSendDataProcs
|
||||
*
|
||||
* Used to send json response with etemplate data in GET request
|
||||
*
|
||||
* @return array responseArray
|
||||
*/
|
||||
public static function returnResult()
|
||||
{
|
||||
$inst = self::get();
|
||||
|
||||
//Call each attached before send data proc
|
||||
foreach ($inst->beforeSendDataProcs as $proc)
|
||||
{
|
||||
call_user_func_array($proc['proc'], $proc['params']);
|
||||
}
|
||||
return $inst->initResponseArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* xAjax compatibility function
|
||||
*/
|
||||
@ -534,154 +31,12 @@ class egw_json_response extends egw_json_msg
|
||||
{
|
||||
// do nothing, as output is triggered by egw::__destruct()
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds any type of data to the message
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $data
|
||||
*/
|
||||
protected function addGeneric($key, $data)
|
||||
{
|
||||
self::get()->responseArray[] = array(
|
||||
'type' => $key,
|
||||
'data' => $data,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init responseArray
|
||||
*
|
||||
* @param array $arr
|
||||
* @return array previous content
|
||||
*/
|
||||
public function initResponseArray()
|
||||
{
|
||||
$return = $this->responseArray;
|
||||
$this->responseArray = $this->beforeSendDataProcs = array();
|
||||
$this->hasData = false;
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a "data" response to the json response.
|
||||
*
|
||||
* This function may only be called once for a single JSON response object.
|
||||
*
|
||||
* @param object|array|string $data can be of any data type and will be added JSON Encoded to your response.
|
||||
*/
|
||||
public function data($data)
|
||||
{
|
||||
/* Only allow adding the data response once */
|
||||
$inst = self::get();
|
||||
if (!$inst->hasData)
|
||||
{
|
||||
$inst->addGeneric('data', $data);
|
||||
$inst->hasData = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Adding more than one data response to a JSON response is not allowed.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual JSON code generated by calling the above "add" function.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getJSON()
|
||||
{
|
||||
$inst = self::get();
|
||||
|
||||
/* Wrap the result array into a parent "response" Object */
|
||||
$res = array('response' => $inst->responseArray);
|
||||
|
||||
return self::json_encode($res); //PHP5.3+, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP);
|
||||
}
|
||||
|
||||
/**
|
||||
* More fault-tollerant version of json_encode removing everything that does not json_encode eg. because not utf-8
|
||||
*
|
||||
* @param mixed $var
|
||||
* @return string
|
||||
*/
|
||||
public static function json_encode($var)
|
||||
{
|
||||
$ret = json_encode($var);
|
||||
|
||||
if ($ret === false && ($err = json_last_error()))
|
||||
{
|
||||
static $json_err2str = array(
|
||||
JSON_ERROR_NONE => 'No errors',
|
||||
JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
|
||||
JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch',
|
||||
JSON_ERROR_CTRL_CHAR => 'Unexpected control character found',
|
||||
JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON',
|
||||
JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded',
|
||||
);
|
||||
error_log(__METHOD__.'('.array2string($var).') json_last_error()='.$err.'='.$json_err2str[$err]);
|
||||
|
||||
if (($var = self::fix_content($var)))
|
||||
{
|
||||
return self::json_encode($var);
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set everything in $var to null, that does not json_encode, eg. because no valid utf-8
|
||||
*
|
||||
* @param midex $var
|
||||
* @param string $prefix =''
|
||||
* @return mixed
|
||||
*/
|
||||
public static function fix_content($var, $prefix='')
|
||||
{
|
||||
if (json_encode($var) !== false) return $var;
|
||||
|
||||
if (is_scalar($var))
|
||||
{
|
||||
error_log(__METHOD__."() json_encode($prefix='$var') === false --> setting it to null");
|
||||
$var = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach($var as $name => &$value)
|
||||
{
|
||||
$value = self::fix_content($value, $prefix ? $prefix.'['.$name.']' : $name);
|
||||
}
|
||||
}
|
||||
return $var;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function which can be used to add an event listener callback function to
|
||||
* the "beforeSendData" callback. This callback might be used to add a response
|
||||
* which always has to be added after all other responses.
|
||||
* @param callback Callback function or method which should be called before the response gets sent
|
||||
* @param mixed n Optional parameters which get passed to the callback function.
|
||||
*/
|
||||
public function addBeforeSendDataCallback($proc)
|
||||
{
|
||||
//Get the current instance
|
||||
$inst = self::get();
|
||||
|
||||
//Get all parameters passed to the function and delete the first one
|
||||
$params = func_get_args();
|
||||
array_shift($params);
|
||||
|
||||
$inst->beforeSendDataProcs[] = array(
|
||||
'proc' => $proc,
|
||||
'params' => $params
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated legacy xajax wrapper functions for the new egw_json interface
|
||||
*
|
||||
* @deprecated use Api\Json\Response methods
|
||||
*/
|
||||
class xajaxResponse
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user