Elgg  Version 3.0
Service.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Elgg\Ajax;
4 
12 
19 class Service {
20 
24  private $hooks;
25 
29  private $msgs;
30 
34  private $request;
35 
39  private $amd_config;
40 
44  private $response_sent = false;
45 
49  private $allowed_views = [];
50 
59  public function __construct(PluginHooksService $hooks, SystemMessagesService $msgs, Request $request, Config $amdConfig) {
60  $this->hooks = $hooks;
61  $this->msgs = $msgs;
62  $this->request = $request;
63  $this->amd_config = $amdConfig;
64 
65  $message_filter = [$this, 'prepareResponse'];
66  $this->hooks->registerHandler(AjaxResponse::RESPONSE_HOOK, 'all', $message_filter, 999);
67  }
68 
74  public function isAjax2Request() {
75  $version = $this->request->headers->get('X-Elgg-Ajax-API');
76  return ($version === '2');
77  }
78 
88  public function isReady() {
89  return !$this->response_sent && $this->isAjax2Request();
90  }
91 
98  public function decodeJson($string) {
99  if (!is_string($string)) {
100  return $string;
101  }
102  $object = json_decode($string);
103  return ($object === null) ? $string : $object;
104  }
105 
114  public function respondFromOutput($output, $hook_type = '', $try_decode = true) {
115  if ($try_decode) {
116  $output = $this->decodeJson($output);
117  }
118 
119  $api_response = new Response();
120  if (is_object($output) && isset($output->value)) {
121  $api_response->setData($output);
122  } else if (is_array($output) && isset($output['value'])) {
123  $api_response->setData((object) $output);
124  } else {
125  $api_response->setData((object) ['value' => $output]);
126  }
127  $api_response = $this->filterApiResponse($api_response, $hook_type);
128  $response = $this->buildHttpResponse($api_response);
129 
130  $this->response_sent = true;
131  return _elgg_services()->responseFactory->send($response);
132  }
133 
141  public function respondFromApiResponse(AjaxResponse $api_response, $hook_type = '') {
142  $api_response = $this->filterApiResponse($api_response, $hook_type);
143  $response = $this->buildHttpResponse($api_response);
144 
145  $this->response_sent = true;
146  return _elgg_services()->responseFactory->send($response);
147  }
148 
156  public function respondWithError($msg = '', $status = 400) {
157  $response = new JsonResponse(['error' => $msg], $status);
158 
159  // clear already set system messages as we respond directly with an error as message body
160  $this->msgs->dumpRegister();
161 
162  $this->response_sent = true;
163  return _elgg_services()->responseFactory->send($response);
164  }
165 
174  private function filterApiResponse(AjaxResponse $api_response, $hook_type = '') {
175  $api_response->setTtl($this->request->getParam('elgg_response_ttl', 0, false));
176 
177  if ($hook_type) {
179  $api_response = $this->hooks->trigger($hook, $hook_type, null, $api_response);
180  if (!$api_response instanceof AjaxResponse) {
181  throw new RuntimeException("The value returned by hook [$hook, $hook_type] was not an ApiResponse");
182  }
183  }
184 
185  return $api_response;
186  }
187 
197  private function buildHttpResponse(AjaxResponse $api_response, $allow_removing_headers = null) {
198  if ($api_response->isCancelled()) {
199  return new JsonResponse(['error' => "The response was cancelled"], 400);
200  }
201 
202  $response = _elgg_services()->responseFactory->prepareJsonResponse($api_response->getData());
203 
204  $ttl = $api_response->getTtl();
205  if ($ttl > 0) {
206  // Required to remove headers set by PHP session
207  if ($allow_removing_headers) {
208  header_remove('Expires');
209  header_remove('Pragma');
210  header_remove('Cache-Control');
211  }
212 
213  // JsonRequest sets a default Cache-Control header we don't want
214  $response->headers->remove('Cache-Control');
215 
216  $response->setClientTtl($ttl);
217 
218  // if we don't set Expires, Apache will add a far-off max-age and Expires for us.
219  $response->headers->set('Expires', gmdate('D, d M Y H:i:s \G\M\T', time() + $ttl));
220  }
221 
222  return $response;
223  }
224 
236  public function prepareResponse($hook, $type, $response, $params) {
237  if (!$response instanceof AjaxResponse) {
238  return;
239  }
240 
241  if ($this->request->getParam('elgg_fetch_messages', true)) {
242  $response->getData()->_elgg_msgs = (object) $this->msgs->dumpRegister();
243  }
244 
245  if ($this->request->getParam('elgg_fetch_deps', true)) {
246  $response->getData()->_elgg_deps = (array) $this->amd_config->getDependencies();
247  }
248 
249  return $response;
250  }
251 
258  public function registerView($view) {
259  $this->allowed_views[$view] = true;
260  }
261 
268  public function unregisterView($view) {
269  unset($this->allowed_views[$view]);
270  }
271 
276  public function getViews() {
277  return array_keys($this->allowed_views);
278  }
279 
280 }
isCancelled()
Has the response been cancelled?
if(!$item instanceof ElggRiverItem) $object
Definition: responses.php:23
Elgg HTTP request.
Definition: Request.php:17
$params
Saves global plugin settings.
Definition: save.php:13
unregisterView($view)
Unregister a view for ajax calls.
Definition: Service.php:268
setTtl($ttl=0)
Set the max-age for client caching.
isAjax2Request()
Did the request come from the elgg/Ajax module?
Definition: Service.php:74
$type
Definition: delete.php:21
catch(LoginException $e) if($request->isXhr()) $output
Definition: login.php:56
Models the Ajax API service.
Definition: Service.php:19
registerView($view)
Register a view to be available for ajax calls.
Definition: Service.php:258
if(!$owner||!$owner->canEdit()) if(!$owner->hasIcon('master')) if(!$owner->saveIconFromElggFile($owner->getIcon('master'), 'icon', $coords)) $view
Definition: crop.php:30
decodeJson($string)
Attempt to JSON decode the given string.
Definition: Service.php:98
JSON endpoint response.
Definition: AjaxResponse.php:9
respondFromOutput($output, $hook_type= '', $try_decode=true)
Send a JSON HTTP response with the given output.
Definition: Service.php:114
$amdConfig
respondFromApiResponse(AjaxResponse $api_response, $hook_type= '')
Send a JSON HTTP response based on the given API response.
Definition: Service.php:141
prepareResponse($hook, $type, $response, $params)
Prepare the response with additional metadata, like system messages and required AMD modules...
Definition: Service.php:236
getData()
Get the response data, which will be a stdClass object with property "value".
System messages service.
isReady()
Is the service ready to respond to the request?
Definition: Service.php:88
__construct(PluginHooksService $hooks, SystemMessagesService $msgs, Request $request, Config $amdConfig)
Constructor.
Definition: Service.php:59
_elgg_services()
Get the global service provider.
Definition: elgglib.php:1292
JSON endpoint response.
Definition: Response.php:10
$version
Definition: version.php:14
getTtl()
Get the max-age for client caching.
getViews()
Returns an array of views allowed for ajax calls.
Definition: Service.php:276
respondWithError($msg= '', $status=400)
Send a JSON HTTP 400 response.
Definition: Service.php:156