mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2025-01-31 17:16:18 +00:00
Refactoring out string escaping and object conversion into base class.
This commit is contained in:
parent
93a2e8fcad
commit
2362f283f2
2 changed files with 183 additions and 91 deletions
|
@ -350,23 +350,6 @@ class JsHelper extends AppHelper {
|
||||||
function redirect_($url = null) {
|
function redirect_($url = null) {
|
||||||
return 'window.location = "' . Router::url($url) . '";';
|
return 'window.location = "' . Router::url($url) . '";';
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Escape a string to be JavaScript friendly.
|
|
||||||
*
|
|
||||||
* List of escaped ellements:
|
|
||||||
* + "\r\n" => '\n'
|
|
||||||
* + "\r" => '\n'
|
|
||||||
* + "\n" => '\n'
|
|
||||||
* + '"' => '\"'
|
|
||||||
* + "'" => "\\'"
|
|
||||||
*
|
|
||||||
* @param string $script String that needs to get escaped.
|
|
||||||
* @return string Escaped string.
|
|
||||||
*/
|
|
||||||
function escape($string) {
|
|
||||||
$escape = array("\r\n" => '\n', "\r" => '\n', "\n" => '\n', '"' => '\"', "'" => "\\'");
|
|
||||||
return str_replace(array_keys($escape), array_values($escape), $string);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* function get__($name) {
|
/* function get__($name) {
|
||||||
return $this->__object($name, 'id');
|
return $this->__object($name, 'id');
|
||||||
|
@ -387,76 +370,157 @@ class JsHelper extends AppHelper {
|
||||||
}
|
}
|
||||||
return $this->__objects[$name];
|
return $this->__objects[$name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JsEngineBaseClass
|
||||||
|
*
|
||||||
|
* Abstract Base Class for All JsEngines to extend. Provides generic methods.
|
||||||
|
*
|
||||||
|
* @package cake.view.helpers
|
||||||
|
*/
|
||||||
|
class JsBaseEngineHelper extends AppHelper {
|
||||||
|
/**
|
||||||
|
* Determines whether native JSON extension is used for encoding. Set by object constructor.
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
var $useNative = false;
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function __construct() {
|
||||||
|
$this->useNative = function_exists('json_encode');
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Generates a JavaScript object in JavaScript Object Notation (JSON)
|
* Generates a JavaScript object in JavaScript Object Notation (JSON)
|
||||||
* from an array
|
* from an array
|
||||||
*
|
*
|
||||||
* @param array $data Data to be converted
|
* Options:
|
||||||
* @param boolean $block Wraps return value in a <script/> block if true
|
* - prefix - String prepended to the returned data.
|
||||||
* @param string $prefix Prepends the string to the returned data
|
* - postfix - String appended to the returned data.
|
||||||
* @param string $postfix Appends the string to the returned data
|
* - stringKeys - A list of array keys to be treated as a string
|
||||||
* @param array $stringKeys A list of array keys to be treated as a string
|
* - quoteKeys - If false treats $options['stringKeys'] as a list of keys **not** to be quoted.
|
||||||
* @param boolean $quoteKeys If false, treats $stringKey as a list of keys *not* to be quoted
|
* - q - Type of quote to use.
|
||||||
* @param string $q The type of quote to use
|
*
|
||||||
|
* @param array $data Data to be converted.
|
||||||
|
* @param array $options Set of options, see above.
|
||||||
* @return string A JSON code block
|
* @return string A JSON code block
|
||||||
*/
|
*/
|
||||||
function object($data = array(), $block = false, $prefix = '', $postfix = '', $stringKeys = array(), $quoteKeys = true, $q = "\"") {
|
function object($data = array(), $options = array()) {
|
||||||
|
$defaultOptions = array(
|
||||||
|
'block' => false, 'prefix' => '', 'postfix' => '',
|
||||||
|
'stringKeys' => array(), 'quoteKeys' => true, 'q' => '"'
|
||||||
|
);
|
||||||
|
$options = array_merge($defaultOptions, $options);
|
||||||
|
|
||||||
if (is_object($data)) {
|
if (is_object($data)) {
|
||||||
$data = get_object_vars($data);
|
$data = get_object_vars($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
$out = array();
|
$out = $keys = array();
|
||||||
$key = array();
|
$numeric = true;
|
||||||
|
|
||||||
|
if ($this->useNative) {
|
||||||
|
$rt = json_encode($data);
|
||||||
|
} else {
|
||||||
if (is_array($data)) {
|
if (is_array($data)) {
|
||||||
$keys = array_keys($data);
|
$keys = array_keys($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
$numeric = true;
|
|
||||||
|
|
||||||
if (!empty($keys)) {
|
if (!empty($keys)) {
|
||||||
foreach ($keys as $key) {
|
$numeric = (array_values($keys) === array_keys(array_values($keys)));
|
||||||
if (!is_numeric($key)) {
|
|
||||||
$numeric = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($data as $key => $val) {
|
foreach ($data as $key => $val) {
|
||||||
if (is_array($val) || is_object($val)) {
|
if (is_array($val) || is_object($val)) {
|
||||||
$val = $this->object($val, false, '', '', $stringKeys, $quoteKeys, $q);
|
$val = $this->object($val, array_merge($options, array('block' => false)));
|
||||||
} else {
|
} else {
|
||||||
if ((!count($stringKeys) && !is_numeric($val) && !is_bool($val)) || ($quoteKeys && in_array($key, $stringKeys)) || (!$quoteKeys && !in_array($key, $stringKeys)) && $val !== null) {
|
$quoteStrings = (
|
||||||
$val = $q . $this->escapeString($val) . $q;
|
!count($options['stringKeys']) ||
|
||||||
|
($options['quoteKeys'] && in_array($key, $options['stringKeys'], true)) ||
|
||||||
|
(!$options['quoteKeys'] && !in_array($key, $options['stringKeys'], true))
|
||||||
|
);
|
||||||
|
$val = $this->value($val, $quoteStrings);
|
||||||
}
|
}
|
||||||
if ($val == null) {
|
|
||||||
$val = 'null';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$numeric) {
|
if (!$numeric) {
|
||||||
$val = $q . $key . $q . ':' . $val;
|
$val = $options['q'] . $this->value($key, false) . $options['q'] . ':' . $val;
|
||||||
}
|
}
|
||||||
|
|
||||||
$out[] = $val;
|
$out[] = $val;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$numeric) {
|
if (!$numeric) {
|
||||||
$rt = '{' . join(', ', $out) . '}';
|
$rt = '{' . join(',', $out) . '}';
|
||||||
} else {
|
} else {
|
||||||
$rt = '[' . join(', ', $out) . ']';
|
$rt = '[' . join(',', $out) . ']';
|
||||||
}
|
}
|
||||||
$rt = $prefix . $rt . $postfix;
|
|
||||||
|
|
||||||
if ($block) {
|
|
||||||
$rt = $this->codeBlock($rt);
|
|
||||||
}
|
}
|
||||||
|
$rt = $options['prefix'] . $rt . $options['postfix'];
|
||||||
|
|
||||||
|
if ($options['block']) {
|
||||||
|
$rt = $this->codeBlock($rt, array_diff_key($options, $defaultOptions));
|
||||||
|
}
|
||||||
return $rt;
|
return $rt;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Converts a PHP-native variable of any type to a JSON-equivalent representation
|
||||||
|
*
|
||||||
|
* @param mixed $val A PHP variable to be converted to JSON
|
||||||
|
* @param boolean $quoteStrings If false, leaves string values unquoted
|
||||||
|
* @return string a JavaScript-safe/JSON representation of $val
|
||||||
|
*/
|
||||||
|
function value($val, $quoteStrings = true) {
|
||||||
|
switch (true) {
|
||||||
|
case (is_array($val) || is_object($val)):
|
||||||
|
$val = $this->object($val);
|
||||||
|
break;
|
||||||
|
case ($val === null):
|
||||||
|
$val = 'null';
|
||||||
|
break;
|
||||||
|
case (is_bool($val)):
|
||||||
|
$val = ($val === true) ? 'true' : 'false';
|
||||||
|
break;
|
||||||
|
case (is_int($val)):
|
||||||
|
$val = $val;
|
||||||
|
break;
|
||||||
|
case (is_float($val)):
|
||||||
|
$val = sprintf("%.11f", $val);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$val = $this->escape($val);
|
||||||
|
if ($quoteStrings) {
|
||||||
|
$val = '"' . $val . '"';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return $val;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Escape a string to be JavaScript friendly.
|
||||||
|
*
|
||||||
|
* List of escaped ellements:
|
||||||
|
* + "\r\n" => '\n'
|
||||||
|
* + "\r" => '\n'
|
||||||
|
* + "\n" => '\n'
|
||||||
|
* + '"' => '\"'
|
||||||
|
* + "'" => "\\'"
|
||||||
|
*
|
||||||
|
* @param string $script String that needs to get escaped.
|
||||||
|
* @return string Escaped string.
|
||||||
|
*/
|
||||||
|
function escape($string) {
|
||||||
|
$escape = array("\r\n" => '\n', "\r" => '\n', "\n" => '\n', '"' => '\"', "'" => "\\'");
|
||||||
|
return str_replace(array_keys($escape), array_values($escape), $string);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class JsHelperObject {
|
class JsHelperObject {
|
||||||
var $__parent = null;
|
var $__parent = null;
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,8 @@ class JsHelperTestCase extends CakeTestCase {
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
function startTest() {
|
function startTest() {
|
||||||
$this->Js = new JsHelper();
|
$this->Js = new JsHelper('JsBase');
|
||||||
|
$this->Js->JsBaseEngine = new JsBaseEngineHelper();
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* tearDown method
|
* tearDown method
|
||||||
|
@ -90,36 +91,6 @@ class JsHelperTestCase extends CakeTestCase {
|
||||||
$this->expectError();
|
$this->expectError();
|
||||||
$js->someMethodThatSurelyDoesntExist();
|
$js->someMethodThatSurelyDoesntExist();
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* test escape string skills
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
**/
|
|
||||||
function testEscaping() {
|
|
||||||
$result = $this->Js->escape('');
|
|
||||||
$expected = '';
|
|
||||||
$this->assertEqual($result, $expected);
|
|
||||||
|
|
||||||
$result = $this->Js->escape('CakePHP' . "\n" . 'Rapid Development Framework');
|
|
||||||
$expected = 'CakePHP\\nRapid Development Framework';
|
|
||||||
$this->assertEqual($result, $expected);
|
|
||||||
|
|
||||||
$result = $this->Js->escape('CakePHP' . "\r\n" . 'Rapid Development Framework' . "\r" . 'For PHP');
|
|
||||||
$expected = 'CakePHP\\nRapid Development Framework\\nFor PHP';
|
|
||||||
$this->assertEqual($result, $expected);
|
|
||||||
|
|
||||||
$result = $this->Js->escape('CakePHP: "Rapid Development Framework"');
|
|
||||||
$expected = 'CakePHP: \\"Rapid Development Framework\\"';
|
|
||||||
$this->assertEqual($result, $expected);
|
|
||||||
|
|
||||||
$result = $this->Js->escape('CakePHP: \'Rapid Development Framework\'');
|
|
||||||
$expected = 'CakePHP: \\\'Rapid Development Framework\\\'';
|
|
||||||
$this->assertEqual($result, $expected);
|
|
||||||
|
|
||||||
$result = $this->Js->escape('my \\"string\\"');
|
|
||||||
$expected = 'my \\\"string\\\"';
|
|
||||||
$this->assertEqual($result, $expected);
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* test prompt() creation
|
* test prompt() creation
|
||||||
*
|
*
|
||||||
|
@ -273,4 +244,61 @@ class JsHelperTestCase extends CakeTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JsBaseEngine Class Test case
|
||||||
|
*
|
||||||
|
* @package cake.tests.view.helpers
|
||||||
|
**/
|
||||||
|
class JsBaseEngineTestCase extends CakeTestCase {
|
||||||
|
/**
|
||||||
|
* setUp method
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function startTest() {
|
||||||
|
$this->JsEngine = new JsBaseEngineHelper();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* tearDown method
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function endTest() {
|
||||||
|
ClassRegistry::removeObject('view');
|
||||||
|
unset($this->JsEngine);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* test escape string skills
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
function testEscaping() {
|
||||||
|
$result = $this->JsEngine->escape('');
|
||||||
|
$expected = '';
|
||||||
|
$this->assertEqual($result, $expected);
|
||||||
|
|
||||||
|
$result = $this->JsEngine->escape('CakePHP' . "\n" . 'Rapid Development Framework');
|
||||||
|
$expected = 'CakePHP\\nRapid Development Framework';
|
||||||
|
$this->assertEqual($result, $expected);
|
||||||
|
|
||||||
|
$result = $this->JsEngine->escape('CakePHP' . "\r\n" . 'Rapid Development Framework' . "\r" . 'For PHP');
|
||||||
|
$expected = 'CakePHP\\nRapid Development Framework\\nFor PHP';
|
||||||
|
$this->assertEqual($result, $expected);
|
||||||
|
|
||||||
|
$result = $this->JsEngine->escape('CakePHP: "Rapid Development Framework"');
|
||||||
|
$expected = 'CakePHP: \\"Rapid Development Framework\\"';
|
||||||
|
$this->assertEqual($result, $expected);
|
||||||
|
|
||||||
|
$result = $this->JsEngine->escape('CakePHP: \'Rapid Development Framework\'');
|
||||||
|
$expected = 'CakePHP: \\\'Rapid Development Framework\\\'';
|
||||||
|
$this->assertEqual($result, $expected);
|
||||||
|
|
||||||
|
$result = $this->JsEngine->escape('my \\"string\\"');
|
||||||
|
$expected = 'my \\\"string\\\"';
|
||||||
|
$this->assertEqual($result, $expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
?>
|
?>
|
Loading…
Add table
Reference in a new issue