Alexander Makarov
12 years ago
77 changed files with 5801 additions and 3766 deletions
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env php |
||||
<?php |
||||
/** |
||||
* build script file. |
||||
* |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
|
||||
// fcgi doesn't have STDIN defined by default |
||||
defined('STDIN') or define('STDIN', fopen('php://stdin', 'r')); |
||||
|
||||
require(__DIR__ . '/../framework/yii.php'); |
||||
|
||||
$id = 'yiic-build'; |
||||
$basePath = __DIR__; |
||||
|
||||
$application = new yii\console\Application($id, $basePath); |
||||
$application->run(); |
@ -0,0 +1,23 @@
|
||||
@echo off |
||||
|
||||
rem ------------------------------------------------------------- |
||||
rem build script for Windows. |
||||
rem |
||||
rem This is the bootstrap script for running build on Windows. |
||||
rem |
||||
rem @author Qiang Xue <qiang.xue@gmail.com> |
||||
rem @link http://www.yiiframework.com/ |
||||
rem @copyright 2008 Yii Software LLC |
||||
rem @license http://www.yiiframework.com/license/ |
||||
rem @version $Id$ |
||||
rem ------------------------------------------------------------- |
||||
|
||||
@setlocal |
||||
|
||||
set BUILD_PATH=%~dp0 |
||||
|
||||
if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe |
||||
|
||||
%PHP_COMMAND% "%BUILD_PATH%build" %* |
||||
|
||||
@endlocal |
@ -0,0 +1,276 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!-- |
||||
/** |
||||
* Phing build file for Yii. |
||||
* |
||||
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright 2008-2009 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
--> |
||||
<project name="yii" basedir="." default="help"> |
||||
<!-- task definitions --> |
||||
<taskdef name="yii-init-build" classname="YiiInitTask" classpath="tasks" /> |
||||
<!-- |
||||
<taskdef name="yii-pear" classname="YiiPearTask" classpath="tasks"/> |
||||
--> |
||||
|
||||
<!-- init yii.version, yii.revision and yii.winbuild --> |
||||
<yii-init-build /> |
||||
|
||||
<!-- these are required external commands --> |
||||
<property name="php" value="php" /> <!-- PHP parser --> |
||||
<property name="hhc" value="hhc" /> <!-- compile phpdoc into CHM --> |
||||
<property name="pdflatex" value="pdflatex" /> <!-- generates PDF from LaTex --> |
||||
|
||||
<property name="pkgname" value="${phing.project.name}-${yii.version}.${yii.revision}"/> |
||||
<property name="docname" value="${phing.project.name}-docs-${yii.version}.${yii.revision}"/> |
||||
<property name="pearname" value="${phing.project.name}-${yii.release}.tgz" /> |
||||
|
||||
<!-- directory definitions --> |
||||
<property name="build.base.dir" value="release"/> |
||||
<property name="build.dist.dir" value="${build.base.dir}/dist"/> |
||||
<property name="build.src.dir" value="${build.base.dir}/${pkgname}"/> |
||||
<property name="build.pear.src.dir" value="${build.src.dir}/framework" /> |
||||
<property name="build.doc.dir" value="${build.base.dir}/${docname}"/> |
||||
<property name="build.web.dir" value="${build.base.dir}/web"/> |
||||
|
||||
<tstamp> |
||||
<format property="DATE" pattern="%b %e %Y" /> |
||||
</tstamp> |
||||
|
||||
<if> |
||||
<equals arg1="${yii.winbuild}" arg2="true"/> |
||||
<then> |
||||
<property name="build" value="build"/> |
||||
</then> |
||||
<else> |
||||
<property name="build" value="php build"/> |
||||
</else> |
||||
</if> |
||||
|
||||
<!-- source files in the framework --> |
||||
<fileset dir=".." id="framework"> |
||||
<exclude name="**/.gitignore"/> |
||||
<exclude name="**/*.bak"/> |
||||
<exclude name="**/*~"/> |
||||
<include name="framework/**/*"/> |
||||
<include name="requirements/**/*"/> |
||||
<include name="demos/**/*"/> |
||||
<include name="CHANGELOG"/> |
||||
<include name="UPGRADE"/> |
||||
<include name="LICENSE"/> |
||||
<include name="README"/> |
||||
</fileset> |
||||
|
||||
<!-- doc files --> |
||||
<fileset dir="../docs" id="docs"> |
||||
<exclude name="**/.gitignore"/> |
||||
<exclude name="**/*.bak"/> |
||||
<exclude name="**/*~"/> |
||||
<include name="guide/**/*"/> |
||||
<include name="blog/**/*"/> |
||||
</fileset> |
||||
|
||||
<fileset dir="../docs/guide" id="docs-guide"> |
||||
<exclude name="**/.gitignore"/> |
||||
<exclude name="**/*.bak"/> |
||||
<exclude name="**/*~"/> |
||||
<include name="**/*"/> |
||||
</fileset> |
||||
|
||||
<fileset dir="../docs/blog" id="docs-blog"> |
||||
<exclude name="**/.gitignore"/> |
||||
<exclude name="**/*.bak"/> |
||||
<exclude name="**/*~"/> |
||||
<include name="**/*"/> |
||||
</fileset> |
||||
|
||||
<fileset dir="." id="writables"> |
||||
<include name="${build.src.dir}/**/runtime" /> |
||||
<include name="${build.src.dir}/**/assets" /> |
||||
<include name="${build.src.dir}/demos/**/data" /> |
||||
</fileset> |
||||
|
||||
<fileset dir="." id="executables"> |
||||
<include name="${build.src.dir}/**/yiic" /> |
||||
</fileset> |
||||
|
||||
<target name="src" depends="sync"> |
||||
<echo>Building package ${pkgname}...</echo> |
||||
<echo>Copying files to build directory...</echo> |
||||
<copy todir="${build.src.dir}"> |
||||
<fileset refid="framework"/> |
||||
</copy> |
||||
|
||||
<echo>Changing file permissions...</echo> |
||||
<chmod mode="0777"> |
||||
<fileset refid="writables" /> |
||||
</chmod> |
||||
<chmod mode="0755"> |
||||
<fileset refid="executables" /> |
||||
</chmod> |
||||
|
||||
<echo>Generating source release file...</echo> |
||||
<mkdir dir="${build.dist.dir}" /> |
||||
<if> |
||||
<equals arg1="${yii.winbuild}" arg2="true"/> |
||||
<then> |
||||
<tar destfile="${build.dist.dir}/${pkgname}.tar.gz" compression="gzip"> |
||||
<fileset dir="${build.base.dir}"> |
||||
<include name="${pkgname}/**/*"/> |
||||
</fileset> |
||||
</tar> |
||||
</then> |
||||
<else> |
||||
<exec command="tar czpf ${pkgname}.tar.gz ${pkgname}" dir="${build.base.dir}"/> |
||||
<move file="${build.base.dir}/${pkgname}.tar.gz" todir="${build.dist.dir}" /> |
||||
</else> |
||||
</if> |
||||
<zip destfile="${build.dist.dir}/${pkgname}.zip"> |
||||
<fileset dir="${build.base.dir}"> |
||||
<include name="${pkgname}/**/*"/> |
||||
</fileset> |
||||
</zip> |
||||
</target> |
||||
|
||||
<target name="doc" depends="sync"> |
||||
<echo>Building documentation...</echo> |
||||
|
||||
<echo>Building Guide PDF...</echo> |
||||
<exec command="${build} guideLatex" dir="." passthru="true" /> |
||||
<exec command="${pdflatex} guide.tex -interaction=nonstopmode -max-print-line=120" dir="commands/guide" passthru="true"/> |
||||
<exec command="${pdflatex} guide.tex -interaction=nonstopmode -max-print-line=120" dir="commands/guide" passthru="true"/> |
||||
<exec command="${pdflatex} guide.tex -interaction=nonstopmode -max-print-line=120" dir="commands/guide" passthru="true"/> |
||||
<move file="commands/guide/guide.pdf" tofile="${build.doc.dir}/yii-guide-${yii.version}.pdf" /> |
||||
|
||||
<echo>Building Blog PDF...</echo> |
||||
<exec command="${build} blogLatex" dir="." passthru="true" /> |
||||
<exec command="${pdflatex} blog.tex -interaction=nonstopmode -max-print-line=120" dir="commands/blog" passthru="true"/> |
||||
<exec command="${pdflatex} blog.tex -interaction=nonstopmode -max-print-line=120" dir="commands/blog" passthru="true"/> |
||||
<exec command="${pdflatex} blog.tex -interaction=nonstopmode -max-print-line=120" dir="commands/blog" passthru="true"/> |
||||
<move file="commands/blog/blog.pdf" tofile="${build.doc.dir}/yii-blog-${yii.version}.pdf" /> |
||||
|
||||
<echo>Building API...</echo> |
||||
<exec command="${build} api ${build.doc.dir}" dir="." passthru="true" /> |
||||
|
||||
<!-- |
||||
<echo>Building API CHM...</echo> |
||||
<exec command="${hhc} ${build.doc.dir}/api/manual.hhp" /> |
||||
<move file="${build.doc.dir}/api/manual.chm" tofile="${build.doc.dir}/yii-api-${yii.version}.chm" /> |
||||
<delete> |
||||
<fileset dir="${build.doc.dir}/api"> |
||||
<include name="manual.*" /> |
||||
</fileset> |
||||
</delete> |
||||
--> |
||||
|
||||
<echo>Generating doc release file...</echo> |
||||
<mkdir dir="${build.dist.dir}" /> |
||||
<tar destfile="${build.dist.dir}/${docname}.tar.gz" compression="gzip"> |
||||
<fileset dir="${build.base.dir}"> |
||||
<include name="${docname}/**/*"/> |
||||
</fileset> |
||||
</tar> |
||||
<zip destfile="${build.dist.dir}/${docname}.zip"> |
||||
<fileset dir="${build.base.dir}"> |
||||
<include name="${docname}/**/*"/> |
||||
</fileset> |
||||
</zip> |
||||
</target> |
||||
|
||||
<target name="web" depends="sync"> |
||||
|
||||
<echo>Building online API...</echo> |
||||
<mkdir dir="${build.web.dir}/common/data/${yii.version}" /> |
||||
<exec command="${build} api ${build.web.dir}/common/data/${yii.version} online" dir="." passthru="true" /> |
||||
|
||||
<echo>Copying tutorials...</echo> |
||||
<copy todir="${build.web.dir}/common/data/${yii.version}/tutorials/guide"> |
||||
<fileset refid="docs-guide"/> |
||||
</copy> |
||||
<copy todir="${build.web.dir}/common/data/${yii.version}/tutorials/blog"> |
||||
<fileset refid="docs-blog"/> |
||||
</copy> |
||||
|
||||
<echo>Copying release text files...</echo> |
||||
<mkdir dir="${build.web.dir}/frontend/www/files" /> |
||||
<copy file="../CHANGELOG" tofile="${build.web.dir}/frontend/www/files/CHANGELOG-${yii.version}.txt" /> |
||||
<copy file="../UPGRADE" tofile="${build.web.dir}/frontend/www/files/UPGRADE-${yii.version}.txt" /> |
||||
|
||||
<echo> |
||||
|
||||
Finished building Web files. |
||||
Please update yiisite/common/data/versions.php file with the following code: |
||||
|
||||
'1.1'=>array( |
||||
'version'=>'${yii.version}', |
||||
'revision'=>'${yii.revision}', |
||||
'date'=>'${yii.date}', |
||||
'latest'=>true, |
||||
), |
||||
|
||||
</echo> |
||||
</target> |
||||
|
||||
<target name="sync"> |
||||
<echo>Synchronizing code changes for ${pkgname}...</echo> |
||||
|
||||
<echo>Building autoload map...</echo> |
||||
<exec command="${build} autoload" dir="." passthru="true"/> |
||||
|
||||
<echo>Building yiilite.php...</echo> |
||||
<exec command="${build} lite" dir="." passthru="true"/> |
||||
</target> |
||||
|
||||
<target name="message"> |
||||
<echo>Extracting i18n messages...</echo> |
||||
<exec command="${build} message ../framework/messages/config.php" dir="." passthru="true"/> |
||||
</target> |
||||
|
||||
<!-- |
||||
<target name="pear" depends="clean,build"> |
||||
<echo>Generating pear package for ${phing.project.name}-${yii.release}</echo> |
||||
<mkdir dir="${build.dist.dir}" /> |
||||
<yii-pear pkgdir="${build.pear.src.dir}" |
||||
channel="pear.php.net" |
||||
version="${yii.release}" |
||||
state="stable" |
||||
category="framework" |
||||
package="${phing.project.name}" |
||||
summary="Yii PHP Framework" |
||||
pkgdescription="Yii PHP Framework: Best for Web 2.0 Development" |
||||
notes="http://www.yiiframework.com/files/CHANGELOG-${yii.release}.txt" |
||||
license="BSD" |
||||
/> |
||||
<exec command="pear package" dir="${build.pear.src.dir}" passthru="true" /> |
||||
<move file="${build.pear.src.dir}/${pearname}" tofile="${build.dist.dir}/${pearname}" /> |
||||
</target> |
||||
--> |
||||
|
||||
<target name="clean"> |
||||
<echo>Cleaning up the build...</echo> |
||||
<delete dir="${build.base.dir}"/> |
||||
</target> |
||||
|
||||
<target name="help"> |
||||
<echo> |
||||
|
||||
Welcome to use Yii build script! |
||||
-------------------------------- |
||||
You may use the following command format to build a target: |
||||
|
||||
phing <target name> |
||||
|
||||
where <target name> can be one of the following: |
||||
|
||||
- sync : synchronize yiilite.php and YiiBase.php |
||||
- message : extract i18n messages of the framework |
||||
- src : build source release |
||||
- doc : build documentation release (Windows only) |
||||
- clean : clean up the build |
||||
|
||||
</echo> |
||||
</target> |
||||
</project> |
@ -0,0 +1,112 @@
|
||||
<?php |
||||
/** |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
|
||||
use yii\console\Controller; |
||||
use yii\helpers\FileHelper; |
||||
|
||||
/** |
||||
* http://www.unicode.org/cldr/charts/supplemental/language_plural_rules.html |
||||
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
* @since 2.0 |
||||
*/ |
||||
class LocaleController extends Controller |
||||
{ |
||||
public $defaultAction = 'plural'; |
||||
|
||||
/** |
||||
* Generates the plural rules data. |
||||
* |
||||
* This command will parse the plural rule XML file from CLDR and convert them |
||||
* into appropriate PHP representation to support Yii message translation feature. |
||||
* @param string $xmlFile the original plural rule XML file (from CLDR). This file may be found in |
||||
* http://www.unicode.org/Public/cldr/latest/core.zip |
||||
* Extract the zip file and locate the file "common/supplemental/plurals.xml". |
||||
* @throws Exception |
||||
*/ |
||||
public function actionPlural($xmlFile) |
||||
{ |
||||
if (!is_file($xmlFile)) { |
||||
throw new Exception("The source plural rule file does not exist: $xmlFile"); |
||||
} |
||||
|
||||
$xml = simplexml_load_file($xmlFile); |
||||
|
||||
$allRules = array(); |
||||
|
||||
$patterns = array( |
||||
'/n in 0..1/' => '(n==0||n==1)', |
||||
'/\s+is\s+not\s+/i' => '!=', //is not |
||||
'/\s+is\s+/i' => '==', //is |
||||
'/n\s+mod\s+(\d+)/i' => 'fmod(n,$1)', //mod (CLDR's "mod" is "fmod()", not "%") |
||||
'/^(.*?)\s+not\s+in\s+(\d+)\.\.(\d+)/i' => '!in_array($1,range($2,$3))', //not in |
||||
'/^(.*?)\s+in\s+(\d+)\.\.(\d+)/i' => 'in_array($1,range($2,$3))', //in |
||||
'/^(.*?)\s+not\s+within\s+(\d+)\.\.(\d+)/i' => '($1<$2||$1>$3)', //not within |
||||
'/^(.*?)\s+within\s+(\d+)\.\.(\d+)/i' => '($1>=$2&&$1<=$3)', //within |
||||
); |
||||
foreach ($xml->plurals->pluralRules as $node) { |
||||
$attributes = $node->attributes(); |
||||
$locales = explode(' ', $attributes['locales']); |
||||
$rules = array(); |
||||
|
||||
if (!empty($node->pluralRule)) { |
||||
foreach ($node->pluralRule as $rule) { |
||||
$expr_or = preg_split('/\s+or\s+/i', $rule); |
||||
foreach ($expr_or as $key_or => $val_or) { |
||||
$expr_and = preg_split('/\s+and\s+/i', $val_or); |
||||
$expr_and = preg_replace(array_keys($patterns), array_values($patterns), $expr_and); |
||||
$expr_or[$key_or] = implode('&&', $expr_and); |
||||
} |
||||
$expr = preg_replace('/\\bn\\b/', '$n', implode('||', $expr_or)); |
||||
$rules[] = preg_replace_callback('/range\((\d+),(\d+)\)/', function ($matches) { |
||||
if ($matches[2] - $matches[1] <= 5) { |
||||
return 'array(' . implode(',', range($matches[1], $matches[2])) . ')'; |
||||
} else { |
||||
return $matches[0]; |
||||
} |
||||
}, $expr); |
||||
|
||||
} |
||||
foreach ($locales as $locale) { |
||||
$allRules[$locale] = $rules; |
||||
} |
||||
} |
||||
} |
||||
// hard fix for "br": the rule is too complex |
||||
$allRules['br'] = array( |
||||
0 => 'fmod($n,10)==1&&!in_array(fmod($n,100),array(11,71,91))', |
||||
1 => 'fmod($n,10)==2&&!in_array(fmod($n,100),array(12,72,92))', |
||||
2 => 'in_array(fmod($n,10),array(3,4,9))&&!in_array(fmod($n,100),array_merge(range(10,19),range(70,79),range(90,99)))', |
||||
3 => 'fmod($n,1000000)==0&&$n!=0', |
||||
); |
||||
if (preg_match('/\d+/', $xml->version['number'], $matches)) { |
||||
$revision = $matches[0]; |
||||
} else { |
||||
$revision = -1; |
||||
} |
||||
|
||||
echo "<?php\n";
|
||||
echo <<<EOD |
||||
/** |
||||
* Plural rules. |
||||
* |
||||
* This file is automatically generated by the "yiic locale/plural" command under the "build" folder. |
||||
* Do not modify it directly. |
||||
* |
||||
* The original plural rule data used for generating this file has the following copyright terms: |
||||
* |
||||
* Copyright © 1991-2007 Unicode, Inc. All rights reserved. |
||||
* Distributed under the Terms of Use in http://www.unicode.org/copyright.html. |
||||
* |
||||
* @revision $revision (of the original plural file) |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
EOD; |
||||
echo "\nreturn " . var_export($allRules, true) . ';'; |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,23 @@
|
||||
<?php |
||||
/** |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
|
||||
namespace yii\db; |
||||
|
||||
/** |
||||
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
* @since 2.0 |
||||
*/ |
||||
class StaleObjectException extends Exception |
||||
{ |
||||
/** |
||||
* @return string the user-friendly name of this exception |
||||
*/ |
||||
public function getName() |
||||
{ |
||||
return \Yii::t('yii|Stale Object Exception'); |
||||
} |
||||
} |
@ -0,0 +1,627 @@
|
||||
<?php |
||||
/** |
||||
* Plural rules. |
||||
* |
||||
* This file is automatically generated by the "yiic locale/plural" command under the "build" folder. |
||||
* Do not modify it directly. |
||||
* |
||||
* The original plural rule data used for generating this file has the following copyright terms: |
||||
* |
||||
* Copyright © 1991-2007 Unicode, Inc. All rights reserved. |
||||
* Distributed under the Terms of Use in http://www.unicode.org/copyright.html. |
||||
* |
||||
* @revision 6008 (of the original plural file) |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
return array ( |
||||
'ar' => |
||||
array ( |
||||
0 => '$n==0', |
||||
1 => '$n==1', |
||||
2 => '$n==2', |
||||
3 => 'in_array(fmod($n,100),range(3,10))', |
||||
4 => 'in_array(fmod($n,100),range(11,99))', |
||||
), |
||||
'asa' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'af' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'bem' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'bez' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'bg' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'bn' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'brx' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'ca' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'cgg' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'chr' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'da' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'de' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'dv' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'ee' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'el' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'en' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'eo' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'es' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'et' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'eu' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'fi' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'fo' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'fur' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'fy' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'gl' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'gsw' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'gu' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'ha' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'haw' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'he' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'is' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'it' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'jmc' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'kaj' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'kcg' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'kk' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'kl' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'ksb' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'ku' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'lb' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'lg' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'mas' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'ml' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'mn' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'mr' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'nah' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'nb' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'nd' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'ne' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'nl' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'nn' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'no' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'nr' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'ny' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'nyn' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'om' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'or' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'pa' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'pap' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'ps' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'pt' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'rof' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'rm' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'rwk' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'saq' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'seh' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'sn' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'so' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'sq' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'ss' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'ssy' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'st' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'sv' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'sw' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'syr' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'ta' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'te' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'teo' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'tig' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'tk' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'tn' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'ts' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'ur' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'wae' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
've' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'vun' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'xh' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'xog' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'zu' => |
||||
array ( |
||||
0 => '$n==1', |
||||
), |
||||
'ak' => |
||||
array ( |
||||
0 => '($n==0||$n==1)', |
||||
), |
||||
'am' => |
||||
array ( |
||||
0 => '($n==0||$n==1)', |
||||
), |
||||
'bh' => |
||||
array ( |
||||
0 => '($n==0||$n==1)', |
||||
), |
||||
'fil' => |
||||
array ( |
||||
0 => '($n==0||$n==1)', |
||||
), |
||||
'tl' => |
||||
array ( |
||||
0 => '($n==0||$n==1)', |
||||
), |
||||
'guw' => |
||||
array ( |
||||
0 => '($n==0||$n==1)', |
||||
), |
||||
'hi' => |
||||
array ( |
||||
0 => '($n==0||$n==1)', |
||||
), |
||||
'ln' => |
||||
array ( |
||||
0 => '($n==0||$n==1)', |
||||
), |
||||
'mg' => |
||||
array ( |
||||
0 => '($n==0||$n==1)', |
||||
), |
||||
'nso' => |
||||
array ( |
||||
0 => '($n==0||$n==1)', |
||||
), |
||||
'ti' => |
||||
array ( |
||||
0 => '($n==0||$n==1)', |
||||
), |
||||
'wa' => |
||||
array ( |
||||
0 => '($n==0||$n==1)', |
||||
), |
||||
'ff' => |
||||
array ( |
||||
0 => '($n>=0&&$n<=2)&&$n!=2', |
||||
), |
||||
'fr' => |
||||
array ( |
||||
0 => '($n>=0&&$n<=2)&&$n!=2', |
||||
), |
||||
'kab' => |
||||
array ( |
||||
0 => '($n>=0&&$n<=2)&&$n!=2', |
||||
), |
||||
'lv' => |
||||
array ( |
||||
0 => '$n==0', |
||||
1 => 'fmod($n,10)==1&&fmod($n,100)!=11', |
||||
), |
||||
'iu' => |
||||
array ( |
||||
0 => '$n==1', |
||||
1 => '$n==2', |
||||
), |
||||
'kw' => |
||||
array ( |
||||
0 => '$n==1', |
||||
1 => '$n==2', |
||||
), |
||||
'naq' => |
||||
array ( |
||||
0 => '$n==1', |
||||
1 => '$n==2', |
||||
), |
||||
'se' => |
||||
array ( |
||||
0 => '$n==1', |
||||
1 => '$n==2', |
||||
), |
||||
'sma' => |
||||
array ( |
||||
0 => '$n==1', |
||||
1 => '$n==2', |
||||
), |
||||
'smi' => |
||||
array ( |
||||
0 => '$n==1', |
||||
1 => '$n==2', |
||||
), |
||||
'smj' => |
||||
array ( |
||||
0 => '$n==1', |
||||
1 => '$n==2', |
||||
), |
||||
'smn' => |
||||
array ( |
||||
0 => '$n==1', |
||||
1 => '$n==2', |
||||
), |
||||
'sms' => |
||||
array ( |
||||
0 => '$n==1', |
||||
1 => '$n==2', |
||||
), |
||||
'ga' => |
||||
array ( |
||||
0 => '$n==1', |
||||
1 => '$n==2', |
||||
2 => 'in_array($n,array(3,4,5,6))', |
||||
3 => 'in_array($n,array(7,8,9,10))', |
||||
), |
||||
'ro' => |
||||
array ( |
||||
0 => '$n==1', |
||||
1 => '$n==0||$n!=1&&in_array(fmod($n,100),range(1,19))', |
||||
), |
||||
'mo' => |
||||
array ( |
||||
0 => '$n==1', |
||||
1 => '$n==0||$n!=1&&in_array(fmod($n,100),range(1,19))', |
||||
), |
||||
'lt' => |
||||
array ( |
||||
0 => 'fmod($n,10)==1&&!in_array(fmod($n,100),range(11,19))', |
||||
1 => 'in_array(fmod($n,10),range(2,9))&&!in_array(fmod($n,100),range(11,19))', |
||||
), |
||||
'be' => |
||||
array ( |
||||
0 => 'fmod($n,10)==1&&fmod($n,100)!=11', |
||||
1 => 'in_array(fmod($n,10),array(2,3,4))&&!in_array(fmod($n,100),array(12,13,14))', |
||||
2 => 'fmod($n,10)==0||in_array(fmod($n,10),array(5,6,7,8,9))||in_array(fmod($n,100),array(11,12,13,14))', |
||||
), |
||||
'bs' => |
||||
array ( |
||||
0 => 'fmod($n,10)==1&&fmod($n,100)!=11', |
||||
1 => 'in_array(fmod($n,10),array(2,3,4))&&!in_array(fmod($n,100),array(12,13,14))', |
||||
2 => 'fmod($n,10)==0||in_array(fmod($n,10),array(5,6,7,8,9))||in_array(fmod($n,100),array(11,12,13,14))', |
||||
), |
||||
'hr' => |
||||
array ( |
||||
0 => 'fmod($n,10)==1&&fmod($n,100)!=11', |
||||
1 => 'in_array(fmod($n,10),array(2,3,4))&&!in_array(fmod($n,100),array(12,13,14))', |
||||
2 => 'fmod($n,10)==0||in_array(fmod($n,10),array(5,6,7,8,9))||in_array(fmod($n,100),array(11,12,13,14))', |
||||
), |
||||
'ru' => |
||||
array ( |
||||
0 => 'fmod($n,10)==1&&fmod($n,100)!=11', |
||||
1 => 'in_array(fmod($n,10),array(2,3,4))&&!in_array(fmod($n,100),array(12,13,14))', |
||||
2 => 'fmod($n,10)==0||in_array(fmod($n,10),array(5,6,7,8,9))||in_array(fmod($n,100),array(11,12,13,14))', |
||||
), |
||||
'sh' => |
||||
array ( |
||||
0 => 'fmod($n,10)==1&&fmod($n,100)!=11', |
||||
1 => 'in_array(fmod($n,10),array(2,3,4))&&!in_array(fmod($n,100),array(12,13,14))', |
||||
2 => 'fmod($n,10)==0||in_array(fmod($n,10),array(5,6,7,8,9))||in_array(fmod($n,100),array(11,12,13,14))', |
||||
), |
||||
'sr' => |
||||
array ( |
||||
0 => 'fmod($n,10)==1&&fmod($n,100)!=11', |
||||
1 => 'in_array(fmod($n,10),array(2,3,4))&&!in_array(fmod($n,100),array(12,13,14))', |
||||
2 => 'fmod($n,10)==0||in_array(fmod($n,10),array(5,6,7,8,9))||in_array(fmod($n,100),array(11,12,13,14))', |
||||
), |
||||
'uk' => |
||||
array ( |
||||
0 => 'fmod($n,10)==1&&fmod($n,100)!=11', |
||||
1 => 'in_array(fmod($n,10),array(2,3,4))&&!in_array(fmod($n,100),array(12,13,14))', |
||||
2 => 'fmod($n,10)==0||in_array(fmod($n,10),array(5,6,7,8,9))||in_array(fmod($n,100),array(11,12,13,14))', |
||||
), |
||||
'cs' => |
||||
array ( |
||||
0 => '$n==1', |
||||
1 => 'in_array($n,array(2,3,4))', |
||||
), |
||||
'sk' => |
||||
array ( |
||||
0 => '$n==1', |
||||
1 => 'in_array($n,array(2,3,4))', |
||||
), |
||||
'pl' => |
||||
array ( |
||||
0 => '$n==1', |
||||
1 => 'in_array(fmod($n,10),array(2,3,4))&&!in_array(fmod($n,100),array(12,13,14))', |
||||
2 => '$n!=1&&in_array(fmod($n,10),array(0,1))||in_array(fmod($n,10),array(5,6,7,8,9))||in_array(fmod($n,100),array(12,13,14))', |
||||
), |
||||
'sl' => |
||||
array ( |
||||
0 => 'fmod($n,100)==1', |
||||
1 => 'fmod($n,100)==2', |
||||
2 => 'in_array(fmod($n,100),array(3,4))', |
||||
), |
||||
'mt' => |
||||
array ( |
||||
0 => '$n==1', |
||||
1 => '$n==0||in_array(fmod($n,100),range(2,10))', |
||||
2 => 'in_array(fmod($n,100),range(11,19))', |
||||
), |
||||
'mk' => |
||||
array ( |
||||
0 => 'fmod($n,10)==1&&$n!=11', |
||||
), |
||||
'cy' => |
||||
array ( |
||||
0 => '$n==0', |
||||
1 => '$n==1', |
||||
2 => '$n==2', |
||||
3 => '$n==3', |
||||
4 => '$n==6', |
||||
), |
||||
'lag' => |
||||
array ( |
||||
0 => '$n==0', |
||||
1 => '($n>=0&&$n<=2)&&$n!=0&&$n!=2', |
||||
), |
||||
'shi' => |
||||
array ( |
||||
0 => '($n>=0&&$n<=1)', |
||||
1 => 'in_array($n,range(2,10))', |
||||
), |
||||
'br' => |
||||
array ( |
||||
0 => 'fmod($n,10)==1&&!in_array(fmod($n,100),array(11,71,91))', |
||||
1 => 'fmod($n,10)==2&&!in_array(fmod($n,100),array(12,72,92))', |
||||
2 => 'in_array(fmod($n,10),array(3,4,9))&&!in_array(fmod($n,100),array_merge(range(10,19),range(70,79),range(90,99)))', |
||||
3 => 'fmod($n,1000000)==0&&$n!=0', |
||||
), |
||||
'ksh' => |
||||
array ( |
||||
0 => '$n==0', |
||||
1 => '$n==1', |
||||
), |
||||
'tzm' => |
||||
array ( |
||||
0 => '($n==0||$n==1)||in_array($n,range(11,99))', |
||||
), |
||||
'gv' => |
||||
array ( |
||||
0 => 'in_array(fmod($n,10),array(1,2))||fmod($n,20)==0', |
||||
), |
||||
); |
@ -0,0 +1,109 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?> |
||||
<!DOCTYPE supplementalData SYSTEM "../../common/dtd/ldmlSupplemental.dtd"> |
||||
<supplementalData> |
||||
<version number="$Revision: 6008 $"/> |
||||
<generation date="$Date: 2011-07-12 13:18:01 -0500 (Tue, 12 Jul 2011) $"/> |
||||
<plurals> |
||||
<!-- if locale is known to have no plurals, there are no rules --> |
||||
<pluralRules locales="az bm bo dz fa id ig ii hu ja jv ka kde kea km kn ko lo ms my sah ses sg th to tr vi wo yo zh"/> |
||||
<pluralRules locales="ar"> |
||||
<pluralRule count="zero">n is 0</pluralRule> |
||||
<pluralRule count="one">n is 1</pluralRule> |
||||
<pluralRule count="two">n is 2</pluralRule> |
||||
<pluralRule count="few">n mod 100 in 3..10</pluralRule> |
||||
<pluralRule count="many">n mod 100 in 11..99</pluralRule> |
||||
</pluralRules> |
||||
<pluralRules locales="asa af bem bez bg bn brx ca cgg chr da de dv ee el en eo es et eu fi fo fur fy gl gsw gu ha haw he is it jmc kaj kcg kk kl ksb ku lb lg mas ml mn mr nah nb nd ne nl nn no nr ny nyn om or pa pap ps pt rof rm rwk saq seh sn so sq ss ssy st sv sw syr ta te teo tig tk tn ts ur wae ve vun xh xog zu"> |
||||
<pluralRule count="one">n is 1</pluralRule> |
||||
</pluralRules> |
||||
<pluralRules locales="ak am bh fil tl guw hi ln mg nso ti wa"> |
||||
<pluralRule count="one">n in 0..1</pluralRule> |
||||
</pluralRules> |
||||
<pluralRules locales="ff fr kab"> |
||||
<pluralRule count="one">n within 0..2 and n is not 2</pluralRule> |
||||
</pluralRules> |
||||
<pluralRules locales="lv"> |
||||
<pluralRule count="zero">n is 0</pluralRule> |
||||
<pluralRule count="one">n mod 10 is 1 and n mod 100 is not 11</pluralRule> |
||||
</pluralRules> |
||||
<pluralRules locales="iu kw naq se sma smi smj smn sms"> |
||||
<pluralRule count="one">n is 1</pluralRule> |
||||
<pluralRule count="two">n is 2</pluralRule> |
||||
</pluralRules> |
||||
<pluralRules locales="ga"> <!-- http://unicode.org/cldr/trac/ticket/3915 --> |
||||
<pluralRule count="one">n is 1</pluralRule> |
||||
<pluralRule count="two">n is 2</pluralRule> |
||||
<pluralRule count="few">n in 3..6</pluralRule> |
||||
<pluralRule count="many">n in 7..10</pluralRule> |
||||
</pluralRules> |
||||
<pluralRules locales="ro mo"> |
||||
<pluralRule count="one">n is 1</pluralRule> |
||||
<pluralRule count="few">n is 0 OR n is not 1 AND n mod 100 in 1..19</pluralRule> |
||||
</pluralRules> |
||||
<pluralRules locales="lt"> |
||||
<pluralRule count="one">n mod 10 is 1 and n mod 100 not in 11..19</pluralRule> |
||||
<pluralRule count="few">n mod 10 in 2..9 and n mod 100 not in 11..19</pluralRule> |
||||
</pluralRules> |
||||
<pluralRules locales="be bs hr ru sh sr uk"> |
||||
<pluralRule count="one">n mod 10 is 1 and n mod 100 is not 11</pluralRule> |
||||
<pluralRule count="few">n mod 10 in 2..4 and n mod 100 not in 12..14</pluralRule> |
||||
<pluralRule count="many">n mod 10 is 0 or n mod 10 in 5..9 or n mod 100 in 11..14</pluralRule> |
||||
<!-- others are fractions --> |
||||
</pluralRules> |
||||
<pluralRules locales="cs sk"> |
||||
<pluralRule count="one">n is 1</pluralRule> |
||||
<pluralRule count="few">n in 2..4</pluralRule> |
||||
</pluralRules> |
||||
<pluralRules locales="pl"> |
||||
<pluralRule count="one">n is 1</pluralRule> |
||||
<pluralRule count="few">n mod 10 in 2..4 and n mod 100 not in 12..14</pluralRule> |
||||
<pluralRule count="many">n is not 1 and n mod 10 in 0..1 or n mod 10 in 5..9 or n mod 100 in 12..14</pluralRule> |
||||
<!-- others are fractions --> |
||||
<!-- and n mod 100 not in 22..24 from Tamplin --> |
||||
</pluralRules> |
||||
<pluralRules locales="sl"> |
||||
<pluralRule count="one">n mod 100 is 1</pluralRule> |
||||
<pluralRule count="two">n mod 100 is 2</pluralRule> |
||||
<pluralRule count="few">n mod 100 in 3..4</pluralRule> |
||||
</pluralRules> |
||||
<pluralRules locales="mt"> <!-- from Tamplin's data --> |
||||
<pluralRule count="one">n is 1</pluralRule> |
||||
<pluralRule count="few">n is 0 or n mod 100 in 2..10</pluralRule> |
||||
<pluralRule count="many">n mod 100 in 11..19</pluralRule> |
||||
</pluralRules> |
||||
<pluralRules locales="mk"> <!-- from Tamplin's data --> |
||||
<pluralRule count="one">n mod 10 is 1 and n is not 11</pluralRule> |
||||
</pluralRules> |
||||
<pluralRules locales="cy"> <!-- from http://www.saltcymru.org/wordpress/?p=99&lang=en --> |
||||
<pluralRule count="zero">n is 0</pluralRule> |
||||
<pluralRule count="one">n is 1</pluralRule> |
||||
<pluralRule count="two">n is 2</pluralRule> |
||||
<pluralRule count="few">n is 3</pluralRule> |
||||
<pluralRule count="many">n is 6</pluralRule> |
||||
</pluralRules> |
||||
<pluralRules locales="lag"> |
||||
<pluralRule count="zero">n is 0</pluralRule> |
||||
<pluralRule count="one">n within 0..2 and n is not 0 and n is not 2</pluralRule> |
||||
</pluralRules> |
||||
<pluralRules locales="shi"> |
||||
<pluralRule count="one">n within 0..1</pluralRule> |
||||
<pluralRule count="few">n in 2..10</pluralRule> |
||||
</pluralRules> |
||||
<pluralRules locales="br"> <!-- from http://unicode.org/cldr/trac/ticket/2886 --> |
||||
<pluralRule count="one">n mod 10 is 1 and n mod 100 not in 11,71,91</pluralRule> |
||||
<pluralRule count="two">n mod 10 is 2 and n mod 100 not in 12,72,92</pluralRule> |
||||
<pluralRule count="few">n mod 10 in 3..4,9 and n mod 100 not in 10..19,70..79,90..99</pluralRule> |
||||
<pluralRule count="many">n mod 1000000 is 0 and n is not 0</pluralRule> |
||||
</pluralRules> |
||||
<pluralRules locales="ksh"> |
||||
<pluralRule count="zero">n is 0</pluralRule> |
||||
<pluralRule count="one">n is 1</pluralRule> |
||||
</pluralRules> |
||||
<pluralRules locales="tzm"> |
||||
<pluralRule count="one">n in 0..1 or n in 11..99</pluralRule> |
||||
</pluralRules> |
||||
<pluralRules locales="gv"> |
||||
<pluralRule count="one">n mod 10 in 1..2 or n mod 20 is 0</pluralRule> |
||||
</pluralRules> |
||||
</plurals> |
||||
</supplementalData> |
@ -0,0 +1,104 @@
|
||||
<?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\Action; |
||||
use yii\base\ActionFilter; |
||||
use yii\base\HttpException; |
||||
|
||||
/** |
||||
* |
||||
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
* @since 2.0 |
||||
*/ |
||||
class AccessControl extends ActionFilter |
||||
{ |
||||
/** |
||||
* @var callback a callback that will be called if the access should be denied |
||||
* to the current user. If not set, [[denyAccess()]] will be called. |
||||
* |
||||
* The signature of the callback should be as follows: |
||||
* |
||||
* ~~~ |
||||
* function ($rule, $action) |
||||
* ~~~ |
||||
* |
||||
* where `$rule` is this rule, and `$action` is the current [[Action|action]] object. |
||||
*/ |
||||
public $denyCallback; |
||||
/** |
||||
* @var string the default class of the access rules. This is used when |
||||
* a rule is configured without specifying a class in [[rules]]. |
||||
*/ |
||||
public $defaultRuleClass = 'yii\web\AccessRule'; |
||||
/** |
||||
* @var array a list of access rule objects or configurations for creating the rule objects. |
||||
*/ |
||||
public $rules = array(); |
||||
|
||||
/** |
||||
* Initializes the [[rules]] array by instantiating rule objects from configurations. |
||||
*/ |
||||
public function init() |
||||
{ |
||||
parent::init(); |
||||
foreach ($this->rules as $i => $rule) { |
||||
if (is_array($rule)) { |
||||
if (!isset($rule['class'])) { |
||||
$rule['class'] = $this->defaultRuleClass; |
||||
} |
||||
$this->rules[$i] = Yii::createObject($rule); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* This method is invoked right before an action is to be executed (after all possible filters.) |
||||
* You may override this method to do last-minute preparation for the action. |
||||
* @param Action $action the action to be executed. |
||||
* @return boolean whether the action should continue to be executed. |
||||
*/ |
||||
public function beforeAction($action) |
||||
{ |
||||
$user = Yii::$app->getUser(); |
||||
$request = Yii::$app->getRequest(); |
||||
/** @var $rule AccessRule */ |
||||
foreach ($this->rules as $rule) { |
||||
if ($allow = $rule->allows($action, $user, $request)) { |
||||
break; |
||||
} elseif ($allow === false) { |
||||
if (isset($rule->denyCallback)) { |
||||
call_user_func($rule->denyCallback, $rule); |
||||
} elseif (isset($this->denyCallback)) { |
||||
call_user_func($this->denyCallback, $rule); |
||||
} else { |
||||
$this->denyAccess($user); |
||||
} |
||||
return false; |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Denies the access of the user. |
||||
* The default implementation will redirect the user to the login page if he is a guest; |
||||
* if the user is already logged, a 403 HTTP exception will be thrown. |
||||
* @param User $user the current user |
||||
* @throws HttpException if the user is already logged in. |
||||
*/ |
||||
protected function denyAccess($user) |
||||
{ |
||||
if ($user->getIsGuest()) { |
||||
$user->loginRequired(); |
||||
} else { |
||||
throw new HttpException(403, Yii::t('yii|You are not allowed to perform this action.')); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,188 @@
|
||||
<?php |
||||
/** |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
|
||||
namespace yii\web; |
||||
|
||||
use yii\base\Component; |
||||
use yii\base\Action; |
||||
use yii\base\Controller; |
||||
use yii\web\User; |
||||
use yii\web\Request; |
||||
|
||||
/** |
||||
* |
||||
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
* @since 2.0 |
||||
*/ |
||||
class AccessRule extends Component |
||||
{ |
||||
/** |
||||
* @var boolean whether this is an 'allow' rule or 'deny' rule. |
||||
*/ |
||||
public $allow; |
||||
/** |
||||
* @var array list of action IDs that this rule applies to. The comparison is case-sensitive. |
||||
* If not set or empty, it means this rule applies to all actions. |
||||
*/ |
||||
public $actions; |
||||
/** |
||||
* @var array list of controller IDs that this rule applies to. The comparison is case-sensitive. |
||||
* If not set or empty, it means this rule applies to all controllers. |
||||
*/ |
||||
public $controllers; |
||||
/** |
||||
* @var array list of roles that this rule applies to. Two special roles are recognized, and |
||||
* they are checked via [[User::isGuest]]: |
||||
* |
||||
* - `?`: matches a guest user (not authenticated yet) |
||||
* - `@`: matches an authenticated user |
||||
* |
||||
* Using additional role names requires RBAC (Role-Based Access Control), and |
||||
* [[User::hasAccess()]] will be called. |
||||
* |
||||
* If this property is not set or empty, it means this rule applies to all roles. |
||||
*/ |
||||
public $roles; |
||||
/** |
||||
* @var array list of user IP addresses that this rule applies to. An IP address |
||||
* can contain the wildcard `*` at the end so that it matches IP addresses with the same prefix. |
||||
* For example, '192.168.*' matches all IP addresses in the segment '192.168.'. |
||||
* If not set or empty, it means this rule applies to all IP addresses. |
||||
* @see Request::userIP |
||||
*/ |
||||
public $ips; |
||||
/** |
||||
* @var array list of request methods (e.g. `GET`, `POST`) that this rule applies to. |
||||
* The request methods must be specified in uppercase. |
||||
* If not set or empty, it means this rule applies to all request methods. |
||||
* @see Request::requestMethod |
||||
*/ |
||||
public $verbs; |
||||
/** |
||||
* @var callback a callback that will be called to determine if the rule should be applied. |
||||
* The signature of the callback should be as follows: |
||||
* |
||||
* ~~~ |
||||
* function ($rule, $action) |
||||
* ~~~ |
||||
* |
||||
* where `$rule` is this rule, and `$action` is the current [[Action|action]] object. |
||||
* The callback should return a boolean value indicating whether this rule should be applied. |
||||
*/ |
||||
public $matchCallback; |
||||
/** |
||||
* @var callback a callback that will be called if this rule determines the access to |
||||
* the current action should be denied. If not set, the behavior will be determined by |
||||
* [[AccessControl]]. |
||||
* |
||||
* The signature of the callback should be as follows: |
||||
* |
||||
* ~~~ |
||||
* function ($rule, $action) |
||||
* ~~~ |
||||
* |
||||
* where `$rule` is this rule, and `$action` is the current [[Action|action]] object. |
||||
*/ |
||||
public $denyCallback; |
||||
|
||||
|
||||
/** |
||||
* Checks whether the Web user is allowed to perform the specified action. |
||||
* @param Action $action the action to be performed |
||||
* @param User $user the user object |
||||
* @param Request $request |
||||
* @return boolean|null true if the user is allowed, false if the user is denied, null if the rule does not apply to the user |
||||
*/ |
||||
public function allows($action, $user, $request) |
||||
{ |
||||
if ($this->matchAction($action) |
||||
&& $this->matchRole($user) |
||||
&& $this->matchIP($request->getUserIP()) |
||||
&& $this->matchVerb($request->getRequestMethod()) |
||||
&& $this->matchController($action->controller) |
||||
&& $this->matchCustom($action) |
||||
) { |
||||
return $this->allow ? true : false; |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @param Action $action the action |
||||
* @return boolean whether the rule applies to the action |
||||
*/ |
||||
protected function matchAction($action) |
||||
{ |
||||
return empty($this->actions) || in_array($action->id, $this->actions, true); |
||||
} |
||||
|
||||
/** |
||||
* @param Controller $controller the controller |
||||
* @return boolean whether the rule applies to the controller |
||||
*/ |
||||
protected function matchController($controller) |
||||
{ |
||||
return empty($this->controllers) || in_array($controller->id, $this->controllers, true); |
||||
} |
||||
|
||||
/** |
||||
* @param User $user the user object |
||||
* @return boolean whether the rule applies to the role |
||||
*/ |
||||
protected function matchRole($user) |
||||
{ |
||||
if (empty($this->roles)) { |
||||
return true; |
||||
} |
||||
foreach ($this->roles as $role) { |
||||
if ($role === '?' && $user->getIsGuest()) { |
||||
return true; |
||||
} elseif ($role === '@' && !$user->getIsGuest()) { |
||||
return true; |
||||
} elseif ($user->hasAccess($role)) { |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* @param string $ip the IP address |
||||
* @return boolean whether the rule applies to the IP address |
||||
*/ |
||||
protected function matchIP($ip) |
||||
{ |
||||
if (empty($this->ips)) { |
||||
return true; |
||||
} |
||||
foreach ($this->ips as $rule) { |
||||
if ($rule === '*' || $rule === $ip || (($pos = strpos($rule, '*')) !== false && !strncmp($ip, $rule, $pos))) { |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* @param string $verb the request method |
||||
* @return boolean whether the rule applies to the request |
||||
*/ |
||||
protected function matchVerb($verb) |
||||
{ |
||||
return empty($this->verbs) || in_array($verb, $this->verbs, true); |
||||
} |
||||
|
||||
/** |
||||
* @param Action $action the action to be performed |
||||
* @return boolean whether the rule should be applied |
||||
*/ |
||||
protected function matchCustom($action) |
||||
{ |
||||
return empty($this->matchCallback) || call_user_func($this->matchCallback, $this, $action); |
||||
} |
||||
} |
@ -0,0 +1,131 @@
|
||||
<?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\ActionFilter; |
||||
use yii\base\Action; |
||||
|
||||
/** |
||||
* @author Da:Sourcerer <webmaster@dasourcerer.net> |
||||
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
* @since 2.0 |
||||
*/ |
||||
class HttpCache extends ActionFilter |
||||
{ |
||||
/** |
||||
* @var callback a PHP callback that returns the UNIX timestamp of the last modification time. |
||||
* The callback's signature should be: |
||||
* |
||||
* ~~~ |
||||
* function ($action, $params) |
||||
* ~~~ |
||||
* |
||||
* where `$action` is the [[Action]] object that this filter is currently handling; |
||||
* `$params` takes the value of [[params]]. The callback should return a UNIX timestamp. |
||||
*/ |
||||
public $lastModified; |
||||
/** |
||||
* @var callback a PHP callback that generates the Etag seed string. |
||||
* The callback's signature should be: |
||||
* |
||||
* ~~~ |
||||
* function ($action, $params) |
||||
* ~~~ |
||||
* |
||||
* where `$action` is the [[Action]] object that this filter is currently handling; |
||||
* `$params` takes the value of [[params]]. The callback should return a string serving |
||||
* as the seed for generating an Etag. |
||||
*/ |
||||
public $etagSeed; |
||||
/** |
||||
* @var mixed additional parameters that should be passed to the [[lastModified]] and [[etagSeed]] callbacks. |
||||
*/ |
||||
public $params; |
||||
/** |
||||
* @var string HTTP cache control header. If null, the header will not be sent. |
||||
*/ |
||||
public $cacheControlHeader = 'Cache-Control: max-age=3600, public'; |
||||
|
||||
/** |
||||
* This method is invoked right before an action is to be executed (after all possible filters.) |
||||
* You may override this method to do last-minute preparation for the action. |
||||
* @param Action $action the action to be executed. |
||||
* @return boolean whether the action should continue to be executed. |
||||
*/ |
||||
public function beforeAction($action) |
||||
{ |
||||
$verb = Yii::$app->request->getRequestMethod(); |
||||
if ($verb !== 'GET' && $verb !== 'HEAD' || $this->lastModified === null && $this->etagSeed === null) { |
||||
return true; |
||||
} |
||||
|
||||
$lastModified = $etag = null; |
||||
if ($this->lastModified !== null) { |
||||
$lastModified = call_user_func($this->lastModified, $action, $this->params); |
||||
} |
||||
if ($this->etagSeed !== null) { |
||||
$seed = call_user_func($this->etagSeed, $action, $this->params); |
||||
$etag = $this->generateEtag($seed); |
||||
} |
||||
|
||||
$this->sendCacheControlHeader(); |
||||
if ($etag !== null) { |
||||
header("ETag: $etag"); |
||||
} |
||||
|
||||
if ($this->validateCache($lastModified, $etag)) { |
||||
header('HTTP/1.1 304 Not Modified'); |
||||
return false; |
||||
} |
||||
|
||||
if ($lastModified !== null) { |
||||
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastModified) . ' GMT'); |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Validates if the HTTP cache contains valid content. |
||||
* @param integer $lastModified the calculated Last-Modified value in terms of a UNIX timestamp. |
||||
* If null, the Last-Modified header will not be validated. |
||||
* @param string $etag the calculated ETag value. If null, the ETag header will not be validated. |
||||
* @return boolean whether the HTTP cache is still valid. |
||||
*/ |
||||
protected function validateCache($lastModified, $etag) |
||||
{ |
||||
if ($lastModified !== null && (!isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) || @strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) < $lastModified)) { |
||||
return false; |
||||
} else { |
||||
return $etag === null || isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] === $etag; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Sends the cache control header to the client |
||||
* @see cacheControl |
||||
*/ |
||||
protected function sendCacheControlHeader() |
||||
{ |
||||
session_cache_limiter('public'); |
||||
header('Pragma:', true); |
||||
if ($this->cacheControlHeader !== null) { |
||||
header($this->cacheControlHeader, true); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Generates an Etag from the given seed string. |
||||
* @param string $seed Seed for the ETag |
||||
* @return string the generated Etag |
||||
*/ |
||||
protected function generateEtag($seed) |
||||
{ |
||||
return '"' . base64_encode(sha1($seed, true)) . '"'; |
||||
} |
||||
} |
@ -0,0 +1,81 @@
|
||||
<?php |
||||
/** |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
|
||||
namespace yii\web; |
||||
|
||||
/** |
||||
* Identity is the interface that should be implemented by a class providing identity information. |
||||
* |
||||
* This interface can typically be implemented by a user model class. For example, the following |
||||
* code shows how to implement this interface by a User ActiveRecord class: |
||||
* |
||||
* ~~~ |
||||
* class User extends ActiveRecord implements Identity |
||||
* { |
||||
* public static function findIdentity($id) |
||||
* { |
||||
* return static::find($id); |
||||
* } |
||||
* |
||||
* public function getId() |
||||
* { |
||||
* return $this->id; |
||||
* } |
||||
* |
||||
* public function getAuthKey() |
||||
* { |
||||
* return $this->authKey; |
||||
* } |
||||
* |
||||
* public function validateAuthKey($authKey) |
||||
* { |
||||
* return $this->authKey === $authKey; |
||||
* } |
||||
* } |
||||
* ~~~ |
||||
* |
||||
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
* @since 2.0 |
||||
*/ |
||||
interface Identity |
||||
{ |
||||
/** |
||||
* Finds an identity by the given ID. |
||||
* @param string|integer $id the ID to be looked for |
||||
* @return Identity the identity object that matches the given ID. |
||||
* Null should be returned if such an identity cannot be found |
||||
* or the identity is not in an active state (disabled, deleted, etc.) |
||||
*/ |
||||
public static function findIdentity($id); |
||||
/** |
||||
* Returns an ID that can uniquely identify a user identity. |
||||
* @return string|integer an ID that uniquely identifies a user identity. |
||||
*/ |
||||
public function getId(); |
||||
/** |
||||
* Returns a key that can be used to check the validity of a given identity ID. |
||||
* |
||||
* The key should be unique for each individual user, and should be persistent |
||||
* so that it can be used to check the validity of the user identity. |
||||
* |
||||
* The space of such keys should be big enough to defeat potential identity attacks. |
||||
* |
||||
* This is required if [[User::enableAutoLogin]] is enabled. |
||||
* @return string a key that is used to check the validity of a given identity ID. |
||||
* @see validateAuthKey() |
||||
*/ |
||||
public function getAuthKey(); |
||||
/** |
||||
* Validates the given auth key. |
||||
* |
||||
* This is required if [[User::enableAutoLogin]] is enabled. |
||||
* @param string $authKey the given auth key |
||||
* @return boolean whether the given auth key is valid. |
||||
* @see getAuthKey() |
||||
*/ |
||||
public function validateAuthKey($authKey); |
||||
} |
@ -1,110 +1,104 @@
|
||||
<?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\ActionFilter; |
||||
use yii\base\Action; |
||||
use yii\base\View; |
||||
use yii\caching\Dependency; |
||||
|
||||
/** |
||||
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
* @since 2.0 |
||||
*/ |
||||
class PageCache extends ActionFilter |
||||
{ |
||||
/** |
||||
* @var boolean whether the content being cached should be differentiated according to the route. |
||||
* A route consists of the requested controller ID and action ID. Defaults to true. |
||||
*/ |
||||
public $varyByRoute = true; |
||||
/** |
||||
* @var View the view object that is used to create the fragment cache widget to implement page caching. |
||||
* If not set, the view registered with the application will be used. |
||||
*/ |
||||
public $view; |
||||
|
||||
/** |
||||
* @var string the ID of the cache application component. Defaults to 'cache' (the primary cache application component.) |
||||
*/ |
||||
public $cacheID = 'cache'; |
||||
/** |
||||
* @var integer number of seconds that the data can remain valid in cache. |
||||
* Use 0 to indicate that the cached data will never expire. |
||||
*/ |
||||
public $duration = 60; |
||||
/** |
||||
* @var array|Dependency the dependency that the cached content depends on. |
||||
* This can be either a [[Dependency]] object or a configuration array for creating the dependency object. |
||||
* For example, |
||||
* |
||||
* ~~~ |
||||
* array( |
||||
* 'class' => 'yii\caching\DbDependency', |
||||
* 'sql' => 'SELECT MAX(lastModified) FROM Post', |
||||
* ) |
||||
* ~~~ |
||||
* |
||||
* would make the output cache depends on the last modified time of all posts. |
||||
* If any post has its modification time changed, the cached content would be invalidated. |
||||
*/ |
||||
public $dependency; |
||||
/** |
||||
* @var array list of factors that would cause the variation of the content being cached. |
||||
* Each factor is a string representing a variation (e.g. the language, a GET parameter). |
||||
* The following variation setting will cause the content to be cached in different versions |
||||
* according to the current application language: |
||||
* |
||||
* ~~~ |
||||
* array( |
||||
* Yii::$app->language, |
||||
* ) |
||||
*/ |
||||
public $variations; |
||||
/** |
||||
* @var boolean whether to enable the fragment cache. You may use this property to turn on and off |
||||
* the fragment cache according to specific setting (e.g. enable fragment cache only for GET requests). |
||||
*/ |
||||
public $enabled = true; |
||||
|
||||
|
||||
public function init() |
||||
{ |
||||
parent::init(); |
||||
if ($this->view === null) { |
||||
$this->view = Yii::$app->getView(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* This method is invoked right before an action is to be executed (after all possible filters.) |
||||
* You may override this method to do last-minute preparation for the action. |
||||
* @param Action $action the action to be executed. |
||||
* @return boolean whether the action should continue to be executed. |
||||
*/ |
||||
public function beforeAction($action) |
||||
{ |
||||
$properties = array(); |
||||
foreach (array('cacheID', 'duration', 'dependency', 'variations', 'enabled') as $name) { |
||||
$properties[$name] = $this->$name; |
||||
} |
||||
$id = $this->varyByRoute ? $action->getUniqueId() : __CLASS__; |
||||
return $this->view->beginCache($id, $properties); |
||||
} |
||||
|
||||
/** |
||||
* This method is invoked right after an action is executed. |
||||
* You may override this method to do some postprocessing for the action. |
||||
* @param Action $action the action just executed. |
||||
*/ |
||||
public function afterAction($action) |
||||
{ |
||||
$this->view->endCache(); |
||||
} |
||||
<?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\ActionFilter; |
||||
use yii\base\Action; |
||||
use yii\base\View; |
||||
use yii\caching\Dependency; |
||||
|
||||
/** |
||||
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
* @since 2.0 |
||||
*/ |
||||
class PageCache extends ActionFilter |
||||
{ |
||||
/** |
||||
* @var boolean whether the content being cached should be differentiated according to the route. |
||||
* A route consists of the requested controller ID and action ID. Defaults to true. |
||||
*/ |
||||
public $varyByRoute = true; |
||||
/** |
||||
* @var string the application component ID of the [[\yii\caching\Cache|cache]] object. |
||||
*/ |
||||
public $cache = 'cache'; |
||||
/** |
||||
* @var integer number of seconds that the data can remain valid in cache. |
||||
* Use 0 to indicate that the cached data will never expire. |
||||
*/ |
||||
public $duration = 60; |
||||
/** |
||||
* @var array|Dependency the dependency that the cached content depends on. |
||||
* This can be either a [[Dependency]] object or a configuration array for creating the dependency object. |
||||
* For example, |
||||
* |
||||
* ~~~ |
||||
* array( |
||||
* 'class' => 'yii\caching\DbDependency', |
||||
* 'sql' => 'SELECT MAX(lastModified) FROM Post', |
||||
* ) |
||||
* ~~~ |
||||
* |
||||
* would make the output cache depends on the last modified time of all posts. |
||||
* If any post has its modification time changed, the cached content would be invalidated. |
||||
*/ |
||||
public $dependency; |
||||
/** |
||||
* @var array list of factors that would cause the variation of the content being cached. |
||||
* Each factor is a string representing a variation (e.g. the language, a GET parameter). |
||||
* The following variation setting will cause the content to be cached in different versions |
||||
* according to the current application language: |
||||
* |
||||
* ~~~ |
||||
* array( |
||||
* Yii::$app->language, |
||||
* ) |
||||
*/ |
||||
public $variations; |
||||
/** |
||||
* @var boolean whether to enable the fragment cache. You may use this property to turn on and off |
||||
* the fragment cache according to specific setting (e.g. enable fragment cache only for GET requests). |
||||
*/ |
||||
public $enabled = true; |
||||
|
||||
|
||||
public function init() |
||||
{ |
||||
parent::init(); |
||||
if ($this->view === null) { |
||||
$this->view = Yii::$app->getView(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* This method is invoked right before an action is to be executed (after all possible filters.) |
||||
* You may override this method to do last-minute preparation for the action. |
||||
* @param Action $action the action to be executed. |
||||
* @return boolean whether the action should continue to be executed. |
||||
*/ |
||||
public function beforeAction($action) |
||||
{ |
||||
$properties = array(); |
||||
foreach (array('cache', 'duration', 'dependency', 'variations', 'enabled') as $name) { |
||||
$properties[$name] = $this->$name; |
||||
} |
||||
$id = $this->varyByRoute ? $action->getUniqueId() : __CLASS__; |
||||
return $this->view->beginCache($id, $properties); |
||||
} |
||||
|
||||
/** |
||||
* This method is invoked right after an action is executed. |
||||
* You may override this method to do some postprocessing for the action. |
||||
* @param Action $action the action just executed. |
||||
*/ |
||||
public function afterAction($action) |
||||
{ |
||||
$this->view->endCache(); |
||||
} |
||||
} |
@ -0,0 +1,34 @@
|
||||
<?php |
||||
/** |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
|
||||
namespace yii\web; |
||||
|
||||
use yii\base\Event; |
||||
|
||||
/** |
||||
* |
||||
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
* @since 2.0 |
||||
*/ |
||||
class UserEvent extends Event |
||||
{ |
||||
/** |
||||
* @var Identity the identity object associated with this event |
||||
*/ |
||||
public $identity; |
||||
/** |
||||
* @var boolean whether the login is cookie-based. This property is only meaningful |
||||
* for [[User::EVENT_BEFORE_LOGIN]] and [[User::EVENT_AFTER_LOGIN]] events. |
||||
*/ |
||||
public $cookieBased; |
||||
/** |
||||
* @var boolean whether the login or logout should proceed. |
||||
* Event handlers may modify this property to determine whether the login or logout should proceed. |
||||
* This property is only meaningful for [[User::EVENT_BEFORE_LOGIN]] and [[User::EVENT_BEFORE_LOGOUT]] events. |
||||
*/ |
||||
public $isValid = true; |
||||
} |
@ -1,213 +1,174 @@
|
||||
<?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\InvalidConfigException; |
||||
use yii\base\Widget; |
||||
use yii\caching\Cache; |
||||
use yii\caching\Dependency; |
||||
|
||||
/** |
||||
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
* @since 2.0 |
||||
*/ |
||||
class FragmentCache extends Widget |
||||
{ |
||||
/** |
||||
* @var string the ID of the cache application component. Defaults to 'cache' (the primary cache application component.) |
||||
*/ |
||||
public $cacheID = 'cache'; |
||||
/** |
||||
* @var integer number of seconds that the data can remain valid in cache. |
||||
* Use 0 to indicate that the cached data will never expire. |
||||
*/ |
||||
public $duration = 60; |
||||
/** |
||||
* @var array|Dependency the dependency that the cached content depends on. |
||||
* This can be either a [[Dependency]] object or a configuration array for creating the dependency object. |
||||
* For example, |
||||
* |
||||
* ~~~ |
||||
* array( |
||||
* 'class' => 'yii\caching\DbDependency', |
||||
* 'sql' => 'SELECT MAX(lastModified) FROM Post', |
||||
* ) |
||||
* ~~~ |
||||
* |
||||
* would make the output cache depends on the last modified time of all posts. |
||||
* If any post has its modification time changed, the cached content would be invalidated. |
||||
*/ |
||||
public $dependency; |
||||
/** |
||||
* @var array list of factors that would cause the variation of the content being cached. |
||||
* Each factor is a string representing a variation (e.g. the language, a GET parameter). |
||||
* The following variation setting will cause the content to be cached in different versions |
||||
* according to the current application language: |
||||
* |
||||
* ~~~ |
||||
* array( |
||||
* Yii::$app->language, |
||||
* ) |
||||
*/ |
||||
public $variations; |
||||
/** |
||||
* @var boolean whether to enable the fragment cache. You may use this property to turn on and off |
||||
* the fragment cache according to specific setting (e.g. enable fragment cache only for GET requests). |
||||
*/ |
||||
public $enabled = true; |
||||
/** |
||||
* @var \yii\base\View the view object within which this widget is used. If not set, |
||||
* the view registered with the application will be used. This is mainly used by dynamic content feature. |
||||
*/ |
||||
public $view; |
||||
/** |
||||
* @var array a list of placeholders for embedding dynamic contents. This property |
||||
* is used internally to implement the content caching feature. Do not modify it. |
||||
*/ |
||||
public $dynamicPlaceholders; |
||||
|
||||
|
||||
/** |
||||
* Marks the start of content to be cached. |
||||
* Content displayed after this method call and before {@link endCache()} |
||||
* will be captured and saved in cache. |
||||
* This method does nothing if valid content is already found in cache. |
||||
*/ |
||||
public function init() |
||||
{ |
||||
if ($this->view === null) { |
||||
$this->view = Yii::$app->getView(); |
||||
} |
||||
if ($this->getCache() !== null && $this->getCachedContent() === false) { |
||||
$this->view->cacheStack[] = $this; |
||||
ob_start(); |
||||
ob_implicit_flush(false); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Marks the end of content to be cached. |
||||
* Content displayed before this method call and after {@link init()} |
||||
* will be captured and saved in cache. |
||||
* This method does nothing if valid content is already found in cache. |
||||
*/ |
||||
public function run() |
||||
{ |
||||
if (($content = $this->getCachedContent()) !== false) { |
||||
echo $content; |
||||
} elseif (($cache = $this->getCache()) !== null) { |
||||
$content = ob_get_clean(); |
||||
array_pop($this->view->cacheStack); |
||||
if (is_array($this->dependency)) { |
||||
$this->dependency = Yii::createObject($this->dependency); |
||||
} |
||||
$data = array($content, $this->dynamicPlaceholders); |
||||
$cache->set($this->calculateKey(), $data, $this->duration, $this->dependency); |
||||
|
||||
if ($this->view->cacheStack === array() && !empty($this->dynamicPlaceholders)) { |
||||
$content = $this->updateDynamicContent($content, $this->dynamicPlaceholders); |
||||
} |
||||
echo $content; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @var string|boolean the cached content. False if the content is not cached. |
||||
*/ |
||||
private $_content; |
||||
|
||||
/** |
||||
* Returns the cached content if available. |
||||
* @return string|boolean the cached content. False is returned if valid content is not found in the cache. |
||||
*/ |
||||
public function getCachedContent() |
||||
{ |
||||
if ($this->_content === null) { |
||||
$this->_content = false; |
||||
if (($cache = $this->getCache()) !== null) { |
||||
$key = $this->calculateKey(); |
||||
$data = $cache->get($key); |
||||
if (is_array($data) && count($data) === 2) { |
||||
list ($content, $placeholders) = $data; |
||||
if (is_array($placeholders) && count($placeholders) > 0) { |
||||
if ($this->view->cacheStack === array()) { |
||||
// outermost cache: replace placeholder with dynamic content |
||||
$content = $this->updateDynamicContent($content, $placeholders); |
||||
} |
||||
foreach ($placeholders as $name => $statements) { |
||||
$this->view->addDynamicPlaceholder($name, $statements); |
||||
} |
||||
} |
||||
$this->_content = $content; |
||||
} |
||||
} |
||||
} |
||||
return $this->_content; |
||||
} |
||||
|
||||
protected function updateDynamicContent($content, $placeholders) |
||||
{ |
||||
foreach ($placeholders as $name => $statements) { |
||||
$placeholders[$name] = $this->view->evaluateDynamicContent($statements); |
||||
} |
||||
return strtr($content, $placeholders); |
||||
} |
||||
|
||||
/** |
||||
* Generates a unique key used for storing the content in cache. |
||||
* The key generated depends on both [[id]] and [[variations]]. |
||||
* @return string a valid cache key |
||||
*/ |
||||
protected function calculateKey() |
||||
{ |
||||
$factors = array(__CLASS__, $this->getId()); |
||||
if (is_array($this->variations)) { |
||||
foreach ($this->variations as $factor) { |
||||
$factors[] = $factor; |
||||
} |
||||
} |
||||
return $this->getCache()->buildKey($factors); |
||||
} |
||||
|
||||
/** |
||||
* @var Cache |
||||
*/ |
||||
private $_cache; |
||||
|
||||
/** |
||||
* Returns the cache instance used for storing content. |
||||
* @return Cache the cache instance. Null is returned if the cache component is not available |
||||
* or [[enabled]] is false. |
||||
* @throws InvalidConfigException if [[cacheID]] does not point to a valid application component. |
||||
*/ |
||||
public function getCache() |
||||
{ |
||||
if (!$this->enabled) { |
||||
return null; |
||||
} |
||||
if ($this->_cache === null) { |
||||
$cache = Yii::$app->getComponent($this->cacheID); |
||||
if ($cache instanceof Cache) { |
||||
$this->_cache = $cache; |
||||
} else { |
||||
throw new InvalidConfigException('FragmentCache::cacheID must refer to the ID of a cache application component.'); |
||||
} |
||||
} |
||||
return $this->_cache; |
||||
} |
||||
|
||||
/** |
||||
* Sets the cache instance used by the session component. |
||||
* @param Cache $value the cache instance |
||||
*/ |
||||
public function setCache($value) |
||||
{ |
||||
$this->_cache = $value; |
||||
} |
||||
<?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\caching\Cache; |
||||
use yii\caching\Dependency; |
||||
|
||||
/** |
||||
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
* @since 2.0 |
||||
*/ |
||||
class FragmentCache extends Widget |
||||
{ |
||||
/** |
||||
* @var Cache|string the cache object or the application component ID of the cache object. |
||||
* After the FragmentCache object is created, if you want to change this property, |
||||
* you should only assign it with a cache object. |
||||
*/ |
||||
public $cache = 'cache'; |
||||
/** |
||||
* @var integer number of seconds that the data can remain valid in cache. |
||||
* Use 0 to indicate that the cached data will never expire. |
||||
*/ |
||||
public $duration = 60; |
||||
/** |
||||
* @var array|Dependency the dependency that the cached content depends on. |
||||
* This can be either a [[Dependency]] object or a configuration array for creating the dependency object. |
||||
* For example, |
||||
* |
||||
* ~~~ |
||||
* array( |
||||
* 'class' => 'yii\caching\DbDependency', |
||||
* 'sql' => 'SELECT MAX(lastModified) FROM Post', |
||||
* ) |
||||
* ~~~ |
||||
* |
||||
* would make the output cache depends on the last modified time of all posts. |
||||
* If any post has its modification time changed, the cached content would be invalidated. |
||||
*/ |
||||
public $dependency; |
||||
/** |
||||
* @var array list of factors that would cause the variation of the content being cached. |
||||
* Each factor is a string representing a variation (e.g. the language, a GET parameter). |
||||
* The following variation setting will cause the content to be cached in different versions |
||||
* according to the current application language: |
||||
* |
||||
* ~~~ |
||||
* array( |
||||
* Yii::$app->language, |
||||
* ) |
||||
*/ |
||||
public $variations; |
||||
/** |
||||
* @var boolean whether to enable the fragment cache. You may use this property to turn on and off |
||||
* the fragment cache according to specific setting (e.g. enable fragment cache only for GET requests). |
||||
*/ |
||||
public $enabled = true; |
||||
/** |
||||
* @var array a list of placeholders for embedding dynamic contents. This property |
||||
* is used internally to implement the content caching feature. Do not modify it. |
||||
*/ |
||||
public $dynamicPlaceholders; |
||||
|
||||
/** |
||||
* Initializes the FragmentCache object. |
||||
*/ |
||||
public function init() |
||||
{ |
||||
parent::init(); |
||||
|
||||
if (!$this->enabled) { |
||||
$this->cache = null; |
||||
} elseif (is_string($this->cache)) { |
||||
$this->cache = Yii::$app->getComponent($this->cache); |
||||
} |
||||
|
||||
if ($this->getCachedContent() === false) { |
||||
$this->view->cacheStack[] = $this; |
||||
ob_start(); |
||||
ob_implicit_flush(false); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Marks the end of content to be cached. |
||||
* Content displayed before this method call and after {@link init()} |
||||
* will be captured and saved in cache. |
||||
* This method does nothing if valid content is already found in cache. |
||||
*/ |
||||
public function run() |
||||
{ |
||||
if (($content = $this->getCachedContent()) !== false) { |
||||
echo $content; |
||||
} elseif ($this->cache instanceof Cache) { |
||||
$content = ob_get_clean(); |
||||
array_pop($this->view->cacheStack); |
||||
if (is_array($this->dependency)) { |
||||
$this->dependency = Yii::createObject($this->dependency); |
||||
} |
||||
$data = array($content, $this->dynamicPlaceholders); |
||||
$this->cache->set($this->calculateKey(), $data, $this->duration, $this->dependency); |
||||
|
||||
if ($this->view->cacheStack === array() && !empty($this->dynamicPlaceholders)) { |
||||
$content = $this->updateDynamicContent($content, $this->dynamicPlaceholders); |
||||
} |
||||
echo $content; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @var string|boolean the cached content. False if the content is not cached. |
||||
*/ |
||||
private $_content; |
||||
|
||||
/** |
||||
* Returns the cached content if available. |
||||
* @return string|boolean the cached content. False is returned if valid content is not found in the cache. |
||||
*/ |
||||
public function getCachedContent() |
||||
{ |
||||
if ($this->_content === null) { |
||||
$this->_content = false; |
||||
if ($this->cache instanceof Cache) { |
||||
$key = $this->calculateKey(); |
||||
$data = $this->cache->get($key); |
||||
if (is_array($data) && count($data) === 2) { |
||||
list ($content, $placeholders) = $data; |
||||
if (is_array($placeholders) && count($placeholders) > 0) { |
||||
if ($this->view->cacheStack === array()) { |
||||
// outermost cache: replace placeholder with dynamic content |
||||
$content = $this->updateDynamicContent($content, $placeholders); |
||||
} |
||||
foreach ($placeholders as $name => $statements) { |
||||
$this->view->addDynamicPlaceholder($name, $statements); |
||||
} |
||||
} |
||||
$this->_content = $content; |
||||
} |
||||
} |
||||
} |
||||
return $this->_content; |
||||
} |
||||
|
||||
protected function updateDynamicContent($content, $placeholders) |
||||
{ |
||||
foreach ($placeholders as $name => $statements) { |
||||
$placeholders[$name] = $this->view->evaluateDynamicContent($statements); |
||||
} |
||||
return strtr($content, $placeholders); |
||||
} |
||||
|
||||
/** |
||||
* Generates a unique key used for storing the content in cache. |
||||
* The key generated depends on both [[id]] and [[variations]]. |
||||
* @return string a valid cache key |
||||
*/ |
||||
protected function calculateKey() |
||||
{ |
||||
$factors = array(__CLASS__, $this->getId()); |
||||
if (is_array($this->variations)) { |
||||
foreach ($this->variations as $factor) { |
||||
$factors[] = $factor; |
||||
} |
||||
} |
||||
return $this->cache->buildKey($factors); |
||||
} |
||||
} |
@ -0,0 +1,17 @@
|
||||
<?php |
||||
namespace yiiunit\data\base; |
||||
use yii\base\Model; |
||||
|
||||
/** |
||||
* InvalidRulesModel |
||||
*/ |
||||
class InvalidRulesModel extends Model |
||||
{ |
||||
public function rules() |
||||
{ |
||||
return array( |
||||
array('test'), |
||||
); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,21 @@
|
||||
<?php |
||||
namespace yiiunit\data\base; |
||||
use yii\base\Model; |
||||
|
||||
/** |
||||
* Singer |
||||
*/ |
||||
class Singer extends Model |
||||
{ |
||||
public $fistName; |
||||
public $lastName; |
||||
|
||||
public function rules() |
||||
{ |
||||
return array( |
||||
array('lastName', 'default', 'value' => 'Lennon'), |
||||
array('lastName', 'required'), |
||||
array('underscore_style', 'yii\validators\CaptchaValidator'), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,39 @@
|
||||
<?php |
||||
namespace yiiunit\data\base; |
||||
use yii\base\Model; |
||||
|
||||
/** |
||||
* Speaker |
||||
*/ |
||||
class Speaker extends Model |
||||
{ |
||||
public $firstName; |
||||
public $lastName; |
||||
|
||||
public $customLabel; |
||||
public $underscore_style; |
||||
|
||||
protected $protectedProperty; |
||||
private $_privateProperty; |
||||
|
||||
public function attributeLabels() |
||||
{ |
||||
return array( |
||||
'customLabel' => 'This is the custom label', |
||||
); |
||||
} |
||||
|
||||
public function rules() |
||||
{ |
||||
return array( |
||||
|
||||
); |
||||
} |
||||
|
||||
public function scenarios() |
||||
{ |
||||
return array( |
||||
'test' => array('firstName', 'lastName', '!underscore_style'), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,203 @@
|
||||
<?php |
||||
|
||||
namespace yiiunit\framework\base; |
||||
use yii\base\Model; |
||||
use yiiunit\TestCase; |
||||
use yiiunit\data\base\Speaker; |
||||
use yiiunit\data\base\Singer; |
||||
use yiiunit\data\base\InvalidRulesModel; |
||||
|
||||
/** |
||||
* ModelTest |
||||
*/ |
||||
class ModelTest extends TestCase |
||||
{ |
||||
public function testGetAttributeLalel() |
||||
{ |
||||
$speaker = new Speaker(); |
||||
$this->assertEquals('First Name', $speaker->getAttributeLabel('firstName')); |
||||
$this->assertEquals('This is the custom label', $speaker->getAttributeLabel('customLabel')); |
||||
$this->assertEquals('Underscore Style', $speaker->getAttributeLabel('underscore_style')); |
||||
} |
||||
|
||||
public function testGetAttributes() |
||||
{ |
||||
$speaker = new Speaker(); |
||||
$speaker->firstName = 'Qiang'; |
||||
$speaker->lastName = 'Xue'; |
||||
|
||||
$this->assertEquals(array( |
||||
'firstName' => 'Qiang', |
||||
'lastName' => 'Xue', |
||||
'customLabel' => null, |
||||
'underscore_style' => null, |
||||
), $speaker->getAttributes()); |
||||
|
||||
$this->assertEquals(array( |
||||
'firstName' => 'Qiang', |
||||
'lastName' => 'Xue', |
||||
), $speaker->getAttributes(array('firstName', 'lastName'))); |
||||
|
||||
$this->assertEquals(array( |
||||
'firstName' => 'Qiang', |
||||
'lastName' => 'Xue', |
||||
), $speaker->getAttributes(null, array('customLabel', 'underscore_style'))); |
||||
|
||||
$this->assertEquals(array( |
||||
'firstName' => 'Qiang', |
||||
), $speaker->getAttributes(array('firstName', 'lastName'), array('lastName', 'customLabel', 'underscore_style'))); |
||||
} |
||||
|
||||
public function testSetAttributes() |
||||
{ |
||||
// by default mass assignment doesn't work at all |
||||
$speaker = new Speaker(); |
||||
$speaker->setAttributes(array('firstName' => 'Qiang', 'underscore_style' => 'test')); |
||||
$this->assertNull($speaker->firstName); |
||||
$this->assertNull($speaker->underscore_style); |
||||
|
||||
// in the test scenario |
||||
$speaker = new Speaker(); |
||||
$speaker->setScenario('test'); |
||||
$speaker->setAttributes(array('firstName' => 'Qiang', 'underscore_style' => 'test')); |
||||
$this->assertNull($speaker->underscore_style); |
||||
$this->assertEquals('Qiang', $speaker->firstName); |
||||
|
||||
$speaker->setAttributes(array('firstName' => 'Qiang', 'underscore_style' => 'test'), false); |
||||
$this->assertEquals('test', $speaker->underscore_style); |
||||
$this->assertEquals('Qiang', $speaker->firstName); |
||||
} |
||||
|
||||
public function testActiveAttributes() |
||||
{ |
||||
// by default mass assignment doesn't work at all |
||||
$speaker = new Speaker(); |
||||
$this->assertEmpty($speaker->activeAttributes()); |
||||
|
||||
$speaker = new Speaker(); |
||||
$speaker->setScenario('test'); |
||||
$this->assertEquals(array('firstName', 'lastName', 'underscore_style'), $speaker->activeAttributes()); |
||||
} |
||||
|
||||
public function testIsAttributeSafe() |
||||
{ |
||||
// by default mass assignment doesn't work at all |
||||
$speaker = new Speaker(); |
||||
$this->assertFalse($speaker->isAttributeSafe('firstName')); |
||||
|
||||
$speaker = new Speaker(); |
||||
$speaker->setScenario('test'); |
||||
$this->assertTrue($speaker->isAttributeSafe('firstName')); |
||||
|
||||
} |
||||
|
||||
public function testErrors() |
||||
{ |
||||
$speaker = new Speaker(); |
||||
|
||||
$this->assertEmpty($speaker->getErrors()); |
||||
$this->assertEmpty($speaker->getErrors('firstName')); |
||||
$this->assertEmpty($speaker->getFirstErrors()); |
||||
|
||||
$this->assertFalse($speaker->hasErrors()); |
||||
$this->assertFalse($speaker->hasErrors('firstName')); |
||||
|
||||
$speaker->addError('firstName', 'Something is wrong!'); |
||||
$this->assertEquals(array('firstName' => array('Something is wrong!')), $speaker->getErrors()); |
||||
$this->assertEquals(array('Something is wrong!'), $speaker->getErrors('firstName')); |
||||
|
||||
$speaker->addError('firstName', 'Totally wrong!'); |
||||
$this->assertEquals(array('firstName' => array('Something is wrong!', 'Totally wrong!')), $speaker->getErrors()); |
||||
$this->assertEquals(array('Something is wrong!', 'Totally wrong!'), $speaker->getErrors('firstName')); |
||||
|
||||
$this->assertTrue($speaker->hasErrors()); |
||||
$this->assertTrue($speaker->hasErrors('firstName')); |
||||
$this->assertFalse($speaker->hasErrors('lastName')); |
||||
|
||||
$this->assertEquals(array('Something is wrong!'), $speaker->getFirstErrors()); |
||||
$this->assertEquals('Something is wrong!', $speaker->getFirstError('firstName')); |
||||
$this->assertNull($speaker->getFirstError('lastName')); |
||||
|
||||
$speaker->addError('lastName', 'Another one!'); |
||||
$this->assertEquals(array( |
||||
'firstName' => array( |
||||
'Something is wrong!', |
||||
'Totally wrong!', |
||||
), |
||||
'lastName' => array('Another one!'), |
||||
), $speaker->getErrors()); |
||||
|
||||
$speaker->clearErrors('firstName'); |
||||
$this->assertEquals(array( |
||||
'lastName' => array('Another one!'), |
||||
), $speaker->getErrors()); |
||||
|
||||
$speaker->clearErrors(); |
||||
$this->assertEmpty($speaker->getErrors()); |
||||
$this->assertFalse($speaker->hasErrors()); |
||||
} |
||||
|
||||
public function testArraySyntax() |
||||
{ |
||||
$speaker = new Speaker(); |
||||
|
||||
// get |
||||
$this->assertNull($speaker['firstName']); |
||||
|
||||
// isset |
||||
$this->assertFalse(isset($speaker['firstName'])); |
||||
|
||||
// set |
||||
$speaker['firstName'] = 'Qiang'; |
||||
|
||||
$this->assertEquals('Qiang', $speaker['firstName']); |
||||
$this->assertTrue(isset($speaker['firstName'])); |
||||
|
||||
// iteration |
||||
$attributes = array(); |
||||
foreach($speaker as $key => $attribute) { |
||||
$attributes[$key] = $attribute; |
||||
} |
||||
$this->assertEquals(array( |
||||
'firstName' => 'Qiang', |
||||
'lastName' => null, |
||||
'customLabel' => null, |
||||
'underscore_style' => null, |
||||
), $attributes); |
||||
|
||||
// unset |
||||
unset($speaker['firstName']); |
||||
|
||||
// exception isn't expected here |
||||
$this->assertNull($speaker['firstName']); |
||||
$this->assertFalse(isset($speaker['firstName'])); |
||||
} |
||||
|
||||
public function testDefaults() |
||||
{ |
||||
$singer = new Model(); |
||||
$this->assertEquals(array(), $singer->rules()); |
||||
$this->assertEquals(array(), $singer->attributeLabels()); |
||||
} |
||||
|
||||
public function testDefaultScenarios() |
||||
{ |
||||
$singer = new Singer(); |
||||
$this->assertEquals(array('default' => array('lastName', 'underscore_style')), $singer->scenarios()); |
||||
} |
||||
|
||||
public function testIsAttributeRequired() |
||||
{ |
||||
$singer = new Singer(); |
||||
$this->assertFalse($singer->isAttributeRequired('firstName')); |
||||
$this->assertTrue($singer->isAttributeRequired('lastName')); |
||||
} |
||||
|
||||
public function testCreateValidators() |
||||
{ |
||||
$this->setExpectedException('yii\base\InvalidConfigException', 'Invalid validation rule: a rule must be an array specifying both attribute names and validator type.'); |
||||
|
||||
$invalid = new InvalidRulesModel(); |
||||
$invalid->createValidators(); |
||||
} |
||||
} |
@ -1,6 +1,6 @@
|
||||
<?php |
||||
|
||||
namespace yiiunit\framework\util; |
||||
namespace yiiunit\framework\helpers; |
||||
|
||||
use yii\helpers\ArrayHelper; |
||||
|
@ -1,6 +1,6 @@
|
||||
<?php |
||||
|
||||
namespace yiiunit\framework\util; |
||||
namespace yiiunit\framework\helpers; |
||||
|
||||
use Yii; |
||||
use yii\helpers\Html; |
@ -0,0 +1,73 @@
|
||||
<?php |
||||
namespace yiiunit\framework\helpers; |
||||
use \yii\helpers\StringHelper as StringHelper; |
||||
|
||||
/** |
||||
* StringHelperTest |
||||
*/ |
||||
class StringHelperTest extends \yii\test\TestCase |
||||
{ |
||||
public function testStrlen() |
||||
{ |
||||
$this->assertEquals(4, StringHelper::strlen('this')); |
||||
$this->assertEquals(6, StringHelper::strlen('это')); |
||||
} |
||||
|
||||
public function testSubstr() |
||||
{ |
||||
$this->assertEquals('th', StringHelper::substr('this', 0, 2)); |
||||
$this->assertEquals('э', StringHelper::substr('это', 0, 2)); |
||||
} |
||||
|
||||
public function testPluralize() |
||||
{ |
||||
$testData = array( |
||||
'move' => 'moves', |
||||
'foot' => 'feet', |
||||
'child' => 'children', |
||||
'human' => 'humans', |
||||
'man' => 'men', |
||||
'staff' => 'staff', |
||||
'tooth' => 'teeth', |
||||
'person' => 'people', |
||||
'mouse' => 'mice', |
||||
'touch' => 'touches', |
||||
'hash' => 'hashes', |
||||
'shelf' => 'shelves', |
||||
'potato' => 'potatoes', |
||||
'bus' => 'buses', |
||||
'test' => 'tests', |
||||
'car' => 'cars', |
||||
); |
||||
|
||||
foreach($testData as $testIn => $testOut) { |
||||
$this->assertEquals($testOut, StringHelper::pluralize($testIn)); |
||||
$this->assertEquals(ucfirst($testOut), ucfirst(StringHelper::pluralize($testIn))); |
||||
} |
||||
} |
||||
|
||||
public function testCamel2words() |
||||
{ |
||||
$this->assertEquals('Camel Case', StringHelper::camel2words('camelCase')); |
||||
$this->assertEquals('Lower Case', StringHelper::camel2words('lower_case')); |
||||
$this->assertEquals('Tricky Stuff It Is Testing', StringHelper::camel2words(' tricky_stuff.it-is testing... ')); |
||||
} |
||||
|
||||
public function testCamel2id() |
||||
{ |
||||
$this->assertEquals('post-tag', StringHelper::camel2id('PostTag')); |
||||
$this->assertEquals('post_tag', StringHelper::camel2id('PostTag', '_')); |
||||
|
||||
$this->assertEquals('post-tag', StringHelper::camel2id('postTag')); |
||||
$this->assertEquals('post_tag', StringHelper::camel2id('postTag', '_')); |
||||
} |
||||
|
||||
public function testId2camel() |
||||
{ |
||||
$this->assertEquals('PostTag', StringHelper::id2camel('post-tag')); |
||||
$this->assertEquals('PostTag', StringHelper::id2camel('post_tag', '_')); |
||||
|
||||
$this->assertEquals('PostTag', StringHelper::id2camel('post-tag')); |
||||
$this->assertEquals('PostTag', StringHelper::id2camel('post_tag', '_')); |
||||
} |
||||
} |
Loading…
Reference in new issue