mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
ENHANCEMENT #3677 Added more rules for escaping reserved characters in XML to their proper entities e.g. ' => '
BUGFIX When exporting data from TableListField to a CSV via TableListField_Item->Fields(), don't convert the values to XML MINOR Added test class ConvertTest with tests for various Convert functions git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@77298 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
5e8b144318
commit
e768d955df
@ -22,35 +22,47 @@
|
|||||||
*/
|
*/
|
||||||
class Convert extends Object {
|
class Convert extends Object {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a value to be suitable for an XML attribute.
|
||||||
|
*
|
||||||
|
* @param array|string $val String to escape, or array of strings
|
||||||
|
* @return array|string
|
||||||
|
*/
|
||||||
static function raw2att($val) {
|
static function raw2att($val) {
|
||||||
if(is_array($val)) {
|
if(is_array($val)) {
|
||||||
foreach($val as $k => $v) $val[$k] = self::raw2att($v);
|
foreach($val as $k => $v) $val[$k] = self::raw2att($v);
|
||||||
return $val;
|
return $val;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return str_replace(array('&','"',"'",'<','>'),array('&','"',''','<','>'),$val);
|
return str_replace(array('&','"',"'",'<','>'), array('&','"',''','<','>'), $val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Convert a value to be suitable for an HTML attribute.
|
||||||
|
*
|
||||||
|
* This is useful for converting human readable values into
|
||||||
|
* a value suitable for an ID or NAME attribute.
|
||||||
|
*
|
||||||
* @see http://www.w3.org/TR/REC-html40/types.html#type-cdata
|
* @see http://www.w3.org/TR/REC-html40/types.html#type-cdata
|
||||||
* @uses raw2att
|
* @uses Convert::raw2att()
|
||||||
|
* @param array|string $val String to escape, or array of strings
|
||||||
|
* @return array|string
|
||||||
*/
|
*/
|
||||||
static function raw2htmlatt($val) {
|
static function raw2htmlatt($val) {
|
||||||
if(is_array($val)) {
|
if(is_array($val)) {
|
||||||
foreach($val as $k => $v) $val[$k] = self::raw2att($v);
|
foreach($val as $k => $v) $val[$k] = self::raw2htmlatt($v);
|
||||||
return $val;
|
return $val;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$val = str_replace(array('&','"',"'",'<','>'),array('&','"',''','<','>'),$val);
|
$val = self::raw2att($val);
|
||||||
$val = preg_replace('/[^a-zA-Z0-9\-_]*/','', $val);
|
$val = preg_replace('/[^a-zA-Z0-9\-_]*/', '', $val);
|
||||||
return $val;
|
return $val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure that text is properly escaped for XML.
|
* Ensure that text is properly escaped for XML.
|
||||||
*
|
*
|
||||||
|
* @see http://www.w3.org/TR/REC-xml/#dt-escape
|
||||||
* @param array|string $val String to escape, or array of strings
|
* @param array|string $val String to escape, or array of strings
|
||||||
* @return array|string
|
* @return array|string
|
||||||
*/
|
*/
|
||||||
@ -59,7 +71,7 @@ class Convert extends Object {
|
|||||||
foreach($val as $k => $v) $val[$k] = self::raw2xml($v);
|
foreach($val as $k => $v) $val[$k] = self::raw2xml($v);
|
||||||
return $val;
|
return $val;
|
||||||
} else {
|
} else {
|
||||||
return str_replace(array('&', '<', '>', "\n"), array('&', '<', '>', '<br />'), $val);
|
return str_replace(array('&','<','>',"\n",'"',"'"), array('&','<','>','<br />','"','''), $val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +91,7 @@ class Convert extends Object {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses the PHP5.2 native json_encode function if available,
|
* Uses the PHP 5.2 native json_encode function if available,
|
||||||
* otherwise falls back to the Services_JSON class.
|
* otherwise falls back to the Services_JSON class.
|
||||||
*
|
*
|
||||||
* @see http://pear.php.net/pepr/pepr-proposal-show.php?id=198
|
* @see http://pear.php.net/pepr/pepr-proposal-show.php?id=198
|
||||||
@ -99,19 +111,17 @@ class Convert extends Object {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static function raw2sql($val) {
|
static function raw2sql($val) {
|
||||||
if(is_array($val)) {
|
if(is_array($val)) {
|
||||||
foreach($val as $k => $v) $val[$k] = self::raw2sql($v);
|
foreach($val as $k => $v) $val[$k] = self::raw2sql($v);
|
||||||
return $val;
|
return $val;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return DB::getConn()->addslashes($val);
|
return DB::getConn()->addslashes($val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert XML to raw text
|
* Convert XML to raw text.
|
||||||
* @uses html2raw()
|
* @uses html2raw()
|
||||||
* @todo Currently &#xxx; entries are stripped; they should be converted
|
* @todo Currently &#xxx; entries are stripped; they should be converted
|
||||||
*/
|
*/
|
||||||
@ -119,18 +129,13 @@ class Convert extends Object {
|
|||||||
if(is_array($val)) {
|
if(is_array($val)) {
|
||||||
foreach($val as $k => $v) $val[$k] = self::xml2raw($v);
|
foreach($val as $k => $v) $val[$k] = self::xml2raw($v);
|
||||||
return $val;
|
return $val;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
// More complex text needs to use html2raw instead
|
||||||
// More complex text needs to use html2raw instaed
|
|
||||||
if(strpos($val,'<') !== false) return self::html2raw($val);
|
if(strpos($val,'<') !== false) return self::html2raw($val);
|
||||||
|
|
||||||
// For simpler stuff, a simple str_replace will do
|
$converted = str_replace(array('&','<','>','"','''), array('&','<','>','"',"'"), $val);
|
||||||
else {
|
$converted = ereg_replace('&#[0-9]+;', '', $converted);
|
||||||
$converted = str_replace(array('&', '<', '>', '''), array('&', '<', '>', "'"), $val);
|
return $converted;
|
||||||
$converted = ereg_replace('&#[0-9]+;', '', $converted);
|
|
||||||
return $converted;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +196,7 @@ class Convert extends Object {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses the PHP5.2 native json_decode function if available,
|
* Uses the PHP 5.2 native json_decode function if available,
|
||||||
* otherwise falls back to the Services_JSON class.
|
* otherwise falls back to the Services_JSON class.
|
||||||
*
|
*
|
||||||
* @see http://pear.php.net/pepr/pepr-proposal-show.php?id=198
|
* @see http://pear.php.net/pepr/pepr-proposal-show.php?id=198
|
||||||
@ -200,13 +205,9 @@ class Convert extends Object {
|
|||||||
* @return mixed JSON safe string
|
* @return mixed JSON safe string
|
||||||
*/
|
*/
|
||||||
static function json2obj($val) {
|
static function json2obj($val) {
|
||||||
//if(function_exists('json_decode')) {
|
require_once(Director::baseFolder() . '/sapphire/thirdparty/json/JSON.php');
|
||||||
// return json_decode($val);
|
$json = new Services_JSON();
|
||||||
//} else {
|
return $json->decode($val);
|
||||||
require_once(Director::baseFolder() . '/sapphire/thirdparty/json/JSON.php');
|
|
||||||
$json = new Services_JSON();
|
|
||||||
return $json->decode($val);
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -264,8 +265,6 @@ class Convert extends Object {
|
|||||||
return '{' . implode( ', ', $result ) . '}';
|
return '{' . implode( ', ', $result ) . '}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a link if the string is a valid URL
|
* Create a link if the string is a valid URL
|
||||||
* @param string The string to linkify
|
* @param string The string to linkify
|
||||||
@ -278,18 +277,6 @@ class Convert extends Object {
|
|||||||
return $string;
|
return $string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a link if the string is a valid URL
|
|
||||||
* @param string The string to linkify
|
|
||||||
* @return A link to the URL if string is a URL
|
|
||||||
*/
|
|
||||||
/*static function mailtoIfMatch($string) {
|
|
||||||
if( preg_match( '/^[a-z+]+\:\/\/[a-zA-Z0-9$-_.+?&=!*\'()%]+$/', $string ) )
|
|
||||||
return "<a href=\"$string\">$string</a>";
|
|
||||||
else
|
|
||||||
return $string;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple conversion of HTML to plaintext.
|
* Simple conversion of HTML to plaintext.
|
||||||
*
|
*
|
||||||
|
@ -957,7 +957,7 @@ JS
|
|||||||
}
|
}
|
||||||
$fieldItem = new TableListField_Item($item, $this);
|
$fieldItem = new TableListField_Item($item, $this);
|
||||||
|
|
||||||
$fields = $fieldItem->Fields();
|
$fields = $fieldItem->Fields(false);
|
||||||
$columnData = array();
|
$columnData = array();
|
||||||
if($fields) foreach($fields as $field) {
|
if($fields) foreach($fields as $field) {
|
||||||
$value = $field->Value;
|
$value = $field->Value;
|
||||||
@ -1241,16 +1241,16 @@ class TableListField_Item extends ViewableData {
|
|||||||
return $this->parent;
|
return $this->parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Fields() {
|
function Fields($xmlSafe = true) {
|
||||||
$list = $this->parent->FieldList();
|
$list = $this->parent->FieldList();
|
||||||
foreach($list as $fieldName => $fieldTitle) {
|
foreach($list as $fieldName => $fieldTitle) {
|
||||||
$value = "";
|
$value = "";
|
||||||
|
|
||||||
// This supports simple FieldName syntax
|
// This supports simple FieldName syntax
|
||||||
if(strpos($fieldName,'.') === false) {
|
if(strpos($fieldName,'.') === false) {
|
||||||
$value = ($this->item->XML_val($fieldName)) ? $this->item->XML_val($fieldName) : $this->item->$fieldName;
|
$value = ($this->item->XML_val($fieldName) && $xmlSafe) ? $this->item->XML_val($fieldName) : $this->item->$fieldName;
|
||||||
// This support the syntax fieldName = Relation.RelatedField
|
} else {
|
||||||
} else {
|
// This supports the syntax fieldName = Relation.RelatedField
|
||||||
$fieldNameParts = explode('.', $fieldName) ;
|
$fieldNameParts = explode('.', $fieldName) ;
|
||||||
$tmpItem = $this->item;
|
$tmpItem = $this->item;
|
||||||
for($j=0;$j<sizeof($fieldNameParts);$j++) {
|
for($j=0;$j<sizeof($fieldNameParts);$j++) {
|
||||||
@ -1268,7 +1268,7 @@ class TableListField_Item extends ViewableData {
|
|||||||
if(array_key_exists($fieldName, $this->parent->fieldCasting)) {
|
if(array_key_exists($fieldName, $this->parent->fieldCasting)) {
|
||||||
$value = $this->parent->getCastedValue($value, $this->parent->fieldCasting[$fieldName]);
|
$value = $this->parent->getCastedValue($value, $this->parent->fieldCasting[$fieldName]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// formatting
|
// formatting
|
||||||
$item = $this->item;
|
$item = $this->item;
|
||||||
if(array_key_exists($fieldName, $this->parent->fieldFormatting)) {
|
if(array_key_exists($fieldName, $this->parent->fieldFormatting)) {
|
||||||
@ -1285,7 +1285,6 @@ class TableListField_Item extends ViewableData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$fields[] = new ArrayData(array(
|
$fields[] = new ArrayData(array(
|
||||||
"Name" => $fieldName,
|
"Name" => $fieldName,
|
||||||
"Title" => $fieldTitle,
|
"Title" => $fieldTitle,
|
||||||
|
53
tests/ConvertTest.php
Normal file
53
tests/ConvertTest.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Test various functions on the {@link Convert} class.
|
||||||
|
* @package sapphire
|
||||||
|
* @subpackage tests
|
||||||
|
*/
|
||||||
|
class ConvertTest extends SapphireTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests {@link Convert::raw2att()}
|
||||||
|
*/
|
||||||
|
function testRaw2Att() {
|
||||||
|
$val1 = '<input type="text">';
|
||||||
|
$this->assertEquals('<input type="text">', Convert::raw2att($val1), 'Special characters are escaped');
|
||||||
|
|
||||||
|
$val2 = 'This is some normal text.';
|
||||||
|
$this->assertEquals('This is some normal text.', Convert::raw2att($val2), 'Normal text is not escaped');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests {@link Convert::raw2htmlatt()}
|
||||||
|
*/
|
||||||
|
function testRaw2HtmlAtt() {
|
||||||
|
$val1 = '<input type="text">';
|
||||||
|
$this->assertEquals('ltinputtypequottextquotgt', Convert::raw2htmlatt($val1), 'Special characters are escaped');
|
||||||
|
|
||||||
|
$val2 = 'This is some normal text.';
|
||||||
|
$this->assertEquals('Thisissomenormaltext', Convert::raw2htmlatt($val2), 'Normal text is not escaped');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests {@link Convert::raw2xml()}
|
||||||
|
*/
|
||||||
|
function testRaw2Xml() {
|
||||||
|
$val1 = '<input type="text">';
|
||||||
|
$this->assertEquals('<input type="text">', Convert::raw2xml($val1), 'Special characters are escaped');
|
||||||
|
|
||||||
|
$val2 = 'This is some normal text.';
|
||||||
|
$this->assertEquals('This is some normal text.', Convert::raw2xml($val2), 'Normal text is not escaped');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests {@link Convert::xml2raw()}
|
||||||
|
*/
|
||||||
|
function testXml2Raw() {
|
||||||
|
$val1 = '<input type="text">';
|
||||||
|
$this->assertEquals('<input type="text">', Convert::xml2raw($val1), 'Special characters are escaped');
|
||||||
|
|
||||||
|
$val2 = 'This is some normal text.';
|
||||||
|
$this->assertEquals('This is some normal text.', Convert::xml2raw($val2), 'Normal text is not escaped');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user