Initial
This commit is contained in:
71
system/Format/Exceptions/FormatException.php
Normal file
71
system/Format/Exceptions/FormatException.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Format\Exceptions;
|
||||
|
||||
use CodeIgniter\Exceptions\DebugTraceableTrait;
|
||||
use CodeIgniter\Exceptions\ExceptionInterface;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* FormatException
|
||||
*/
|
||||
class FormatException extends RuntimeException implements ExceptionInterface
|
||||
{
|
||||
use DebugTraceableTrait;
|
||||
|
||||
/**
|
||||
* Thrown when the instantiated class does not exist.
|
||||
*
|
||||
* @return FormatException
|
||||
*/
|
||||
public static function forInvalidFormatter(string $class)
|
||||
{
|
||||
return new static(lang('Format.invalidFormatter', [$class]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown in JSONFormatter when the json_encode produces
|
||||
* an error code other than JSON_ERROR_NONE and JSON_ERROR_RECURSION.
|
||||
*
|
||||
* @param string $error
|
||||
*
|
||||
* @return FormatException
|
||||
*/
|
||||
public static function forInvalidJSON(?string $error = null)
|
||||
{
|
||||
return new static(lang('Format.invalidJSON', [$error]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown when the supplied MIME type has no
|
||||
* defined Formatter class.
|
||||
*
|
||||
* @return FormatException
|
||||
*/
|
||||
public static function forInvalidMime(string $mime)
|
||||
{
|
||||
return new static(lang('Format.invalidMime', [$mime]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown on XMLFormatter when the `simplexml` extension
|
||||
* is not installed.
|
||||
*
|
||||
* @return FormatException
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public static function forMissingExtension()
|
||||
{
|
||||
return new static(lang('Format.missingExtension'));
|
||||
}
|
||||
}
|
||||
72
system/Format/Format.php
Normal file
72
system/Format/Format.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Format;
|
||||
|
||||
use CodeIgniter\Format\Exceptions\FormatException;
|
||||
use Config\Format as FormatConfig;
|
||||
|
||||
/**
|
||||
* The Format class is a convenient place to create Formatters.
|
||||
*/
|
||||
class Format
|
||||
{
|
||||
/**
|
||||
* Configuration instance
|
||||
*
|
||||
* @var FormatConfig
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct(FormatConfig $config)
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current configuration instance.
|
||||
*
|
||||
* @return FormatConfig
|
||||
*/
|
||||
public function getConfig()
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Factory method to return the appropriate formatter for the given mime type.
|
||||
*
|
||||
* @throws FormatException
|
||||
*/
|
||||
public function getFormatter(string $mime): FormatterInterface
|
||||
{
|
||||
if (! array_key_exists($mime, $this->config->formatters)) {
|
||||
throw FormatException::forInvalidMime($mime);
|
||||
}
|
||||
|
||||
$className = $this->config->formatters[$mime];
|
||||
|
||||
if (! class_exists($className)) {
|
||||
throw FormatException::forInvalidFormatter($className);
|
||||
}
|
||||
|
||||
$class = new $className();
|
||||
|
||||
if (! $class instanceof FormatterInterface) {
|
||||
throw FormatException::forInvalidFormatter($className);
|
||||
}
|
||||
|
||||
return $class;
|
||||
}
|
||||
}
|
||||
27
system/Format/FormatterInterface.php
Normal file
27
system/Format/FormatterInterface.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Format;
|
||||
|
||||
/**
|
||||
* Formatter interface
|
||||
*/
|
||||
interface FormatterInterface
|
||||
{
|
||||
/**
|
||||
* Takes the given data and formats it.
|
||||
*
|
||||
* @param array|string $data
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function format($data);
|
||||
}
|
||||
46
system/Format/JSONFormatter.php
Normal file
46
system/Format/JSONFormatter.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Format;
|
||||
|
||||
use CodeIgniter\Format\Exceptions\FormatException;
|
||||
use Config\Format;
|
||||
|
||||
/**
|
||||
* JSON data formatter
|
||||
*/
|
||||
class JSONFormatter implements FormatterInterface
|
||||
{
|
||||
/**
|
||||
* Takes the given data and formats it.
|
||||
*
|
||||
* @param mixed $data
|
||||
*
|
||||
* @return bool|string (JSON string | false)
|
||||
*/
|
||||
public function format($data)
|
||||
{
|
||||
$config = new Format();
|
||||
|
||||
$options = $config->formatterOptions['application/json'] ?? JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
|
||||
$options = $options | JSON_PARTIAL_OUTPUT_ON_ERROR;
|
||||
|
||||
$options = ENVIRONMENT === 'production' ? $options : $options | JSON_PRETTY_PRINT;
|
||||
|
||||
$result = json_encode($data, $options, 512);
|
||||
|
||||
if (! in_array(json_last_error(), [JSON_ERROR_NONE, JSON_ERROR_RECURSION], true)) {
|
||||
throw FormatException::forInvalidJSON(json_last_error_msg());
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
99
system/Format/XMLFormatter.php
Normal file
99
system/Format/XMLFormatter.php
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Format;
|
||||
|
||||
use CodeIgniter\Format\Exceptions\FormatException;
|
||||
use Config\Format;
|
||||
use SimpleXMLElement;
|
||||
|
||||
/**
|
||||
* XML data formatter
|
||||
*/
|
||||
class XMLFormatter implements FormatterInterface
|
||||
{
|
||||
/**
|
||||
* Takes the given data and formats it.
|
||||
*
|
||||
* @param mixed $data
|
||||
*
|
||||
* @return bool|string (XML string | false)
|
||||
*/
|
||||
public function format($data)
|
||||
{
|
||||
$config = new Format();
|
||||
|
||||
// SimpleXML is installed but default
|
||||
// but best to check, and then provide a fallback.
|
||||
if (! extension_loaded('simplexml')) {
|
||||
// never thrown in travis-ci
|
||||
// @codeCoverageIgnoreStart
|
||||
throw FormatException::forMissingExtension();
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
$options = $config->formatterOptions['application/xml'] ?? 0;
|
||||
$output = new SimpleXMLElement('<?xml version="1.0"?><response></response>', $options);
|
||||
|
||||
$this->arrayToXML((array) $data, $output);
|
||||
|
||||
return $output->asXML();
|
||||
}
|
||||
|
||||
/**
|
||||
* A recursive method to convert an array into a valid XML string.
|
||||
*
|
||||
* Written by CodexWorld. Received permission by email on Nov 24, 2016 to use this code.
|
||||
*
|
||||
* @see http://www.codexworld.com/convert-array-to-xml-in-php/
|
||||
*
|
||||
* @param SimpleXMLElement $output
|
||||
*/
|
||||
protected function arrayToXML(array $data, &$output)
|
||||
{
|
||||
foreach ($data as $key => $value) {
|
||||
$key = $this->normalizeXMLTag($key);
|
||||
|
||||
if (is_array($value)) {
|
||||
$subnode = $output->addChild("{$key}");
|
||||
$this->arrayToXML($value, $subnode);
|
||||
} else {
|
||||
$output->addChild("{$key}", htmlspecialchars("{$value}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes tags into the allowed by W3C.
|
||||
* Regex adopted from this StackOverflow answer.
|
||||
*
|
||||
* @param int|string $key
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @see https://stackoverflow.com/questions/60001029/invalid-characters-in-xml-tag-name
|
||||
*/
|
||||
protected function normalizeXMLTag($key)
|
||||
{
|
||||
$startChar = 'A-Z_a-z' .
|
||||
'\\x{C0}-\\x{D6}\\x{D8}-\\x{F6}\\x{F8}-\\x{2FF}\\x{370}-\\x{37D}' .
|
||||
'\\x{37F}-\\x{1FFF}\\x{200C}-\\x{200D}\\x{2070}-\\x{218F}' .
|
||||
'\\x{2C00}-\\x{2FEF}\\x{3001}-\\x{D7FF}\\x{F900}-\\x{FDCF}' .
|
||||
'\\x{FDF0}-\\x{FFFD}\\x{10000}-\\x{EFFFF}';
|
||||
$validName = $startChar . '\\.\\d\\x{B7}\\x{300}-\\x{36F}\\x{203F}-\\x{2040}';
|
||||
|
||||
$key = trim($key);
|
||||
$key = preg_replace("/[^{$validName}-]+/u", '', $key);
|
||||
$key = preg_replace("/^[^{$startChar}]+/u", 'item$0', $key);
|
||||
|
||||
return preg_replace('/^(xml).*/iu', 'item$0', $key); // XML is a reserved starting word
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user