Overview

Namespaces

  • Composer
    • Autoload
  • Guzzle
    • Common
      • Exception
    • Http
      • Curl
      • Exception
      • Message
        • Header
      • QueryAggregator
    • Parser
      • Cookie
      • Message
      • UriTemplate
      • Url
    • Plugin
      • Mock
    • Stream
  • Mockery
    • Adapter
      • Phpunit
    • CountValidator
    • Exception
    • Generator
      • StringManipulation
        • Pass
    • Loader
    • Matcher
  • None
  • Omnipay
    • Common
      • Exception
      • Message
    • Dummy
      • Message
    • Fatzebra
      • Message
  • PHP
  • Symfony
    • Component
      • EventDispatcher
        • Debug
        • DependencyInjection
        • Tests
          • Debug
          • DependencyInjection
      • HttpFoundation
        • File
          • Exception
          • MimeType
        • Session
          • Attribute
          • Flash
          • Storage
            • Handler
            • Proxy
        • Tests
          • File
            • MimeType
          • Session
            • Attribute
            • Flash
            • Storage
              • Handler
              • Proxy
      • Yaml
        • Exception
        • Tests

Classes

  • Symfony\Component\Yaml\Tests\A
  • Symfony\Component\Yaml\Tests\B
  • Symfony\Component\Yaml\Tests\DumperTest
  • Symfony\Component\Yaml\Tests\InlineTest
  • Symfony\Component\Yaml\Tests\ParseExceptionTest
  • Symfony\Component\Yaml\Tests\ParserTest
  • Symfony\Component\Yaml\Tests\YamlTest
  • Overview
  • Namespace
  • Function
  • Tree
  1: <?php
  2: 
  3: /*
  4:  * This file is part of the Symfony package.
  5:  *
  6:  * (c) Fabien Potencier <fabien@symfony.com>
  7:  *
  8:  * For the full copyright and license information, please view the LICENSE
  9:  * file that was distributed with this source code.
 10:  */
 11: 
 12: namespace Symfony\Component\HttpFoundation;
 13: 
 14: /**
 15:  * Response represents an HTTP response in JSON format.
 16:  *
 17:  * Note that this class does not force the returned JSON content to be an
 18:  * object. It is however recommended that you do return an object as it
 19:  * protects yourself against XSSI and JSON-JavaScript Hijacking.
 20:  *
 21:  * @see https://www.owasp.org/index.php/OWASP_AJAX_Security_Guidelines#Always_return_JSON_with_an_Object_on_the_outside
 22:  *
 23:  * @author Igor Wiedler <igor@wiedler.ch>
 24:  */
 25: class JsonResponse extends Response
 26: {
 27:     protected $data;
 28:     protected $callback;
 29:     protected $encodingOptions;
 30: 
 31:     /**
 32:      * Constructor.
 33:      *
 34:      * @param mixed $data    The response data
 35:      * @param int   $status  The response status code
 36:      * @param array $headers An array of response headers
 37:      */
 38:     public function __construct($data = null, $status = 200, $headers = array())
 39:     {
 40:         parent::__construct('', $status, $headers);
 41: 
 42:         if (null === $data) {
 43:             $data = new \ArrayObject();
 44:         }
 45: 
 46:         // Encode <, >, ', &, and " for RFC4627-compliant JSON, which may also be embedded into HTML.
 47:         $this->encodingOptions = JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT;
 48: 
 49:         $this->setData($data);
 50:     }
 51: 
 52:     /**
 53:      * {@inheritdoc}
 54:      */
 55:     public static function create($data = null, $status = 200, $headers = array())
 56:     {
 57:         return new static($data, $status, $headers);
 58:     }
 59: 
 60:     /**
 61:      * Sets the JSONP callback.
 62:      *
 63:      * @param string|null $callback The JSONP callback or null to use none
 64:      *
 65:      * @return JsonResponse
 66:      *
 67:      * @throws \InvalidArgumentException When the callback name is not valid
 68:      */
 69:     public function setCallback($callback = null)
 70:     {
 71:         if (null !== $callback) {
 72:             // taken from http://www.geekality.net/2011/08/03/valid-javascript-identifier/
 73:             $pattern = '/^[$_\p{L}][$_\p{L}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*+$/u';
 74:             $parts = explode('.', $callback);
 75:             foreach ($parts as $part) {
 76:                 if (!preg_match($pattern, $part)) {
 77:                     throw new \InvalidArgumentException('The callback name is not valid.');
 78:                 }
 79:             }
 80:         }
 81: 
 82:         $this->callback = $callback;
 83: 
 84:         return $this->update();
 85:     }
 86: 
 87:     /**
 88:      * Sets the data to be sent as JSON.
 89:      *
 90:      * @param mixed $data
 91:      *
 92:      * @return JsonResponse
 93:      *
 94:      * @throws \InvalidArgumentException
 95:      */
 96:     public function setData($data = array())
 97:     {
 98:         $errorHandler = null;
 99:         $errorHandler = set_error_handler(function () use (&$errorHandler) {
100:             if (JSON_ERROR_NONE !== json_last_error()) {
101:                 return;
102:             }
103: 
104:             if ($errorHandler) {
105:                 call_user_func_array($errorHandler, func_get_args());
106:             }
107:         });
108: 
109:         try {
110:             // Clear json_last_error()
111:             json_encode(null);
112: 
113:             $this->data = json_encode($data, $this->encodingOptions);
114: 
115:             restore_error_handler();
116:         } catch (\Exception $exception) {
117:             restore_error_handler();
118: 
119:             throw $exception;
120:         }
121: 
122:         if (JSON_ERROR_NONE !== json_last_error()) {
123:             throw new \InvalidArgumentException($this->transformJsonError());
124:         }
125: 
126:         return $this->update();
127:     }
128: 
129:     /**
130:      * Returns options used while encoding data to JSON.
131:      *
132:      * @return int
133:      */
134:     public function getEncodingOptions()
135:     {
136:         return $this->encodingOptions;
137:     }
138: 
139:     /**
140:      * Sets options used while encoding data to JSON.
141:      *
142:      * @param int $encodingOptions
143:      *
144:      * @return JsonResponse
145:      */
146:     public function setEncodingOptions($encodingOptions)
147:     {
148:         $this->encodingOptions = (int) $encodingOptions;
149: 
150:         return $this->setData(json_decode($this->data));
151:     }
152: 
153:     /**
154:      * Updates the content and headers according to the JSON data and callback.
155:      *
156:      * @return JsonResponse
157:      */
158:     protected function update()
159:     {
160:         if (null !== $this->callback) {
161:             // Not using application/javascript for compatibility reasons with older browsers.
162:             $this->headers->set('Content-Type', 'text/javascript');
163: 
164:             return $this->setContent(sprintf('/**/%s(%s);', $this->callback, $this->data));
165:         }
166: 
167:         // Only set the header when there is none or when it equals 'text/javascript' (from a previous update with callback)
168:         // in order to not overwrite a custom definition.
169:         if (!$this->headers->has('Content-Type') || 'text/javascript' === $this->headers->get('Content-Type')) {
170:             $this->headers->set('Content-Type', 'application/json');
171:         }
172: 
173:         return $this->setContent($this->data);
174:     }
175: 
176:     private function transformJsonError()
177:     {
178:         if (function_exists('json_last_error_msg')) {
179:             return json_last_error_msg();
180:         }
181: 
182:         switch (json_last_error()) {
183:             case JSON_ERROR_DEPTH:
184:                 return 'Maximum stack depth exceeded.';
185: 
186:             case JSON_ERROR_STATE_MISMATCH:
187:                 return 'Underflow or the modes mismatch.';
188: 
189:             case JSON_ERROR_CTRL_CHAR:
190:                 return 'Unexpected control character found.';
191: 
192:             case JSON_ERROR_SYNTAX:
193:                 return 'Syntax error, malformed JSON.';
194: 
195:             case JSON_ERROR_UTF8:
196:                 return 'Malformed UTF-8 characters, possibly incorrectly encoded.';
197: 
198:             default:
199:                 return 'Unknown error.';
200:         }
201:     }
202: }
203: 
Omnipay Fat Zebra / Paystream Gateway Module API Documentation API documentation generated by ApiGen