mirror of
https://github.com/yiisoft/yii2.git
synced 2025-11-17 14:57:23 +08:00
Refactored based on comments and feedback (3rd round)
This commit is contained in:
@@ -48,4 +48,11 @@ return array(
|
||||
YII_DEBUG ? 'punycode/punycode.js' : 'punycode/punycode.min.js',
|
||||
),
|
||||
),
|
||||
'yii/maskedinput' => array(
|
||||
'sourcePath' => __DIR__ . '/assets',
|
||||
'js' => array(
|
||||
'jquery.maskedinput.js',
|
||||
),
|
||||
'depends' => array('yii/jquery'),
|
||||
),
|
||||
);
|
||||
|
||||
338
framework/yii/assets/jquery.maskedinput.js
Normal file
338
framework/yii/assets/jquery.maskedinput.js
Normal file
@@ -0,0 +1,338 @@
|
||||
/*
|
||||
Masked Input plugin for jQuery
|
||||
Copyright (c) 2007-2013 Josh Bush (digitalbush.com)
|
||||
Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license)
|
||||
Version: 1.3.1
|
||||
*/
|
||||
(function($) {
|
||||
function getPasteEvent() {
|
||||
var el = document.createElement('input'),
|
||||
name = 'onpaste';
|
||||
el.setAttribute(name, '');
|
||||
return (typeof el[name] === 'function')?'paste':'input';
|
||||
}
|
||||
|
||||
var pasteEventName = getPasteEvent() + ".mask",
|
||||
ua = navigator.userAgent,
|
||||
iPhone = /iphone/i.test(ua),
|
||||
android=/android/i.test(ua),
|
||||
caretTimeoutId;
|
||||
|
||||
$.mask = {
|
||||
//Predefined character definitions
|
||||
definitions: {
|
||||
'9': "[0-9]",
|
||||
'a': "[A-Za-z]",
|
||||
'*': "[A-Za-z0-9]"
|
||||
},
|
||||
dataName: "rawMaskFn",
|
||||
placeholder: '_',
|
||||
};
|
||||
|
||||
$.fn.extend({
|
||||
//Helper Function for Caret positioning
|
||||
caret: function(begin, end) {
|
||||
var range;
|
||||
|
||||
if (this.length === 0 || this.is(":hidden")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof begin == 'number') {
|
||||
end = (typeof end === 'number') ? end : begin;
|
||||
return this.each(function() {
|
||||
if (this.setSelectionRange) {
|
||||
this.setSelectionRange(begin, end);
|
||||
} else if (this.createTextRange) {
|
||||
range = this.createTextRange();
|
||||
range.collapse(true);
|
||||
range.moveEnd('character', end);
|
||||
range.moveStart('character', begin);
|
||||
range.select();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (this[0].setSelectionRange) {
|
||||
begin = this[0].selectionStart;
|
||||
end = this[0].selectionEnd;
|
||||
} else if (document.selection && document.selection.createRange) {
|
||||
range = document.selection.createRange();
|
||||
begin = 0 - range.duplicate().moveStart('character', -100000);
|
||||
end = begin + range.text.length;
|
||||
}
|
||||
return { begin: begin, end: end };
|
||||
}
|
||||
},
|
||||
unmask: function() {
|
||||
return this.trigger("unmask");
|
||||
},
|
||||
mask: function(mask, settings) {
|
||||
var input,
|
||||
defs,
|
||||
tests,
|
||||
partialPosition,
|
||||
firstNonMaskPos,
|
||||
len;
|
||||
|
||||
if (!mask && this.length > 0) {
|
||||
input = $(this[0]);
|
||||
return input.data($.mask.dataName)();
|
||||
}
|
||||
settings = $.extend({
|
||||
placeholder: $.mask.placeholder, // Load default placeholder
|
||||
completed: null
|
||||
}, settings);
|
||||
|
||||
|
||||
defs = $.mask.definitions;
|
||||
tests = [];
|
||||
partialPosition = len = mask.length;
|
||||
firstNonMaskPos = null;
|
||||
|
||||
$.each(mask.split(""), function(i, c) {
|
||||
if (c == '?') {
|
||||
len--;
|
||||
partialPosition = i;
|
||||
} else if (defs[c]) {
|
||||
tests.push(new RegExp(defs[c]));
|
||||
if (firstNonMaskPos === null) {
|
||||
firstNonMaskPos = tests.length - 1;
|
||||
}
|
||||
} else {
|
||||
tests.push(null);
|
||||
}
|
||||
});
|
||||
|
||||
return this.trigger("unmask").each(function() {
|
||||
var input = $(this),
|
||||
buffer = $.map(
|
||||
mask.split(""),
|
||||
function(c, i) {
|
||||
if (c != '?') {
|
||||
return defs[c] ? settings.placeholder : c;
|
||||
}
|
||||
}),
|
||||
focusText = input.val();
|
||||
|
||||
function seekNext(pos) {
|
||||
while (++pos < len && !tests[pos]);
|
||||
return pos;
|
||||
}
|
||||
|
||||
function seekPrev(pos) {
|
||||
while (--pos >= 0 && !tests[pos]);
|
||||
return pos;
|
||||
}
|
||||
|
||||
function shiftL(begin,end) {
|
||||
var i,
|
||||
j;
|
||||
|
||||
if (begin<0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = begin, j = seekNext(end); i < len; i++) {
|
||||
if (tests[i]) {
|
||||
if (j < len && tests[i].test(buffer[j])) {
|
||||
buffer[i] = buffer[j];
|
||||
buffer[j] = settings.placeholder;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
j = seekNext(j);
|
||||
}
|
||||
}
|
||||
writeBuffer();
|
||||
input.caret(Math.max(firstNonMaskPos, begin));
|
||||
}
|
||||
|
||||
function shiftR(pos) {
|
||||
var i,
|
||||
c,
|
||||
j,
|
||||
t;
|
||||
|
||||
for (i = pos, c = settings.placeholder; i < len; i++) {
|
||||
if (tests[i]) {
|
||||
j = seekNext(i);
|
||||
t = buffer[i];
|
||||
buffer[i] = c;
|
||||
if (j < len && tests[j].test(t)) {
|
||||
c = t;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function keydownEvent(e) {
|
||||
var k = e.which,
|
||||
pos,
|
||||
begin,
|
||||
end;
|
||||
|
||||
//backspace, delete, and escape get special treatment
|
||||
if (k === 8 || k === 46 || (iPhone && k === 127)) {
|
||||
pos = input.caret();
|
||||
begin = pos.begin;
|
||||
end = pos.end;
|
||||
|
||||
if (end - begin === 0) {
|
||||
begin=k!==46?seekPrev(begin):(end=seekNext(begin-1));
|
||||
end=k===46?seekNext(end):end;
|
||||
}
|
||||
clearBuffer(begin, end);
|
||||
shiftL(begin, end - 1);
|
||||
|
||||
e.preventDefault();
|
||||
} else if (k == 27) {//escape
|
||||
input.val(focusText);
|
||||
input.caret(0, checkVal());
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
function keypressEvent(e) {
|
||||
var k = e.which,
|
||||
pos = input.caret(),
|
||||
p,
|
||||
c,
|
||||
next;
|
||||
|
||||
if (e.ctrlKey || e.altKey || e.metaKey || k < 32) {//Ignore
|
||||
return;
|
||||
} else if (k) {
|
||||
if (pos.end - pos.begin !== 0){
|
||||
clearBuffer(pos.begin, pos.end);
|
||||
shiftL(pos.begin, pos.end-1);
|
||||
}
|
||||
|
||||
p = seekNext(pos.begin - 1);
|
||||
if (p < len) {
|
||||
c = String.fromCharCode(k);
|
||||
if (tests[p].test(c)) {
|
||||
shiftR(p);
|
||||
|
||||
buffer[p] = c;
|
||||
writeBuffer();
|
||||
next = seekNext(p);
|
||||
|
||||
if(android){
|
||||
setTimeout($.proxy($.fn.caret,input,next),0);
|
||||
}else{
|
||||
input.caret(next);
|
||||
}
|
||||
|
||||
if (settings.completed && next >= len) {
|
||||
settings.completed.call(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
function clearBuffer(start, end) {
|
||||
var i;
|
||||
for (i = start; i < end && i < len; i++) {
|
||||
if (tests[i]) {
|
||||
buffer[i] = settings.placeholder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function writeBuffer() { input.val(buffer.join('')); }
|
||||
|
||||
function checkVal(allow) {
|
||||
//try to place characters where they belong
|
||||
var test = input.val(),
|
||||
lastMatch = -1,
|
||||
i,
|
||||
c;
|
||||
|
||||
for (i = 0, pos = 0; i < len; i++) {
|
||||
if (tests[i]) {
|
||||
buffer[i] = settings.placeholder;
|
||||
while (pos++ < test.length) {
|
||||
c = test.charAt(pos - 1);
|
||||
if (tests[i].test(c)) {
|
||||
buffer[i] = c;
|
||||
lastMatch = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pos > test.length) {
|
||||
break;
|
||||
}
|
||||
} else if (buffer[i] === test.charAt(pos) && i !== partialPosition) {
|
||||
pos++;
|
||||
lastMatch = i;
|
||||
}
|
||||
}
|
||||
if (allow) {
|
||||
writeBuffer();
|
||||
} else if (lastMatch + 1 < partialPosition) {
|
||||
input.val("");
|
||||
clearBuffer(0, len);
|
||||
} else {
|
||||
writeBuffer();
|
||||
input.val(input.val().substring(0, lastMatch + 1));
|
||||
}
|
||||
return (partialPosition ? i : firstNonMaskPos);
|
||||
}
|
||||
|
||||
input.data($.mask.dataName,function(){
|
||||
return $.map(buffer, function(c, i) {
|
||||
return tests[i]&&c!=settings.placeholder ? c : null;
|
||||
}).join('');
|
||||
});
|
||||
|
||||
if (!input.attr("readonly"))
|
||||
input
|
||||
.one("unmask", function() {
|
||||
input
|
||||
.unbind(".mask")
|
||||
.removeData($.mask.dataName);
|
||||
})
|
||||
.bind("focus.mask", function() {
|
||||
clearTimeout(caretTimeoutId);
|
||||
var pos,
|
||||
moveCaret;
|
||||
|
||||
focusText = input.val();
|
||||
pos = checkVal();
|
||||
|
||||
caretTimeoutId = setTimeout(function(){
|
||||
writeBuffer();
|
||||
if (pos == mask.length) {
|
||||
input.caret(0, pos);
|
||||
} else {
|
||||
input.caret(pos);
|
||||
}
|
||||
}, 10);
|
||||
})
|
||||
.bind("blur.mask", function() {
|
||||
checkVal();
|
||||
if (input.val() != focusText)
|
||||
input.change();
|
||||
})
|
||||
.bind("keydown.mask", keydownEvent)
|
||||
.bind("keypress.mask", keypressEvent)
|
||||
.bind(pasteEventName, function() {
|
||||
setTimeout(function() {
|
||||
var pos=checkVal(true);
|
||||
input.caret(pos);
|
||||
if (settings.completed && pos == input.val().length)
|
||||
settings.completed.call(input);
|
||||
}, 0);
|
||||
});
|
||||
checkVal(); //Perform initial check for existing values
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
})(jQuery);
|
||||
@@ -30,8 +30,8 @@ class ActionFilter extends Behavior
|
||||
public function events()
|
||||
{
|
||||
return array(
|
||||
'beforeAction' => 'beforeFilter',
|
||||
'afterAction' => 'afterFilter',
|
||||
Controller::EVENT_BEFORE_ACTION => 'beforeFilter',
|
||||
Controller::EVENT_AFTER_ACTION => 'afterFilter',
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -278,6 +278,15 @@ class Application extends Module
|
||||
return $this->getComponent('cache');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the formatter component.
|
||||
* @return \yii\base\Formatter the formatter application component.
|
||||
*/
|
||||
public function getFormatter()
|
||||
{
|
||||
return $this->getComponent('formatter');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the request component.
|
||||
* @return \yii\web\Request|\yii\console\Request the request component
|
||||
@@ -333,6 +342,9 @@ class Application extends Module
|
||||
'errorHandler' => array(
|
||||
'class' => 'yii\base\ErrorHandler',
|
||||
),
|
||||
'formatter' => array(
|
||||
'class' => 'yii\base\Formatter',
|
||||
),
|
||||
'i18n' => array(
|
||||
'class' => 'yii\i18n\I18N',
|
||||
),
|
||||
|
||||
@@ -151,43 +151,13 @@ class Controller extends Component
|
||||
/**
|
||||
* Binds the parameters to the action.
|
||||
* This method is invoked by [[Action]] when it begins to run with the given parameters.
|
||||
* This method will check the parameter names that the action requires and return
|
||||
* the provided parameters according to the requirement. If there is any missing parameter,
|
||||
* an exception will be thrown.
|
||||
* @param Action $action the action to be bound with parameters
|
||||
* @param array $params the parameters to be bound to the action
|
||||
* @return array the valid parameters that the action can run with.
|
||||
* @throws InvalidRequestException if there are missing parameters.
|
||||
*/
|
||||
public function bindActionParams($action, $params)
|
||||
{
|
||||
if ($action instanceof InlineAction) {
|
||||
$method = new \ReflectionMethod($this, $action->actionMethod);
|
||||
} else {
|
||||
$method = new \ReflectionMethod($action, 'run');
|
||||
}
|
||||
|
||||
$args = array();
|
||||
$missing = array();
|
||||
foreach ($method->getParameters() as $param) {
|
||||
$name = $param->getName();
|
||||
if (array_key_exists($name, $params)) {
|
||||
$args[] = $params[$name];
|
||||
unset($params[$name]);
|
||||
} elseif ($param->isDefaultValueAvailable()) {
|
||||
$args[] = $param->getDefaultValue();
|
||||
} else {
|
||||
$missing[] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($missing)) {
|
||||
throw new InvalidRequestException(Yii::t('yii', 'Missing required parameters: {params}', array(
|
||||
'{params}' => implode(', ', $missing),
|
||||
)));
|
||||
}
|
||||
|
||||
return $args;
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -271,18 +241,6 @@ class Controller extends Component
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the parameter being bound to actions.
|
||||
* This method is invoked when parameters are being bound to the currently requested action.
|
||||
* Child classes may override this method to throw exceptions when there are missing and/or unknown parameters.
|
||||
* @param Action $action the currently requested action
|
||||
* @param array $missingParams the names of the missing parameters
|
||||
* @param array $unknownParams the unknown parameters (name => value)
|
||||
*/
|
||||
public function validateActionParams($action, $missingParams, $unknownParams)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the controller ID that is prefixed with the module ID (if any).
|
||||
*/
|
||||
|
||||
292
framework/yii/base/Formatter.php
Normal file
292
framework/yii/base/Formatter.php
Normal file
@@ -0,0 +1,292 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\base;
|
||||
|
||||
use Yii;
|
||||
use DateTime;
|
||||
use yii\helpers\HtmlPurifier;
|
||||
use yii\helpers\Html;
|
||||
|
||||
|
||||
/**
|
||||
* Formatter provides a set of commonly used data formatting methods.
|
||||
*
|
||||
* The formatting methods provided by Formatter are all named in the form of `asXyz()`.
|
||||
* The behavior of some of them may be configured via the properties of Formatter. For example,
|
||||
* by configuring [[dateFormat]], one may control how [[asDate()]] formats the value into a date string.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class Formatter extends Component
|
||||
{
|
||||
/**
|
||||
* @var string the default format string to be used to format a date using PHP date() function.
|
||||
*/
|
||||
public $dateFormat = 'Y/m/d';
|
||||
/**
|
||||
* @var string the default format string to be used to format a time using PHP date() function.
|
||||
*/
|
||||
public $timeFormat = 'h:i:s A';
|
||||
/**
|
||||
* @var string the default format string to be used to format a date and time using PHP date() function.
|
||||
*/
|
||||
public $datetimeFormat = 'Y/m/d h:i:s A';
|
||||
/**
|
||||
* @var array the text to be displayed when formatting a boolean value. The first element corresponds
|
||||
* to the text display for false, the second element for true. Defaults to <code>array('No', 'Yes')</code>.
|
||||
*/
|
||||
public $booleanFormat;
|
||||
/**
|
||||
* @var string the character displayed as the decimal point when formatting a number.
|
||||
*/
|
||||
public $decimalSeparator = '.';
|
||||
/**
|
||||
* @var string the character displayed as the thousands separator character when formatting a number.
|
||||
*/
|
||||
public $thousandSeparator = ',';
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the component.
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
if (empty($this->booleanFormat)) {
|
||||
$this->booleanFormat = array(Yii::t('yii', 'No'), Yii::t('yii', 'Yes'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as is without any formatting.
|
||||
* This method simply returns back the parameter without any format.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatted result
|
||||
*/
|
||||
public function asRaw($value)
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as an HTML-encoded plain text.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatted result
|
||||
*/
|
||||
public function asText($value)
|
||||
{
|
||||
return Html::encode($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as an HTML-encoded plain text with newlines converted into breaks.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatted result
|
||||
*/
|
||||
public function asNtext($value)
|
||||
{
|
||||
return nl2br(Html::encode($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as HTML-encoded text paragraphs.
|
||||
* Each text paragraph is enclosed within a `<p>` tag.
|
||||
* One or multiple consecutive empty lines divide two paragraphs.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatted result
|
||||
*/
|
||||
public function asParagraphs($value)
|
||||
{
|
||||
return str_replace('<p></p>', '',
|
||||
'<p>' . preg_replace('/[\r\n]{2,}/', "</p>\n<p>", Html::encode($value)) . '</p>'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as HTML text.
|
||||
* The value will be purified using [[HtmlPurifier]] to avoid XSS attacks.
|
||||
* Use [[asRaw()]] if you do not want any purification of the value.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @param array|null $config the configuration for the HTMLPurifier class.
|
||||
* @return string the formatted result
|
||||
*/
|
||||
public function asHtml($value, $config = null)
|
||||
{
|
||||
return HtmlPurifier::process($value, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a mailto link.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatted result
|
||||
*/
|
||||
public function asEmail($value)
|
||||
{
|
||||
return Html::mailto($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as an image tag.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatted result
|
||||
*/
|
||||
public function asImage($value)
|
||||
{
|
||||
return Html::img($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a hyperlink.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatted result
|
||||
*/
|
||||
public function asUrl($value)
|
||||
{
|
||||
$url = $value;
|
||||
if (strpos($url, 'http://') !== 0 && strpos($url, 'https://') !== 0) {
|
||||
$url = 'http://' . $url;
|
||||
}
|
||||
return Html::a(Html::encode($value), $url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a boolean.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatted result
|
||||
* @see booleanFormat
|
||||
*/
|
||||
public function asBoolean($value)
|
||||
{
|
||||
return $value ? $this->booleanFormat[1] : $this->booleanFormat[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a date.
|
||||
* @param integer|string|DateTime $value the value to be formatted. The following
|
||||
* types of value are supported:
|
||||
*
|
||||
* - an integer representing a UNIX timestamp
|
||||
* - a string that can be parsed into a UNIX timestamp via `strtotime()`
|
||||
* - a PHP DateTime object
|
||||
*
|
||||
* @param string $format the format used to convert the value into a date string.
|
||||
* If null, [[dateFormat]] will be used. The format string should be one
|
||||
* that can be recognized by the PHP `date()` function.
|
||||
* @return string the formatted result
|
||||
* @see dateFormat
|
||||
*/
|
||||
public function asDate($value, $format = null)
|
||||
{
|
||||
$value = $this->normalizeDatetimeValue($value);
|
||||
return date($format === null ? $this->dateFormat : $format, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a time.
|
||||
* @param integer|string|DateTime $value the value to be formatted. The following
|
||||
* types of value are supported:
|
||||
*
|
||||
* - an integer representing a UNIX timestamp
|
||||
* - a string that can be parsed into a UNIX timestamp via `strtotime()`
|
||||
* - a PHP DateTime object
|
||||
*
|
||||
* @param string $format the format used to convert the value into a date string.
|
||||
* If null, [[timeFormat]] will be used. The format string should be one
|
||||
* that can be recognized by the PHP `date()` function.
|
||||
* @return string the formatted result
|
||||
* @see timeFormat
|
||||
*/
|
||||
public function asTime($value, $format = null)
|
||||
{
|
||||
$value = $this->normalizeDatetimeValue($value);
|
||||
return date($format === null ? $this->timeFormat : $format, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a datetime.
|
||||
* @param integer|string|DateTime $value the value to be formatted. The following
|
||||
* types of value are supported:
|
||||
*
|
||||
* - an integer representing a UNIX timestamp
|
||||
* - a string that can be parsed into a UNIX timestamp via `strtotime()`
|
||||
* - a PHP DateTime object
|
||||
*
|
||||
* @param string $format the format used to convert the value into a date string.
|
||||
* If null, [[datetimeFormat]] will be used. The format string should be one
|
||||
* that can be recognized by the PHP `date()` function.
|
||||
* @return string the formatted result
|
||||
* @see datetimeFormat
|
||||
*/
|
||||
public function asDatetime($value, $format = null)
|
||||
{
|
||||
$value = $this->normalizeDatetimeValue($value);
|
||||
return date($format === null ? $this->datetimeFormat : $format, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the given datetime value as one that can be taken by various date/time formatting methods.
|
||||
* @param mixed $value the datetime value to be normalized.
|
||||
* @return mixed the normalized datetime value
|
||||
*/
|
||||
protected function normalizeDatetimeValue($value)
|
||||
{
|
||||
if (is_string($value)) {
|
||||
if (ctype_digit($value) || $value[0] === '-' && ctype_digit(substr($value, 1))) {
|
||||
return (int)$value;
|
||||
} else {
|
||||
return strtotime($value);
|
||||
}
|
||||
} elseif ($value instanceof DateTime) {
|
||||
return $value->getTimestamp();
|
||||
} else {
|
||||
return (int)$value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as an integer.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @return string the formatting result.
|
||||
*/
|
||||
public function asInteger($value)
|
||||
{
|
||||
if (is_string($value) && preg_match('/^(-?\d+)/', $value, $matches)) {
|
||||
return $matches[1];
|
||||
} else {
|
||||
$value = (int)$value;
|
||||
return "$value";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a double number.
|
||||
* Property [[decimalSeparator]] will be used to represent the decimal point.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @param integer $decimals the number of digits after the decimal point
|
||||
* @return string the formatting result.
|
||||
* @see decimalSeparator
|
||||
*/
|
||||
public function asDouble($value, $decimals = 2)
|
||||
{
|
||||
return str_replace('.', $this->decimalSeparator, sprintf("%.{$decimals}f", $value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a number with decimal and thousand separators.
|
||||
* This method calls the PHP number_format() function to do the formatting.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @param integer $decimals the number of digits after the decimal point
|
||||
* @return string the formatted result
|
||||
* @see decimalSeparator
|
||||
* @see thousandSeparator
|
||||
*/
|
||||
public function asNumber($value, $decimals = 0)
|
||||
{
|
||||
return number_format($value, $decimals, $this->decimalSeparator, $this->thousandSeparator);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\base;
|
||||
|
||||
/**
|
||||
* InvalidRequestException represents an exception caused by incorrect end user request.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class InvalidRequestException extends UserException
|
||||
{
|
||||
/**
|
||||
* @return string the user-friendly name of this exception
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return \Yii::t('yii', 'Invalid Request');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
namespace yii\bootstrap;
|
||||
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\helpers\base\ArrayHelper;
|
||||
use yii\helpers\ArrayHelper;
|
||||
use yii\helpers\Html;
|
||||
|
||||
|
||||
@@ -32,17 +32,22 @@ class Dropdown extends Widget
|
||||
* // optional, url of the item link
|
||||
* 'url' => '',
|
||||
* // optional the HTML attributes of the item link
|
||||
* 'urlOptions'=> array(...),
|
||||
* 'linkOptions'=> array(...),
|
||||
* // optional the HTML attributes of the item
|
||||
* 'options'=> array(...),
|
||||
* // optional, an array of items that configure a sub menu of the item
|
||||
* // note: if `items` is set, then `url` of the parent item will be ignored and automatically set to "#"
|
||||
* // important: there is an issue with sub-dropdown menus, and as of 3.0, bootstrap won't support sub-dropdown
|
||||
* // @see https://github.com/twitter/bootstrap/issues/5050#issuecomment-11741727
|
||||
* 'items'=> array(...)
|
||||
* )
|
||||
* ```
|
||||
* Additionally, you can also configure a dropdown item as string.
|
||||
*/
|
||||
public $items = array();
|
||||
/**
|
||||
* @var boolean whether the labels for header items should be HTML-encoded.
|
||||
*/
|
||||
public $encodeLabels = true;
|
||||
|
||||
|
||||
/**
|
||||
@@ -60,43 +65,41 @@ class Dropdown extends Widget
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
echo Html::beginTag('ul', $this->options) . "\n";
|
||||
echo $this->renderContents() . "\n";
|
||||
echo Html::endTag('ul') . "\n";
|
||||
echo $this->renderItems() . "\n";
|
||||
$this->registerPlugin('dropdown');
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders dropdown contents as specified on [[items]].
|
||||
* Renders dropdown items as specified on [[items]].
|
||||
* @return string the rendering result.
|
||||
* @throws InvalidConfigException
|
||||
*/
|
||||
protected function renderContents()
|
||||
protected function renderItems()
|
||||
{
|
||||
$contents = array();
|
||||
$items = array();
|
||||
foreach ($this->items as $item) {
|
||||
if (is_string($item)) {
|
||||
$contents[] = $item;
|
||||
$items[] = $item;
|
||||
continue;
|
||||
}
|
||||
if (!isset($item['label'])) {
|
||||
throw new InvalidConfigException("The 'label' option is required.");
|
||||
}
|
||||
|
||||
$label = $this->encodeLabels ? Html::encode($item['label']) : $item['label'];
|
||||
$options = ArrayHelper::getValue($item, 'options', array());
|
||||
$urlOptions = ArrayHelper::getValue($item, 'urlOptions', array());
|
||||
$urlOptions['tabindex'] = '-1';
|
||||
$linkOptions = ArrayHelper::getValue($item, 'linkOptions', array());
|
||||
$linkOptions['tabindex'] = '-1';
|
||||
|
||||
if (isset($item['items'])) {
|
||||
$this->addCssClass($options, 'dropdown-submenu');
|
||||
$content = Html::a($item['label'], '#', $urlOptions) . $this->dropdown($item['items']);
|
||||
$content = Html::a($label, '#', $linkOptions) . $this->dropdown($item['items']);
|
||||
} else {
|
||||
$content = Html::a($item['label'], ArrayHelper::getValue($item, 'url', '#'), $urlOptions);
|
||||
$content = Html::a($label, ArrayHelper::getValue($item, 'url', '#'), $linkOptions);
|
||||
}
|
||||
$contents[] = Html::tag('li', $content , $options);
|
||||
$items[] = Html::tag('li', $content , $options);
|
||||
}
|
||||
|
||||
return implode("\n", $contents);
|
||||
return Html::tag('ul', implode("\n", $items), $this->options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -344,7 +344,7 @@ class Html
|
||||
/**
|
||||
* Generates a hyperlink tag.
|
||||
* @param string $text link body. It will NOT be HTML-encoded. Therefore you can pass in HTML code
|
||||
* such as an image tag. If this is is coming from end users, you should consider [[encode()]]
|
||||
* such as an image tag. If this is coming from end users, you should consider [[encode()]]
|
||||
* it to prevent XSS attacks.
|
||||
* @param array|string|null $url the URL for the hyperlink tag. This parameter will be processed by [[url()]]
|
||||
* and will be used for the "href" attribute of the tag. If this parameter is null, the "href" attribute
|
||||
@@ -366,7 +366,7 @@ class Html
|
||||
/**
|
||||
* Generates a mailto hyperlink.
|
||||
* @param string $text link body. It will NOT be HTML-encoded. Therefore you can pass in HTML code
|
||||
* such as an image tag. If this is is coming from end users, you should consider [[encode()]]
|
||||
* such as an image tag. If this is coming from end users, you should consider [[encode()]]
|
||||
* it to prevent XSS attacks.
|
||||
* @param string $email email address. If this is null, the first parameter (link body) will be treated
|
||||
* as the email address and used.
|
||||
|
||||
232
framework/yii/i18n/Formatter.php
Normal file
232
framework/yii/i18n/Formatter.php
Normal file
@@ -0,0 +1,232 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\i18n;
|
||||
|
||||
use Yii;
|
||||
use IntlDateFormatter;
|
||||
use NumberFormatter;
|
||||
use DateTime;
|
||||
use yii\base\InvalidConfigException;
|
||||
|
||||
/**
|
||||
* Formatter is the localized version of [[\yii\base\Formatter]].
|
||||
*
|
||||
* Formatter requires the PHP "intl" extension to be installed. Formatter supports localized
|
||||
* formatting of date, time and numbers, based on the current [[locale]].
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class Formatter extends \yii\base\Formatter
|
||||
{
|
||||
/**
|
||||
* @var string the locale ID that is used to localize the date and number formatting.
|
||||
* If not set, [[\yii\base\Application::language]] will be used.
|
||||
*/
|
||||
public $locale;
|
||||
/**
|
||||
* @var string the default format string to be used to format a date using PHP date() function.
|
||||
*/
|
||||
public $dateFormat = 'short';
|
||||
/**
|
||||
* @var string the default format string to be used to format a time using PHP date() function.
|
||||
*/
|
||||
public $timeFormat = 'short';
|
||||
/**
|
||||
* @var string the default format string to be used to format a date and time using PHP date() function.
|
||||
*/
|
||||
public $datetimeFormat = 'short';
|
||||
/**
|
||||
* @var array the options to be set for the NumberFormatter objects. Please refer to
|
||||
*/
|
||||
public $numberFormatOptions = array();
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the component.
|
||||
* This method will check if the "intl" PHP extension is installed and set the
|
||||
* default value of [[locale]].
|
||||
* @throws InvalidConfigException if the "intl" PHP extension is not installed.
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
if (!extension_loaded('intl')) {
|
||||
throw new InvalidConfigException('The "intl" PHP extension is not install. It is required to format data values in localized formats.');
|
||||
}
|
||||
if ($this->locale === null) {
|
||||
$this->locale = Yii::$app->language;
|
||||
}
|
||||
parent::init();
|
||||
}
|
||||
|
||||
private $_dateFormats = array(
|
||||
'short' => IntlDateFormatter::SHORT,
|
||||
'medium' => IntlDateFormatter::MEDIUM,
|
||||
'long' => IntlDateFormatter::LONG,
|
||||
'full' => IntlDateFormatter::FULL,
|
||||
);
|
||||
|
||||
/**
|
||||
* Formats the value as a date.
|
||||
* @param integer|string|DateTime $value the value to be formatted. The following
|
||||
* types of value are supported:
|
||||
*
|
||||
* - an integer representing a UNIX timestamp
|
||||
* - a string that can be parsed into a UNIX timestamp via `strtotime()`
|
||||
* - a PHP DateTime object
|
||||
*
|
||||
* @param string $format the format used to convert the value into a date string.
|
||||
* If null, [[dateFormat]] will be used. The format string should be the one
|
||||
* that can be recognized by the PHP `date()` function.
|
||||
* @return string the formatted result
|
||||
* @see dateFormat
|
||||
*/
|
||||
public function asDate($value, $format = null)
|
||||
{
|
||||
$value = $this->normalizeDatetimeValue($value);
|
||||
if ($format === null) {
|
||||
$format = $this->dateFormat;
|
||||
}
|
||||
if (isset($this->_dateFormats[$format])) {
|
||||
$formatter = new IntlDateFormatter($this->locale, $this->_dateFormats[$format], IntlDateFormatter::NONE);
|
||||
} else {
|
||||
$formatter = new IntlDateFormatter($this->locale, IntlDateFormatter::NONE, IntlDateFormatter::NONE);
|
||||
$formatter->setPattern($format);
|
||||
}
|
||||
return $formatter->format($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a time.
|
||||
* @param integer|string|DateTime $value the value to be formatted. The following
|
||||
* types of value are supported:
|
||||
*
|
||||
* - an integer representing a UNIX timestamp
|
||||
* - a string that can be parsed into a UNIX timestamp via `strtotime()`
|
||||
* - a PHP DateTime object
|
||||
*
|
||||
* @param string $format the format used to convert the value into a date string.
|
||||
* If null, [[dateFormat]] will be used. The format string should be the one
|
||||
* that can be recognized by the PHP `date()` function.
|
||||
* @return string the formatted result
|
||||
* @see timeFormat
|
||||
*/
|
||||
public function asTime($value, $format = null)
|
||||
{
|
||||
$value = $this->normalizeDatetimeValue($value);
|
||||
if ($format === null) {
|
||||
$format = $this->timeFormat;
|
||||
}
|
||||
if (isset($this->_dateFormats[$format])) {
|
||||
$formatter = new IntlDateFormatter($this->locale, IntlDateFormatter::NONE, $this->_dateFormats[$format]);
|
||||
} else {
|
||||
$formatter = new IntlDateFormatter($this->locale, IntlDateFormatter::NONE, IntlDateFormatter::NONE);
|
||||
$formatter->setPattern($format);
|
||||
}
|
||||
return $formatter->format($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a datetime.
|
||||
* @param integer|string|DateTime $value the value to be formatted. The following
|
||||
* types of value are supported:
|
||||
*
|
||||
* - an integer representing a UNIX timestamp
|
||||
* - a string that can be parsed into a UNIX timestamp via `strtotime()`
|
||||
* - a PHP DateTime object
|
||||
*
|
||||
* @param string $format the format used to convert the value into a date string.
|
||||
* If null, [[dateFormat]] will be used. The format string should be the one
|
||||
* that can be recognized by the PHP `date()` function.
|
||||
* @return string the formatted result
|
||||
* @see datetimeFormat
|
||||
*/
|
||||
public function asDatetime($value, $format = null)
|
||||
{
|
||||
$value = $this->normalizeDatetimeValue($value);
|
||||
if ($format === null) {
|
||||
$format = $this->datetimeFormat;
|
||||
}
|
||||
if (isset($this->_dateFormats[$format])) {
|
||||
$formatter = new IntlDateFormatter($this->locale, $this->_dateFormats[$format], $this->_dateFormats[$format]);
|
||||
} else {
|
||||
$formatter = new IntlDateFormatter($this->locale, IntlDateFormatter::NONE, IntlDateFormatter::NONE);
|
||||
$formatter->setPattern($format);
|
||||
}
|
||||
return $formatter->format($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a decimal number.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @param string $format the format to be used. Please refer to [ICU manual](http://www.icu-project.org/apiref/icu4c/classDecimalFormat.html#_details)
|
||||
* for details on how to specify a format.
|
||||
* @return string the formatted result.
|
||||
*/
|
||||
public function asDecimal($value, $format = null)
|
||||
{
|
||||
return $this->createNumberFormatter(NumberFormatter::DECIMAL, $format)->format($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a currency number.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @param string $currency the 3-letter ISO 4217 currency code indicating the currency to use.
|
||||
* @param string $format the format to be used. Please refer to [ICU manual](http://www.icu-project.org/apiref/icu4c/classDecimalFormat.html#_details)
|
||||
* for details on how to specify a format.
|
||||
* @return string the formatted result.
|
||||
*/
|
||||
public function asCurrency($value, $currency = 'USD', $format = null)
|
||||
{
|
||||
return $this->createNumberFormatter(NumberFormatter::CURRENCY, $format)->formatCurrency($value, $currency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a percent number.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @param string $format the format to be used. Please refer to [ICU manual](http://www.icu-project.org/apiref/icu4c/classDecimalFormat.html#_details)
|
||||
* for details on how to specify a format.
|
||||
* @return string the formatted result.
|
||||
*/
|
||||
public function asPercent($value, $format = null)
|
||||
{
|
||||
return $this->createNumberFormatter(NumberFormatter::PERCENT, $format)->format($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the value as a scientific number.
|
||||
* @param mixed $value the value to be formatted
|
||||
* @param string $format the format to be used. Please refer to [ICU manual](http://www.icu-project.org/apiref/icu4c/classDecimalFormat.html#_details)
|
||||
* for details on how to specify a format.
|
||||
* @return string the formatted result.
|
||||
*/
|
||||
public function asScientific($value, $format = null)
|
||||
{
|
||||
return $this->createNumberFormatter(NumberFormatter::SCIENTIFIC, $format)->format($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a number formatter based on the given type and format.
|
||||
* @param integer $type the type of the number formatter
|
||||
* @param string $format the format to be used
|
||||
* @return NumberFormatter the created formatter instance
|
||||
*/
|
||||
protected function createNumberFormatter($type, $format)
|
||||
{
|
||||
$formatter = new NumberFormatter($this->locale, $type);
|
||||
if ($format !== null) {
|
||||
$formatter->setPattern($format);
|
||||
}
|
||||
if (!empty($this->numberFormatOptions)) {
|
||||
foreach ($this->numberFormatOptions as $name => $attribute) {
|
||||
$formatter->setAttribute($name, $attribute);
|
||||
}
|
||||
}
|
||||
return $formatter;
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,6 @@ return array(
|
||||
'mandatory' => false,
|
||||
'condition' => $this->checkPhpExtensionVersion('intl', '1.0.2'),
|
||||
'by' => '<a href="http://www.php.net/manual/en/book.intl.php">Internationalization</a> support',
|
||||
'memo' => 'PHP Intl extension 1.0.2 or higher is required when you want to use <abbr title="Internationalized domain names">IDN</abbr>-feature of EmailValidator or UrlValidator.'
|
||||
'memo' => 'PHP Intl extension 1.0.2 or higher is required when you want to use <abbr title="Internationalized domain names">IDN</abbr>-feature of EmailValidator or UrlValidator or the <code>yii\i18n\Formatter</code> class.'
|
||||
),
|
||||
);
|
||||
@@ -8,6 +8,8 @@
|
||||
namespace yii\web;
|
||||
|
||||
use Yii;
|
||||
use yii\base\HttpException;
|
||||
use yii\base\InlineAction;
|
||||
|
||||
/**
|
||||
* Controller is the base class of Web controllers.
|
||||
@@ -18,6 +20,48 @@ use Yii;
|
||||
*/
|
||||
class Controller extends \yii\base\Controller
|
||||
{
|
||||
/**
|
||||
* Binds the parameters to the action.
|
||||
* This method is invoked by [[Action]] when it begins to run with the given parameters.
|
||||
* This method will check the parameter names that the action requires and return
|
||||
* the provided parameters according to the requirement. If there is any missing parameter,
|
||||
* an exception will be thrown.
|
||||
* @param \yii\base\Action $action the action to be bound with parameters
|
||||
* @param array $params the parameters to be bound to the action
|
||||
* @return array the valid parameters that the action can run with.
|
||||
* @throws HttpException if there are missing parameters.
|
||||
*/
|
||||
public function bindActionParams($action, $params)
|
||||
{
|
||||
if ($action instanceof InlineAction) {
|
||||
$method = new \ReflectionMethod($this, $action->actionMethod);
|
||||
} else {
|
||||
$method = new \ReflectionMethod($action, 'run');
|
||||
}
|
||||
|
||||
$args = array();
|
||||
$missing = array();
|
||||
foreach ($method->getParameters() as $param) {
|
||||
$name = $param->getName();
|
||||
if (array_key_exists($name, $params)) {
|
||||
$args[] = $params[$name];
|
||||
unset($params[$name]);
|
||||
} elseif ($param->isDefaultValueAvailable()) {
|
||||
$args[] = $param->getDefaultValue();
|
||||
} else {
|
||||
$missing[] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($missing)) {
|
||||
throw new HttpException(400, Yii::t('yii', 'Missing required parameters: {params}', array(
|
||||
'{params}' => implode(', ', $missing),
|
||||
)));
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a URL using the given route and parameters.
|
||||
*
|
||||
|
||||
90
framework/yii/web/VerbFilter.php
Normal file
90
framework/yii/web/VerbFilter.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\web;
|
||||
|
||||
use Yii;
|
||||
use yii\base\ActionEvent;
|
||||
use yii\base\Behavior;
|
||||
use yii\base\HttpException;
|
||||
|
||||
/**
|
||||
* VerbFilter is an action filter that filters by HTTP request methods.
|
||||
*
|
||||
* It allows to define allowed HTTP request methods for each action and will throw
|
||||
* an HTTP 405 error when the method is not allowed.
|
||||
*
|
||||
* To use VerbFilter, declare it in the `behaviors()` method of your controller class.
|
||||
* For example, the following declarations will define a typical set of allowed
|
||||
* request methods for REST CRUD actions.
|
||||
*
|
||||
* ~~~
|
||||
* public function behaviors()
|
||||
* {
|
||||
* return array(
|
||||
* 'verbs' => array(
|
||||
* 'class' => \yii\web\VerbFilter::className(),
|
||||
* 'actions' => array(
|
||||
* 'index' => array('get'),
|
||||
* 'view' => array('get'),
|
||||
* 'create' => array('get', 'post'),
|
||||
* 'update' => array('get', 'put', 'post'),
|
||||
* 'delete' => array('post', 'delete'),
|
||||
* ),
|
||||
* ),
|
||||
* );
|
||||
* }
|
||||
* ~~~
|
||||
*
|
||||
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.7
|
||||
* @author Carsten Brandt <mail@cebe.cc>
|
||||
* @since 2.0
|
||||
*/
|
||||
class VerbFilter extends Behavior
|
||||
{
|
||||
/**
|
||||
* @var array this property defines the allowed request methods for each action.
|
||||
* For each action that should only support limited set of request methods
|
||||
* you add an entry with the action id as array key and an array of
|
||||
* allowed methods (e.g. GET, HEAD, PUT) as the value.
|
||||
* If an action is not listed all request methods are considered allowed.
|
||||
*/
|
||||
public $actions = array();
|
||||
|
||||
|
||||
/**
|
||||
* Declares event handlers for the [[owner]]'s events.
|
||||
* @return array events (array keys) and the corresponding event handler methods (array values).
|
||||
*/
|
||||
public function events()
|
||||
{
|
||||
return array(
|
||||
Controller::EVENT_BEFORE_ACTION => 'beforeAction',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ActionEvent $event
|
||||
* @return boolean
|
||||
* @throws \yii\base\HttpException when the request method is not allowed.
|
||||
*/
|
||||
public function beforeAction($event)
|
||||
{
|
||||
$action = $event->action->id;
|
||||
if (isset($this->actions[$action])) {
|
||||
$verb = Yii::$app->getRequest()->getRequestMethod();
|
||||
$allowed = array_map('strtoupper', $this->actions[$action]);
|
||||
if (!in_array($verb, $allowed)) {
|
||||
$event->isValid = false;
|
||||
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.7
|
||||
header('Allow: ' . implode(', ', $allowed));
|
||||
throw new HttpException(405, 'Method Not Allowed. This url can only handle the following request methods: ' . implode(', ', $allowed));
|
||||
}
|
||||
}
|
||||
return $event->isValid;
|
||||
}
|
||||
}
|
||||
@@ -134,8 +134,8 @@ class ActiveForm extends Widget
|
||||
$id = $this->options['id'];
|
||||
$options = Json::encode($this->getClientOptions());
|
||||
$attributes = Json::encode($this->attributes);
|
||||
$this->view->registerAssetBundle('yii/form');
|
||||
$this->view->registerJs("jQuery('#$id').yiiActiveForm($attributes, $options);");
|
||||
$this->getView()->registerAssetBundle('yii/form');
|
||||
$this->getView()->registerJs("jQuery('#$id').yiiActiveForm($attributes, $options);");
|
||||
}
|
||||
echo Html::endForm();
|
||||
}
|
||||
|
||||
64
framework/yii/widgets/InputWidget.php
Normal file
64
framework/yii/widgets/InputWidget.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\widgets;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Widget;
|
||||
use yii\base\Model;
|
||||
use yii\base\InvalidConfigException;
|
||||
|
||||
/**
|
||||
* InputWidget is the base class for widgets that collect user inputs.
|
||||
*
|
||||
* An input widget can be associated with a data model and an attribute,
|
||||
* or a name and a value. If the former, the name and the value will
|
||||
* be generated automatically.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class InputWidget extends Widget
|
||||
{
|
||||
/**
|
||||
* @var Model the data model that this widget is associated with.
|
||||
*/
|
||||
public $model;
|
||||
/**
|
||||
* @var string the model attribute that this widget is associated with.
|
||||
*/
|
||||
public $attribute;
|
||||
/**
|
||||
* @var string the input name. This must be set if [[model]] and [[attribute]] are not set.
|
||||
*/
|
||||
public $name;
|
||||
/**
|
||||
* @var string the input value.
|
||||
*/
|
||||
public $value;
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the widget.
|
||||
* If you override this method, make sure you call the parent implementation first.
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
if (!$this->hasModel() && $this->name === null) {
|
||||
throw new InvalidConfigException("Either 'name' or 'model' and 'attribute' properties must be specified.");
|
||||
}
|
||||
parent::init();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean whether this widget is associated with a data model.
|
||||
*/
|
||||
protected function hasModel()
|
||||
{
|
||||
return $this->model instanceof Model && $this->attribute !== null;
|
||||
}
|
||||
}
|
||||
136
framework/yii/widgets/MaskedInput.php
Normal file
136
framework/yii/widgets/MaskedInput.php
Normal file
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\widgets;
|
||||
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\helpers\Html;
|
||||
use yii\helpers\Json;
|
||||
use yii\web\JsExpression;
|
||||
|
||||
/**
|
||||
* MaskedInput generates a masked text input.
|
||||
*
|
||||
* MaskedInput is similar to [[Html::textInput()]] except that
|
||||
* an input mask will be used to force users to enter properly formatted data,
|
||||
* such as phone numbers, social security numbers.
|
||||
*
|
||||
* To use MaskedInput, you must set the [[mask]] property. The following example
|
||||
* shows how to use MaskedInput to collect phone numbers:
|
||||
*
|
||||
* ~~~
|
||||
* echo MaskedInput::widget(array(
|
||||
* 'name' => 'phone',
|
||||
* 'mask' => '999-999-9999',
|
||||
* ));
|
||||
* ~~~
|
||||
*
|
||||
* The masked text field is implemented based on the [jQuery masked input plugin](http://digitalbush.com/projects/masked-input-plugin).
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class MaskedInput extends InputWidget
|
||||
{
|
||||
/**
|
||||
* @var string the input mask (e.g. '99/99/9999' for date input). The following characters are predefined:
|
||||
*
|
||||
* - `a`: represents an alpha character (A-Z,a-z)
|
||||
* - `9`: represents a numeric character (0-9)
|
||||
* - `*`: represents an alphanumeric character (A-Z,a-z,0-9)
|
||||
* - `?`: anything listed after '?' within the mask is considered optional user input
|
||||
*
|
||||
* Additional characters can be defined by specifying the [[charMap]] property.
|
||||
*/
|
||||
public $mask;
|
||||
/**
|
||||
* @var array the mapping between mask characters and the corresponding patterns.
|
||||
* For example, `array('~' => '[+-]')` specifies that the '~' character expects '+' or '-' input.
|
||||
* Defaults to null, meaning using the map as described in [[mask]].
|
||||
*/
|
||||
public $charMap;
|
||||
/**
|
||||
* @var string the character prompting for user input. Defaults to underscore '_'.
|
||||
*/
|
||||
public $placeholder;
|
||||
/**
|
||||
* @var string a JavaScript function callback that will be invoked when user finishes the input.
|
||||
*/
|
||||
public $completed;
|
||||
/**
|
||||
* @var array the HTML attributes for the input tag.
|
||||
*/
|
||||
public $options = array();
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the widget.
|
||||
* @throws InvalidConfigException if the "mask" property is not set.
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
if (empty($this->mask)) {
|
||||
throw new InvalidConfigException('The "mask" property must be set.');
|
||||
}
|
||||
|
||||
if (!isset($this->options['id'])) {
|
||||
$this->options['id'] = $this->hasModel() ? Html::getInputId($this->model, $this->attribute) : $this->getId();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the widget.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
if ($this->hasModel()) {
|
||||
echo Html::activeTextInput($this->model, $this->attribute, $this->options);
|
||||
} else {
|
||||
echo Html::textInput($this->name, $this->value, $this->options);
|
||||
}
|
||||
$this->registerClientScript();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the needed JavaScript.
|
||||
*/
|
||||
public function registerClientScript()
|
||||
{
|
||||
$options = $this->getClientOptions();
|
||||
$options = empty($options) ? '' : ',' . Json::encode($options);
|
||||
$js = '';
|
||||
if (is_array($this->charMap) && !empty($this->charMap)) {
|
||||
$js .= 'jQuery.mask.definitions=' . Json::encode($this->charMap) . ";\n";
|
||||
}
|
||||
$id = $this->options['id'];
|
||||
$js .= "jQuery(\"#{$id}\").mask(\"{$this->mask}\"{$options});";
|
||||
$this->getView()->registerAssetBundle('yii/maskedinput');
|
||||
$this->getView()->registerJs($js);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array the options for the text field
|
||||
*/
|
||||
protected function getClientOptions()
|
||||
{
|
||||
$options = array();
|
||||
if ($this->placeholder !== null) {
|
||||
$options['placeholder'] = $this->placeholder;
|
||||
}
|
||||
|
||||
if ($this->completed !== null) {
|
||||
if ($this->completed instanceof JsExpression) {
|
||||
$options['completed'] = $this->completed;
|
||||
} else {
|
||||
$options['completed'] = new JsExpression($this->completed);
|
||||
}
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user