Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yii2
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
PSDI Army
yii2
Commits
379e48a4
Commit
379e48a4
authored
Mar 24, 2013
by
Qiang Xue
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Finished new message translation implementation.
parent
884977a7
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
457 additions
and
101 deletions
+457
-101
ActionFilter.php
framework/base/ActionFilter.php
+46
-0
Application.php
framework/base/Application.php
+0
-1
View.php
framework/base/View.php
+39
-42
I18N.php
framework/i18n/I18N.php
+55
-53
PhpMessageSource.php
framework/i18n/PhpMessageSource.php
+21
-2
Target.php
framework/logging/Target.php
+1
-2
FragmentCache.php
framework/widgets/FragmentCache.php
+295
-0
todo.md
todo.md
+0
-1
No files found.
framework/base/ActionFilter.php
0 → 100644
View file @
379e48a4
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace
yii\base
;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class
Filter
extends
Behavior
{
/**
* 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
(
'beforeAction'
=>
'beforeAction'
,
'afterAction'
=>
'afterAction'
,
);
}
/**
* @param ActionEvent $event
* @return boolean
*/
public
function
beforeAction
(
$event
)
{
return
$event
->
isValid
;
}
/**
* @param ActionEvent $event
* @return boolean
*/
public
function
afterAction
(
$event
)
{
}
}
\ No newline at end of file
framework/base/Application.php
View file @
379e48a4
...
...
@@ -92,7 +92,6 @@ class Application extends Module
private
$_runtimePath
;
private
$_ended
=
false
;
private
$_language
;
/**
* @var string Used to reserve memory for fatal error handler. This memory
...
...
framework/base/View.php
View file @
379e48a4
...
...
@@ -322,46 +322,42 @@ class View extends Component
$this
->
endWidget
();
}
//
// /**
// * Begins fragment caching.
// * This method will display cached content if it is available.
// * If not, it will start caching and would expect an [[endCache()]]
// * call to end the cache and save the content into cache.
// * A typical usage of fragment caching is as follows,
// *
// * ~~~
// * if($this->beginCache($id)) {
// * // ...generate content here
// * $this->endCache();
// * }
// * ~~~
// *
// * @param string $id a unique ID identifying the fragment to be cached.
// * @param array $properties initial property values for [[yii\widgets\OutputCache]]
// * @return boolean whether we need to generate content for caching. False if cached version is available.
// * @see endCache
// */
// public function beginCache($id, $properties = array())
// {
// $properties['id'] = $id;
// $cache = $this->beginWidget('yii\widgets\OutputCache', $properties);
// if ($cache->getIsContentCached()) {
// $this->endCache();
// return false;
// } else {
// return true;
// }
// }
//
// /**
// * Ends fragment caching.
// * This is an alias to [[endWidget()]]
// * @see beginCache
// */
// public function endCache()
// {
// $this->endWidget();
// }
//
/**
* Begins fragment caching.
* This method will display cached content if it is available.
* If not, it will start caching and would expect an [[endCache()]]
* call to end the cache and save the content into cache.
* A typical usage of fragment caching is as follows,
*
* ~~~
* if($this->beginCache($id)) {
* // ...generate content here
* $this->endCache();
* }
* ~~~
*
* @param string $id a unique ID identifying the fragment to be cached.
* @param array $properties initial property values for [[\yii\widgets\OutputCache]]
* @return boolean whether you should generate the content for caching.
* False if the cached version is available.
*/
public
function
beginCache
(
$id
,
$properties
=
array
())
{
$properties
[
'id'
]
=
$id
;
$cache
=
$this
->
beginWidget
(
'yii\widgets\OutputCache'
,
$properties
);
if
(
$cache
->
getIsContentCached
())
{
$this
->
endCache
();
return
false
;
}
else
{
return
true
;
}
}
/**
* Ends fragment caching.
*/
public
function
endCache
()
{
$this
->
endWidget
();
}
}
\ No newline at end of file
framework/i18n/I18N.php
View file @
379e48a4
...
...
@@ -4,91 +4,93 @@ namespace yii\i18n;
use
Yii
;
use
yii\base\Component
;
use
yii\base\InvalidConfigException
;
class
I18N
extends
Component
{
/**
* @var array list of [[MessageSource]] configurations or objects. The array keys are message
* categories, and the array values are the corresponding [[MessageSource]] objects or the configurations
* for creating the [[MessageSource]] objects. The message categories can contain the wildcard '*' at the end
* to match multiple categories with the same prefix. For example, 'app\*' matches both 'app\cat1' and 'app\cat2'.
*/
public
$translations
;
public
function
init
()
{
if
(
!
isset
(
$this
->
translations
[
'yii'
]))
{
$this
->
translations
[
'yii'
]
=
array
(
'class'
=>
'yii\i18n\PhpMessageSource'
,
'sourceLanguage'
=>
'en_US'
,
'basePath'
=>
'@yii/messages'
,
);
}
if
(
!
isset
(
$this
->
translations
[
'app'
]))
{
$this
->
translations
[
'app'
]
=
array
(
'class'
=>
'yii\i18n\PhpMessageSource'
,
'sourceLanguage'
=>
'en_US'
,
'basePath'
=>
'@app/messages'
,
);
}
}
public
function
translate
(
$message
,
$params
=
array
(),
$language
=
null
)
{
if
(
$language
===
null
)
{
$language
=
Yii
::
$app
->
language
;
}
if
(
strpos
(
$message
,
'|'
)
!==
false
&&
preg_match
(
'/^([\w\-\.]+)\|(.*)/'
,
$message
,
$matches
))
{
// allow chars for category: word chars, ".", "-", "/","\"
if
(
strpos
(
$message
,
'|'
)
!==
false
&&
preg_match
(
'/^([\w\-\\/\.\\\\]+)\|(.*)/'
,
$message
,
$matches
))
{
$category
=
$matches
[
1
];
$message
=
$matches
[
2
];
}
else
{
$category
=
'app'
;
}
// $message = $this->getMessageSource($category)->translate($category, $message, $language);
//
// if (!is_array($params)) {
// $params = array($params);
// }
//
// if (isset($params[0])) {
// $message = $this->getPluralFormat($message, $params[0], $language);
// if (!isset($params['{n}'])) {
// $params['{n}'] = $params[0];
// }
// unset($params[0]);
// }
$message
=
$this
->
getMessageSource
(
$category
)
->
translate
(
$category
,
$message
,
$language
);
return
$params
===
array
()
?
$message
:
strtr
(
$message
,
$params
);
if
(
!
is_array
(
$params
))
{
$params
=
array
(
$params
);
}
public
function
getLocale
(
$language
)
{
if
(
isset
(
$params
[
0
]))
{
$message
=
$this
->
getPluralForm
(
$message
,
$params
[
0
],
$language
);
if
(
!
isset
(
$params
[
'{n}'
]))
{
$params
[
'{n}'
]
=
$params
[
0
];
}
public
function
getMessageSource
(
$category
)
{
return
$category
===
'yii'
?
$this
->
getMessages
()
:
$this
->
getCoreMessages
();
unset
(
$params
[
0
]);
}
private
$_coreMessages
;
private
$_messages
;
return
$params
===
array
()
?
$message
:
strtr
(
$message
,
$params
)
;
}
public
function
get
CoreMessages
(
)
public
function
get
MessageSource
(
$category
)
{
if
(
is_object
(
$this
->
_coreMessages
))
{
return
$this
->
_coreMessages
;
}
elseif
(
$this
->
_coreMessages
===
null
)
{
return
$this
->
_coreMessages
=
new
PhpMessageSource
(
array
(
'sourceLanguage'
=>
'en_US'
,
'basePath'
=>
'@yii/messages'
,
));
if
(
isset
(
$this
->
translations
[
$category
]))
{
$source
=
$this
->
translations
[
$category
];
}
else
{
return
$this
->
_coreMessages
=
Yii
::
createObject
(
$this
->
_coreMessages
);
// try wildcard matching
foreach
(
$this
->
translations
as
$pattern
=>
$config
)
{
if
(
substr
(
$pattern
,
-
1
)
===
'*'
&&
strpos
(
$category
,
rtrim
(
$pattern
,
'*'
))
===
0
)
{
$source
=
$config
;
break
;
}
}
public
function
setCoreMessages
(
$config
)
{
$this
->
_coreMessages
=
$config
;
}
public
function
getMessages
()
{
if
(
is_object
(
$this
->
_messages
))
{
return
$this
->
_messages
;
}
elseif
(
$this
->
_messages
===
null
)
{
return
$this
->
_messages
=
new
PhpMessageSource
(
array
(
'sourceLanguage'
=>
'en_US'
,
'basePath'
=>
'@app/messages'
,
));
if
(
isset
(
$source
))
{
return
$source
instanceof
MessageSource
?
$source
:
Yii
::
createObject
(
$source
);
}
else
{
return
$this
->
_messages
=
Yii
::
createObject
(
$this
->
_messages
);
throw
new
InvalidConfigException
(
"Unable to locate message source for category '
$category
'."
);
}
}
public
function
setMessages
(
$config
)
public
function
getLocale
(
$language
)
{
$this
->
_messages
=
$config
;
}
protected
function
getPluralForm
at
(
$message
,
$number
,
$language
)
protected
function
getPluralForm
(
$message
,
$number
,
$language
)
{
if
(
strpos
(
$message
,
'|'
)
===
false
)
{
return
$message
;
...
...
@@ -96,7 +98,7 @@ class I18N extends Component
$chunks
=
explode
(
'|'
,
$message
);
$rules
=
$this
->
getLocale
(
$language
)
->
getPluralRules
();
foreach
(
$rules
as
$i
=>
$rule
)
{
if
(
isset
(
$chunks
[
$i
])
&&
self
::
evaluate
(
$rule
,
$number
))
{
if
(
isset
(
$chunks
[
$i
])
&&
$this
->
evaluate
(
$rule
,
$number
))
{
return
$chunks
[
$i
];
}
}
...
...
@@ -110,7 +112,7 @@ class I18N extends Component
* @param mixed $n the number value
* @return boolean the expression result
*/
protected
static
function
evaluate
(
$expression
,
$n
)
protected
function
evaluate
(
$expression
,
$n
)
{
return
@
eval
(
"return
$expression
;"
);
}
...
...
framework/i18n/PhpMessageSource.php
View file @
379e48a4
...
...
@@ -36,6 +36,18 @@ class PhpMessageSource extends MessageSource
* the "messages" subdirectory of the application directory (e.g. "protected/messages").
*/
public
$basePath
=
'@app/messages'
;
/**
* @var array mapping between message categories and the corresponding message file paths.
* The file paths are relative to [[basePath]]. For example,
*
* ~~~
* array(
* 'core' => 'core.php',
* 'ext' => 'extensions.php',
* )
* ~~~
*/
public
$fileMap
;
/**
* Loads the message translation for the specified language and category.
...
...
@@ -45,7 +57,14 @@ class PhpMessageSource extends MessageSource
*/
protected
function
loadMessages
(
$category
,
$language
)
{
$messageFile
=
Yii
::
getAlias
(
$this
->
basePath
)
.
"/
$language
/
$category
.php"
;
$messageFile
=
Yii
::
getAlias
(
$this
->
basePath
)
.
"/
$language
/"
;
if
(
isset
(
$this
->
fileMap
[
$category
]))
{
$messageFile
.=
$this
->
fileMap
[
$category
];
}
elseif
((
$pos
=
strrpos
(
$category
,
'\\'
))
!==
false
)
{
$messageFile
.=
(
substr
(
$category
,
$pos
)
.
'.php'
);
}
else
{
$messageFile
.=
"
$category
.php"
;
}
if
(
is_file
(
$messageFile
))
{
$messages
=
include
(
$messageFile
);
if
(
!
is_array
(
$messages
))
{
...
...
@@ -53,7 +72,7 @@ class PhpMessageSource extends MessageSource
}
return
$messages
;
}
else
{
Yii
::
error
(
"
Message file not found
:
$messageFile
"
,
__CLASS__
);
Yii
::
error
(
"
The message file for category '
$category
' does not exist
:
$messageFile
"
,
__CLASS__
);
return
array
();
}
}
...
...
framework/logging/Target.php
View file @
379e48a4
...
...
@@ -192,8 +192,7 @@ abstract class Target extends \yii\base\Component
$matched
=
empty
(
$this
->
categories
);
foreach
(
$this
->
categories
as
$category
)
{
$prefix
=
rtrim
(
$category
,
'*'
);
if
(
strpos
(
$message
[
2
],
$prefix
)
===
0
&&
(
$message
[
2
]
===
$category
||
$prefix
!==
$category
))
{
if
(
$message
[
2
]
===
$category
||
substr
(
$category
,
-
1
)
===
'*'
&&
strpos
(
$message
[
2
],
rtrim
(
$category
,
'*'
))
===
0
)
{
$matched
=
true
;
break
;
}
...
...
framework/widgets/FragmentCache.php
0 → 100644
View file @
379e48a4
<?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\Widget
;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class
FragmentCache
extends
Widget
{
/**
* Prefix to the keys for storing cached data
*/
const
CACHE_KEY_PREFIX
=
'Yii.COutputCache.'
;
/**
* @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 in cache. Defaults to 60 seconds.
* If it is 0, existing cached content would be removed from the cache.
* If it is a negative value, the cache will be disabled (any existing cached content will
* remain in the cache.)
*
* Note, if cache dependency changes or cache space is limited,
* the data may be purged out of cache earlier.
*/
public
$duration
=
60
;
/**
* @var mixed the dependency that the cached content depends on.
* This can be either an object implementing {@link ICacheDependency} interface or an array
* specifying the configuration of the dependency object. For example,
* <pre>
* array(
* 'class'=>'CDbCacheDependency',
* 'sql'=>'SELECT MAX(lastModified) FROM Post',
* )
* </pre>
* 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 boolean whether the content being cached should be differentiated according to route.
* A route consists of the requested controller ID and action ID.
* Defaults to true.
*/
public
$varyByRoute
=
true
;
/**
* @var boolean whether the content being cached should be differentiated according to user's language.
* A language is retrieved via Yii::app()->language.
* Defaults to false.
* @since 1.1.14
*/
public
$varyByLanguage
=
false
;
/**
* @var array list of GET parameters that should participate in cache key calculation.
* By setting this property, the output cache will use different cached data
* for each different set of GET parameter values.
*/
public
$varyByParam
;
/**
* @var string a PHP expression whose result is used in the cache key calculation.
* By setting this property, the output cache will use different cached data
* for each different expression result.
* The expression can also be a valid PHP callback,
* including class method name (array(ClassName/Object, MethodName)),
* or anonymous function (PHP 5.3.0+). The function/method signature should be as follows:
* <pre>
* function foo($cache) { ... }
* </pre>
* where $cache refers to the output cache component.
*/
public
$varyByExpression
;
/**
* @var array list of request types (e.g. GET, POST) for which the cache should be enabled only.
* Defaults to null, meaning all request types.
*/
public
$requestTypes
;
private
$_key
;
private
$_cache
;
private
$_contentCached
;
private
$_content
;
private
$_actions
;
/**
* 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
->
getIsContentCached
())
{
$this
->
replayActions
();
}
elseif
(
$this
->
_cache
!==
null
)
{
$this
->
getController
()
->
getCachingStack
()
->
push
(
$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
(
$this
->
getIsContentCached
())
{
if
(
$this
->
getController
()
->
isCachingStackEmpty
())
{
echo
$this
->
getController
()
->
processDynamicOutput
(
$this
->
_content
);
}
else
{
echo
$this
->
_content
;
}
}
elseif
(
$this
->
_cache
!==
null
)
{
$this
->
_content
=
ob_get_clean
();
$this
->
getController
()
->
getCachingStack
()
->
pop
();
$data
=
array
(
$this
->
_content
,
$this
->
_actions
);
if
(
is_array
(
$this
->
dependency
))
{
$this
->
dependency
=
Yii
::
createComponent
(
$this
->
dependency
);
}
$this
->
_cache
->
set
(
$this
->
getCacheKey
(),
$data
,
$this
->
duration
,
$this
->
dependency
);
if
(
$this
->
getController
()
->
isCachingStackEmpty
())
{
echo
$this
->
getController
()
->
processDynamicOutput
(
$this
->
_content
);
}
else
{
echo
$this
->
_content
;
}
}
}
/**
* @return boolean whether the content can be found from cache
*/
public
function
getIsContentCached
()
{
if
(
$this
->
_contentCached
!==
null
)
{
return
$this
->
_contentCached
;
}
else
{
return
$this
->
_contentCached
=
$this
->
checkContentCache
();
}
}
/**
* Looks for content in cache.
* @return boolean whether the content is found in cache.
*/
protected
function
checkContentCache
()
{
if
((
empty
(
$this
->
requestTypes
)
||
in_array
(
Yii
::
app
()
->
getRequest
()
->
getRequestType
(),
$this
->
requestTypes
))
&&
(
$this
->
_cache
=
$this
->
getCache
())
!==
null
)
{
if
(
$this
->
duration
>
0
&&
(
$data
=
$this
->
_cache
->
get
(
$this
->
getCacheKey
()))
!==
false
)
{
$this
->
_content
=
$data
[
0
];
$this
->
_actions
=
$data
[
1
];
return
true
;
}
if
(
$this
->
duration
==
0
)
{
$this
->
_cache
->
delete
(
$this
->
getCacheKey
());
}
if
(
$this
->
duration
<=
0
)
{
$this
->
_cache
=
null
;
}
}
return
false
;
}
/**
* @return ICache the cache used for caching the content.
*/
protected
function
getCache
()
{
return
Yii
::
app
()
->
getComponent
(
$this
->
cacheID
);
}
/**
* Caclulates the base cache key.
* The calculated key will be further variated in {@link getCacheKey}.
* Derived classes may override this method if more variations are needed.
* @return string basic cache key without variations
*/
protected
function
getBaseCacheKey
()
{
return
self
::
CACHE_KEY_PREFIX
.
$this
->
getId
()
.
'.'
;
}
/**
* Calculates the cache key.
* The key is calculated based on {@link getBaseCacheKey} and other factors, including
* {@link varyByRoute}, {@link varyByParam}, {@link varyBySession} and {@link varyByLanguage}.
* @return string cache key
*/
protected
function
getCacheKey
()
{
if
(
$this
->
_key
!==
null
)
{
return
$this
->
_key
;
}
else
{
$key
=
$this
->
getBaseCacheKey
()
.
'.'
;
if
(
$this
->
varyByRoute
)
{
$controller
=
$this
->
getController
();
$key
.=
$controller
->
getUniqueId
()
.
'/'
;
if
((
$action
=
$controller
->
getAction
())
!==
null
)
{
$key
.=
$action
->
getId
();
}
}
$key
.=
'.'
;
if
(
$this
->
varyBySession
)
{
$key
.=
Yii
::
app
()
->
getSession
()
->
getSessionID
();
}
$key
.=
'.'
;
if
(
is_array
(
$this
->
varyByParam
)
&&
isset
(
$this
->
varyByParam
[
0
]))
{
$params
=
array
();
foreach
(
$this
->
varyByParam
as
$name
)
{
if
(
isset
(
$_GET
[
$name
]))
{
$params
[
$name
]
=
$_GET
[
$name
];
}
else
{
$params
[
$name
]
=
''
;
}
}
$key
.=
serialize
(
$params
);
}
$key
.=
'.'
;
if
(
$this
->
varyByExpression
!==
null
)
{
$key
.=
$this
->
evaluateExpression
(
$this
->
varyByExpression
);
}
$key
.=
'.'
;
if
(
$this
->
varyByLanguage
)
{
$key
.=
Yii
::
app
()
->
language
;
}
$key
.=
'.'
;
return
$this
->
_key
=
$key
;
}
}
/**
* Records a method call when this output cache is in effect.
* When the content is served from the output cache, the recorded
* method will be re-invoked.
* @param string $context a property name of the controller. The property should refer to an object
* whose method is being recorded. If empty it means the controller itself.
* @param string $method the method name
* @param array $params parameters passed to the method
*/
public
function
recordAction
(
$context
,
$method
,
$params
)
{
$this
->
_actions
[]
=
array
(
$context
,
$method
,
$params
);
}
/**
* Replays the recorded method calls.
*/
protected
function
replayActions
()
{
if
(
empty
(
$this
->
_actions
))
{
return
;
}
$controller
=
$this
->
getController
();
$cs
=
Yii
::
app
()
->
getClientScript
();
foreach
(
$this
->
_actions
as
$action
)
{
if
(
$action
[
0
]
===
'clientScript'
)
{
$object
=
$cs
;
}
elseif
(
$action
[
0
]
===
''
)
{
$object
=
$controller
;
}
else
{
$object
=
$controller
->
{
$action
[
0
]};
}
if
(
method_exists
(
$object
,
$action
[
1
]))
{
call_user_func_array
(
array
(
$object
,
$action
[
1
]),
$action
[
2
]);
}
elseif
(
$action
[
0
]
===
''
&&
function_exists
(
$action
[
1
]))
{
call_user_func_array
(
$action
[
1
],
$action
[
2
]);
}
else
{
throw
new
CException
(
Yii
::
t
(
'yii'
,
'Unable to replay the action "{object}.{method}". The method does not exist.'
,
array
(
'object'
=>
$action
[
0
],
'method'
=>
$action
[
1
])));
}
}
}
}
\ No newline at end of file
todo.md
View file @
379e48a4
...
...
@@ -39,7 +39,6 @@ memo
*
consider to be released as a separate tool for user app docs
-
i18n
*
consider using PHP built-in support and data
*
message translations, choice format
*
formatting: number and date
*
parsing??
*
make dates/date patterns uniform application-wide including JUI, formats etc.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment