-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added new
Grav\Framework\File\Formatter
classes for encoding/decodi…
…ng YAML, MarkDown, JSON, INI and PHP serialized formats
- Loading branch information
Showing
7 changed files
with
369 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 28 additions & 0 deletions
28
system/src/Grav/Framework/File/Formatter/FormatterInterface.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?php | ||
/** | ||
* @package Grav\Framework\Formatter | ||
* | ||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved. | ||
* @license MIT License; see LICENSE file for details. | ||
*/ | ||
|
||
namespace Grav\Framework\Formatter; | ||
|
||
interface FormatterInterface | ||
{ | ||
/** | ||
* Encode data into a string. | ||
* | ||
* @param array $data | ||
* @return string | ||
*/ | ||
public function encode($data); | ||
|
||
/** | ||
* Decode a string into data. | ||
* | ||
* @param string $data | ||
* @return array | ||
*/ | ||
public function decode($data); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<?php | ||
/** | ||
* @package Grav\Framework\Formatter | ||
* | ||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved. | ||
* @license MIT License; see LICENSE file for details. | ||
*/ | ||
|
||
namespace Grav\Framework\Formatter; | ||
|
||
/** | ||
* Class IniFormatter | ||
* @package Grav\Framework\Formatter | ||
*/ | ||
class IniFormatter implements FormatterInterface | ||
{ | ||
public function getFileExtension() | ||
{ | ||
return 'ini'; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function encode($data) | ||
{ | ||
$string = ''; | ||
foreach ($data as $key => $value) { | ||
$string .= $key . '="' . preg_replace( | ||
['/"/', '/\\\/', "/\t/", "/\n/", "/\r/"], | ||
['\"', '\\\\', '\t', '\n', '\r'], | ||
$value | ||
) . "\"\n"; | ||
} | ||
return $string; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function decode($data) | ||
{ | ||
$decoded = @parse_ini_string($data); | ||
|
||
if ($decoded === false) { | ||
throw new \RuntimeException("Decoding INI format failed'"); | ||
} | ||
|
||
return $decoded; | ||
} | ||
} |
51 changes: 51 additions & 0 deletions
51
system/src/Grav/Framework/File/Formatter/JsonFormatter.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<?php | ||
/** | ||
* @package Grav\Framework\Formatter | ||
* | ||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved. | ||
* @license MIT License; see LICENSE file for details. | ||
*/ | ||
|
||
namespace Grav\Framework\Formatter; | ||
|
||
/** | ||
* Class JsonFormatter | ||
* @package Grav\Framework\Formatter | ||
*/ | ||
class JsonFormatter implements FormatterInterface | ||
{ | ||
/** @var array */ | ||
private $config; | ||
|
||
public function __construct(array $config = []) | ||
{ | ||
$this->config = $config + [ | ||
'encode_options' => 0, | ||
'decode_assoc' => true | ||
]; | ||
} | ||
|
||
public function getFileExtension() | ||
{ | ||
return 'json'; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function encode($data) | ||
{ | ||
$encoded = json_encode($data, $this->config['encode_options']); | ||
if ($encoded === false) { | ||
throw new \RuntimeException(''); | ||
} | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function decode($data) | ||
{ | ||
return json_decode($data, $this->config['decode_assoc']); | ||
} | ||
} |
98 changes: 98 additions & 0 deletions
98
system/src/Grav/Framework/File/Formatter/MarkdownFormatter.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
<?php | ||
/** | ||
* @package Grav\Framework\Formatter | ||
* | ||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved. | ||
* @license MIT License; see LICENSE file for details. | ||
*/ | ||
|
||
namespace Grav\Framework\Formatter; | ||
|
||
/** | ||
* Class MarkdownFormatter | ||
* @package Grav\Framework\Formatter | ||
*/ | ||
class MarkdownFormatter implements FormatterInterface | ||
{ | ||
/** @var array */ | ||
private $config; | ||
/** @var FormatterInterface */ | ||
private $headerFormatter; | ||
|
||
public function __construct(array $config = [], FormatterInterface $headerFormatter = null) | ||
{ | ||
$this->config = $config + [ | ||
'header' => 'header', | ||
'body' => 'markdown', | ||
'raw' => 'frontmatter', | ||
'formatter' => ['inline' => 20] | ||
]; | ||
|
||
$this->headerFormatter = $headerFormatter ?: new YamlFormatter($this->config['formatter']); | ||
} | ||
|
||
public function getFileExtension() | ||
{ | ||
return 'md'; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function encode($data) | ||
{ | ||
$headerVar = $this->config['header']; | ||
$bodyVar = $this->config['body']; | ||
|
||
$header = isset($data[$headerVar]) ? (array) $data[$headerVar] : []; | ||
$body = isset($data[$bodyVar]) ? (string) $data[$bodyVar] : ''; | ||
|
||
// Create Markdown file with YAML header. | ||
$encoded = ''; | ||
if ($header) { | ||
$encoded = "---\n" . trim($this->headerFormatter->encode($data['header'])) . "\n---\n\n"; | ||
} | ||
$encoded .= $body; | ||
|
||
// Normalize line endings to Unix style. | ||
$encoded = preg_replace("/(\r\n|\r)/", "\n", $encoded); | ||
|
||
return $encoded; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function decode($data) | ||
{ | ||
$headerVar = $this->config['header']; | ||
$bodyVar = $this->config['body']; | ||
$rawVar = $this->config['raw']; | ||
|
||
$content = [ | ||
$headerVar => [], | ||
$bodyVar => '' | ||
]; | ||
|
||
$headerRegex = "/^---\n(.+?)\n---\n{0,}(.*)$/uis"; | ||
|
||
// Normalize line endings to Unix style. | ||
$data = preg_replace("/(\r\n|\r)/", "\n", $data); | ||
|
||
// Parse header. | ||
preg_match($headerRegex, ltrim($data), $matches); | ||
if(empty($matches)) { | ||
$content[$bodyVar] = $data; | ||
} else { | ||
// Normalize frontmatter. | ||
$frontmatter = preg_replace("/\n\t/", "\n ", $matches[1]); | ||
if ($rawVar) { | ||
$content[$rawVar] = $frontmatter; | ||
} | ||
$content[$headerVar] = $this->headerFormatter->decode($frontmatter); | ||
$content[$bodyVar] = $matches[2]; | ||
} | ||
|
||
return $content; | ||
} | ||
} |
55 changes: 55 additions & 0 deletions
55
system/src/Grav/Framework/File/Formatter/SerializeFormatter.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
<?php | ||
/** | ||
* @package Grav\Framework\Formatter | ||
* | ||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved. | ||
* @license MIT License; see LICENSE file for details. | ||
*/ | ||
|
||
namespace Grav\Framework\Formatter; | ||
|
||
class SerializeFormatter implements FormatterInterface | ||
{ | ||
public function getFileExtension() | ||
{ | ||
return 'raw'; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function encode($data) | ||
{ | ||
return serialize($this->preserveLines($data, ["\n", "\r"], ['\\n', '\\r'])); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function decode($data) | ||
{ | ||
return $this->preserveLines(unserialize($data), ['\\n', '\\r'], ["\n", "\r"]); | ||
} | ||
|
||
/** | ||
* Preserve new lines, recursive function. | ||
* | ||
* @param mixed $data | ||
* @param array $search | ||
* @param array $replace | ||
* @return mixed | ||
*/ | ||
protected function preserveLines($data, $search, $replace) | ||
{ | ||
if (is_string($data)) { | ||
$data = str_replace($search, $replace, $data); | ||
} elseif (is_array($data)) { | ||
foreach ($data as &$value) { | ||
$value = $this->preserveLines($value, $search, $replace); | ||
} | ||
unset($value); | ||
} | ||
|
||
return $data; | ||
} | ||
} |
85 changes: 85 additions & 0 deletions
85
system/src/Grav/Framework/File/Formatter/YamlFormatter.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
<?php | ||
/** | ||
* @package Grav\Framework\Formatter | ||
* | ||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved. | ||
* @license MIT License; see LICENSE file for details. | ||
*/ | ||
|
||
namespace Grav\Framework\Formatter; | ||
|
||
use Symfony\Component\Yaml\Exception\DumpException; | ||
use Symfony\Component\Yaml\Exception\ParseException; | ||
use Symfony\Component\Yaml\Yaml as YamlParser; | ||
use RocketTheme\Toolbox\Compat\Yaml\Yaml as FallbackYamlParser; | ||
|
||
/** | ||
* Class YamlFormatter | ||
* @package Grav\Framework\Formatter | ||
*/ | ||
class YamlFormatter implements FormatterInterface | ||
{ | ||
/** @var array */ | ||
private $config; | ||
|
||
public function __construct(array $config = []) | ||
{ | ||
$this->config = $config + [ | ||
'inline' => 5, | ||
'indent' => 2, | ||
'native' => true, | ||
'compat' => true | ||
]; | ||
} | ||
|
||
public function getFileExtension() | ||
{ | ||
return 'yaml'; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function encode($data) | ||
{ | ||
try { | ||
return (string) YamlParser::dump( | ||
$data, | ||
$this->config['inline'], | ||
$this->config['indent'], | ||
YamlParser::DUMP_EXCEPTION_ON_INVALID_TYPE | ||
); | ||
} catch (DumpException $e) { | ||
throw new \RuntimeException($e->getMessage(), 500, $e); | ||
} | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function decode($data) | ||
{ | ||
// Try native PECL YAML PHP extension first if available. | ||
if ($this->config['native'] && function_exists('yaml_parse')) { | ||
// Safely decode YAML. | ||
$saved = @ini_get('yaml.decode_php'); | ||
@ini_set('yaml.decode_php', 0); | ||
$decoded = @yaml_parse($data); | ||
@ini_set('yaml.decode_php', $saved); | ||
|
||
if ($decoded !== false) { | ||
return (array) $decoded; | ||
} | ||
} | ||
|
||
try { | ||
return (array) YamlParser::parse($data); | ||
} catch (ParseException $e) { | ||
if ($this->config['compat']) { | ||
return (array) FallbackYamlParser::parse($data); | ||
} | ||
|
||
throw new \RuntimeException($e->getMessage(), 500, $e); | ||
} | ||
} | ||
} |