Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 40
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
AjaxResponseTrait
0.00% covered (danger)
0.00%
0 / 40
0.00% covered (danger)
0.00%
0 / 4
306
0.00% covered (danger)
0.00%
0 / 1
 formatContent
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
90
 getAjaxResponse
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
6
 getExceptionResponse
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 callAjaxMethod
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2
3/**
4 * Trait to allow AJAX response generation.
5 *
6 * PHP version 8
7 *
8 * Copyright (C) Villanova University 2018.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2,
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22 *
23 * @category VuFind
24 * @package  Controller
25 * @author   Chris Hallberg <challber@villanova.edu>
26 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
27 * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
28 */
29
30namespace VuFind\Controller;
31
32use VuFind\AjaxHandler\AjaxHandlerInterface as Ajax;
33use VuFind\AjaxHandler\PluginManager;
34
35/**
36 * Trait to allow AJAX response generation.
37 *
38 * Dependencies:
39 * - \VuFind\I18n\Translator\TranslatorAwareTrait
40 * - Injection of $this->ajaxManager (for some functionality)
41 *
42 * @category VuFind
43 * @package  Controller
44 * @author   Chris Hallberg <challber@villanova.edu>
45 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
46 * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
47 */
48trait AjaxResponseTrait
49{
50    /**
51     * AJAX Handler plugin manager
52     *
53     * @var PluginManager
54     */
55    protected $ajaxManager = null;
56
57    /**
58     * Format the content of the AJAX response based on the response type.
59     *
60     * @param string $type     Content-type of output
61     * @param mixed  $data     The response data
62     * @param int    $httpCode A custom HTTP Status Code
63     *
64     * @return string
65     * @throws \Exception
66     */
67    protected function formatContent($type, $data, $httpCode)
68    {
69        switch ($type) {
70            case 'application/javascript':
71            case 'application/json':
72                return json_encode(compact('data'));
73            case 'text/plain':
74                return ((null !== $httpCode && $httpCode >= 400) ? 'ERROR ' : 'OK ')
75                    . $data;
76            case 'text/html':
77                return $data ?: '';
78            default:
79                throw new \Exception("Unsupported content type: $type");
80        }
81    }
82
83    /**
84     * Send output data and exit.
85     *
86     * @param string $type     Content type to output
87     * @param mixed  $data     The response data
88     * @param int    $httpCode A custom HTTP Status Code
89     *
90     * @return \Laminas\Http\Response
91     * @throws \Exception
92     */
93    protected function getAjaxResponse($type, $data, $httpCode = null)
94    {
95        $response = $this->getResponse();
96        $headers = $response->getHeaders();
97        $headers->addHeaderLine('Content-type', $type);
98        $headers->addHeaderLine('Cache-Control', 'no-cache, must-revalidate');
99        $headers->addHeaderLine('Expires', 'Mon, 26 Jul 1997 05:00:00 GMT');
100        if ($httpCode !== null) {
101            $response->setStatusCode($httpCode);
102        }
103        $response->setContent($this->formatContent($type, $data, $httpCode));
104        return $response;
105    }
106
107    /**
108     * Turn an exception into error response.
109     *
110     * @param string     $type Content type to output
111     * @param \Exception $e    Exception to output.
112     *
113     * @return \Laminas\Http\Response
114     */
115    protected function getExceptionResponse($type, \Exception $e)
116    {
117        $debugMsg = ('development' == APPLICATION_ENV)
118            ? ': ' . $e->getMessage() : '';
119        return $this->getAjaxResponse(
120            $type,
121            $this->translate('An error has occurred') . $debugMsg,
122            Ajax::STATUS_HTTP_ERROR
123        );
124    }
125
126    /**
127     * Call an AJAX method and turn the result into a response.
128     *
129     * @param string $method AJAX method to call
130     * @param string $type   Content type to output
131     *
132     * @return \Laminas\Http\Response
133     */
134    protected function callAjaxMethod($method, $type = 'application/json')
135    {
136        // Check the AJAX handler plugin manager for the method.
137        if (!$this->ajaxManager) {
138            throw new \Exception('AJAX Handler Plugin Manager missing.');
139        }
140        if ($this->ajaxManager->has($method)) {
141            try {
142                $handler = $this->ajaxManager->get($method);
143                return $this->getAjaxResponse(
144                    $type,
145                    ...$handler->handleRequest($this->params())
146                );
147            } catch (\Exception $e) {
148                return $this->getExceptionResponse($type, $e);
149            }
150        }
151
152        // If we got this far, we can't handle the requested method:
153        return $this->getAjaxResponse(
154            $type,
155            $this->translate('Invalid Method'),
156            Ajax::STATUS_HTTP_BAD_REQUEST
157        );
158    }
159}