Alexander Makarov
12 years ago
49 changed files with 1592 additions and 1439 deletions
@ -1,328 +0,0 @@ |
|||||||
Yii2 code standard |
|
||||||
================== |
|
||||||
|
|
||||||
This code standard is used for all the Yii2 core classes and can be applied to |
|
||||||
your application in order to achieve consistency among your team. Also it will |
|
||||||
help in case you want to opensource code. |
|
||||||
|
|
||||||
PHP file formatting |
|
||||||
------------------- |
|
||||||
|
|
||||||
### General |
|
||||||
|
|
||||||
- Do not end file with `?>` if it contains PHP code only. |
|
||||||
- Do not use `<?`. Use `<?php` instead. |
|
||||||
- Files should be encoded in UTF-8. |
|
||||||
- Any file that contains PHP code should end with the extension `.php`. |
|
||||||
- Do not add trailing spaces to the end of the lines. |
|
||||||
|
|
||||||
#### Indentation |
|
||||||
|
|
||||||
All code must be indented with tabs. That includes both PHP and JavaScript code. |
|
||||||
|
|
||||||
#### Maximum Line Length |
|
||||||
|
|
||||||
We're not strictly limiting maximum line length but sticking to 80 characters |
|
||||||
where possible. |
|
||||||
|
|
||||||
### PHP types |
|
||||||
|
|
||||||
All PHP types and values should be used lowercase. That includes `true`, `false`, |
|
||||||
`null` and `array`. |
|
||||||
|
|
||||||
### Strings |
|
||||||
|
|
||||||
- If string doesn't contain variables or single quotes, use single quotes. |
|
||||||
|
|
||||||
~~~ |
|
||||||
$str = 'Like this.'; |
|
||||||
~~~ |
|
||||||
|
|
||||||
- If string contains single quotes you can use double quotes to avoid extra escaping. |
|
||||||
- You can use the following forms of variable substitution: |
|
||||||
|
|
||||||
~~~ |
|
||||||
$str1 = "Hello $username!"; |
|
||||||
$str2 = "Hello {$username}!"; |
|
||||||
~~~ |
|
||||||
|
|
||||||
The following is not permitted: |
|
||||||
|
|
||||||
~~~ |
|
||||||
$str3 = "Hello ${username}!"; |
|
||||||
~~~ |
|
||||||
|
|
||||||
### String concatenation |
|
||||||
|
|
||||||
Add spaces around dot when concatenating strings: |
|
||||||
|
|
||||||
~~~ |
|
||||||
$name = 'Yii' . ' Framework'; |
|
||||||
~~~ |
|
||||||
|
|
||||||
When string is long format is the following: |
|
||||||
|
|
||||||
~~~ |
|
||||||
$sql = "SELECT *" |
|
||||||
. "FROM `post` " |
|
||||||
. "WHERE `id` = 121 "; |
|
||||||
~~~ |
|
||||||
|
|
||||||
|
|
||||||
### Numerically indexed arrays |
|
||||||
|
|
||||||
- Do not use negative numbers as array indexes. |
|
||||||
|
|
||||||
Use the following formatting when declaring array: |
|
||||||
|
|
||||||
~~~ |
|
||||||
$arr = array(3, 14, 15, 'Yii', 'Framework'); |
|
||||||
~~~ |
|
||||||
|
|
||||||
If there are too many elements for a single line: |
|
||||||
|
|
||||||
~~~ |
|
||||||
$arr = array( |
|
||||||
3, 14, 15, |
|
||||||
92, 6, $test, |
|
||||||
'Yii', 'Framework', |
|
||||||
); |
|
||||||
~~~ |
|
||||||
|
|
||||||
### Associative arrays |
|
||||||
|
|
||||||
Use the following format for associative arrays: |
|
||||||
|
|
||||||
~~~ |
|
||||||
$config = array( |
|
||||||
'name' => 'Yii', |
|
||||||
'options' => array( |
|
||||||
'usePHP' => true, |
|
||||||
), |
|
||||||
); |
|
||||||
~~~ |
|
||||||
|
|
||||||
### Classes |
|
||||||
|
|
||||||
- Classes should be named using `CamelCase`. |
|
||||||
- The brace should always be written on the line underneath the class name. |
|
||||||
- Every class must have a documentation block that conforms to the PHPDoc. |
|
||||||
- All code in a class must be indented with a single tab. |
|
||||||
- There should be only one class in a single PHP file. |
|
||||||
- All classes should be namespaced. |
|
||||||
- Class name should match file name. Class namespace should match directory structure. |
|
||||||
|
|
||||||
~~~ |
|
||||||
/** |
|
||||||
* Documentation |
|
||||||
*/ |
|
||||||
class MyClass extends \yii\Object implements MyInterface |
|
||||||
{ |
|
||||||
// code |
|
||||||
} |
|
||||||
~~~ |
|
||||||
|
|
||||||
|
|
||||||
### Class members and variables |
|
||||||
|
|
||||||
- When declaring public class members specify `public` keyword explicitly. |
|
||||||
- Variables should be declared at the top of the class before any method declarations. |
|
||||||
- Private and protected variables should be named like `$_varName`. |
|
||||||
- Public class members and standalone variables should be named using `$camelCase` |
|
||||||
with first letter lowercase. |
|
||||||
- Use descriptive names. Variables such as `$i` and `$j` are better not to be used. |
|
||||||
|
|
||||||
### Constants |
|
||||||
|
|
||||||
Both class level constants and global constants should be named in uppercase. Words |
|
||||||
are separated by underscore. |
|
||||||
|
|
||||||
~~~ |
|
||||||
class User { |
|
||||||
const STATUS_ACTIVE = 1; |
|
||||||
const STATUS_BANNED = 2; |
|
||||||
} |
|
||||||
~~~ |
|
||||||
|
|
||||||
It's preferable to define class level constants rather than global ones. |
|
||||||
|
|
||||||
### Functions and methods |
|
||||||
|
|
||||||
- Functions and methods should be named using `camelCase` with first letter lowercase. |
|
||||||
- Name should be descriptive by itself indicating the purpose of the function. |
|
||||||
- Class methods should always declare visibility using `private`, `protected` and |
|
||||||
`public` modifiers. `var` is not allowed. |
|
||||||
- Opening brace of a function should be on the line after the function declaration. |
|
||||||
|
|
||||||
~~~ |
|
||||||
/** |
|
||||||
* Documentation |
|
||||||
*/ |
|
||||||
class Foo |
|
||||||
{ |
|
||||||
/** |
|
||||||
* Documentation |
|
||||||
*/ |
|
||||||
public function bar() |
|
||||||
{ |
|
||||||
// code |
|
||||||
return $value; |
|
||||||
} |
|
||||||
} |
|
||||||
~~~ |
|
||||||
|
|
||||||
Use type hinting where possible: |
|
||||||
|
|
||||||
~~~ |
|
||||||
public function __construct(CDbConnection $connection) |
|
||||||
{ |
|
||||||
$this->connection = $connection; |
|
||||||
} |
|
||||||
~~~ |
|
||||||
|
|
||||||
### Function and method calls |
|
||||||
|
|
||||||
~~~ |
|
||||||
doIt(2, 3); |
|
||||||
|
|
||||||
doIt(array( |
|
||||||
'a' => 'b', |
|
||||||
)); |
|
||||||
|
|
||||||
doIt('a', array( |
|
||||||
'a' => 'b', |
|
||||||
)); |
|
||||||
~~~ |
|
||||||
|
|
||||||
### Control statements |
|
||||||
|
|
||||||
- Control statement condition must have single space before and after parenthesis. |
|
||||||
- Operators inside of parenthesis should be separated by spaces. |
|
||||||
- Opening brace is on the same line. |
|
||||||
- Closing brace is on a new line. |
|
||||||
- Always use braces for single line statements. |
|
||||||
|
|
||||||
~~~ |
|
||||||
if ($event === null) { |
|
||||||
return new Event(); |
|
||||||
} elseif ($event instanceof CoolEvent) { |
|
||||||
return $event->instance(); |
|
||||||
} else { |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
// the following is NOT allowed: |
|
||||||
if(!$model) |
|
||||||
throw new Exception('test'); |
|
||||||
~~~ |
|
||||||
|
|
||||||
|
|
||||||
### Switch |
|
||||||
|
|
||||||
Use the following formatting for switch: |
|
||||||
|
|
||||||
~~~ |
|
||||||
switch ($this->phpType) { |
|
||||||
case 'string': |
|
||||||
$a = (string)$value; |
|
||||||
break; |
|
||||||
case 'integer': |
|
||||||
case 'int': |
|
||||||
$a = (integer)$value; |
|
||||||
break; |
|
||||||
case 'boolean': |
|
||||||
$a = (boolean)$value; |
|
||||||
break; |
|
||||||
default: |
|
||||||
$a = null; |
|
||||||
} |
|
||||||
~~~ |
|
||||||
|
|
||||||
### Code documentation |
|
||||||
|
|
||||||
- Refer ot [phpDoc](http://phpdoc.org/) for documentation syntax. |
|
||||||
- Code without documentation is not allowed. |
|
||||||
- All class files must contain a "file-level" docblock at the top of each file |
|
||||||
and a "class-level" docblock immediately above each class. |
|
||||||
- There is no need to use `@return` if method does return nothing. |
|
||||||
|
|
||||||
#### File |
|
||||||
|
|
||||||
~~~ |
|
||||||
<?php |
|
||||||
/** |
|
||||||
* @link http://www.yiiframework.com/ |
|
||||||
* @copyright Copyright (c) 2008 Yii Software LLC |
|
||||||
* @license http://www.yiiframework.com/license/ |
|
||||||
*/ |
|
||||||
~~~ |
|
||||||
|
|
||||||
#### Class |
|
||||||
|
|
||||||
~~~ |
|
||||||
/** |
|
||||||
* Component is the base class that provides the *property*, *event* and *behavior* features. |
|
||||||
* |
|
||||||
* @include @yii/docs/base-Component.md |
|
||||||
* |
|
||||||
* @author Qiang Xue <qiang.xue@gmail.com> |
|
||||||
* @since 2.0 |
|
||||||
*/ |
|
||||||
class Component extends \yii\base\Object |
|
||||||
~~~ |
|
||||||
|
|
||||||
|
|
||||||
#### Function / method |
|
||||||
|
|
||||||
~~~ |
|
||||||
/** |
|
||||||
* Returns the list of attached event handlers for an event. |
|
||||||
* You may manipulate the returned [[Vector]] object by adding or removing handlers. |
|
||||||
* For example, |
|
||||||
* |
|
||||||
* ~~~ |
|
||||||
* $component->getEventHandlers($eventName)->insertAt(0, $eventHandler); |
|
||||||
* ~~~ |
|
||||||
* |
|
||||||
* @param string $name the event name |
|
||||||
* @return Vector list of attached event handlers for the event |
|
||||||
* @throws Exception if the event is not defined |
|
||||||
*/ |
|
||||||
public function getEventHandlers($name) |
|
||||||
{ |
|
||||||
if (!isset($this->_e[$name])) { |
|
||||||
$this->_e[$name] = new Vector; |
|
||||||
} |
|
||||||
$this->ensureBehaviors(); |
|
||||||
return $this->_e[$name]; |
|
||||||
} |
|
||||||
~~~ |
|
||||||
|
|
||||||
#### Comments |
|
||||||
|
|
||||||
- One-line comments should be started with `//` and not `#`. |
|
||||||
- One-line comment should be on its own line. |
|
||||||
|
|
||||||
Yii application naming conventions |
|
||||||
---------------------------------- |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Other library and framework standards |
|
||||||
------------------------------------- |
|
||||||
|
|
||||||
It's good to be consistent with other frameworks and libraries whose components |
|
||||||
will be possibly used with Yii2. That's why when there are no objective reasons |
|
||||||
to use different style we should use one that's common among most of the popular |
|
||||||
libraries and frameworks. |
|
||||||
|
|
||||||
That's not only about PHP but about JavaScript as well. Since we're using jQuery |
|
||||||
a lot it's better to be consistent with its style as well. |
|
||||||
|
|
||||||
Application style consistency is much more important than consistency with other frameworks and libraries. |
|
||||||
|
|
||||||
- [Symfony 2](http://symfony.com/doc/current/contributing/code/standards.html) |
|
||||||
- [Zend Framework 1](http://framework.zend.com/manual/en/coding-standard.coding-style.html) |
|
||||||
- [Zend Framework 2](http://framework.zend.com/wiki/display/ZFDEV2/Coding+Standards) |
|
||||||
- [Pear](http://pear.php.net/manual/en/standards.php) |
|
||||||
- [jQuery](http://docs.jquery.com/JQuery_Core_Style_Guidelines) |
|
Before Width: | Height: | Size: 298 KiB |
Before Width: | Height: | Size: 16 KiB |
@ -1,192 +0,0 @@ |
|||||||
Alex's Code Review, 2011.11.12 |
|
||||||
============================== |
|
||||||
|
|
||||||
Overall hierarchy |
|
||||||
------------------ |
|
||||||
|
|
||||||
Generally is OK. Like that `Object` and `Component` are now separated. |
|
||||||
I've generated 2 diagrams under `docs/` to see it better as a whole. |
|
||||||
|
|
||||||
> The purpose of separating `Object` from `Component` is to make `Object` |
|
||||||
> a super-light base class that supports properties defined by getter/setters. |
|
||||||
> Note that `Component` is a bit of heavy because it uses two extra member |
|
||||||
> variables to support events and behaviors. |
|
||||||
|
|
||||||
|
|
||||||
Object |
|
||||||
------ |
|
||||||
|
|
||||||
### property feature |
|
||||||
|
|
||||||
Is it OK that `canGetProperty` and `canSetProperty` will return `false` for real |
|
||||||
class members? |
|
||||||
|
|
||||||
> Added $checkVar parameter |
|
||||||
|
|
||||||
### callbacks and expressions |
|
||||||
|
|
||||||
We're using 5.3. What's the reason to support `eval()` in `evaluateExpression` if |
|
||||||
we have anonymous functions? Is that for storing code as string inside of DB (RBAC)? |
|
||||||
|
|
||||||
If we're going to get rid of `eval()`, cosider remaning method to something about callback. |
|
||||||
If not then we definitely need to use anonymous functions in API docs and the guide |
|
||||||
where possible. |
|
||||||
|
|
||||||
> The purpose of evaluateExpression() is to provide a way of evaluating a PHP expression |
|
||||||
> in the context of an object. Will remove it before release if we find no use of it. |
|
||||||
|
|
||||||
>> mdomba: |
|
||||||
>> As eval() is controversial, and anonymous functions can replace all Yii 1 usage of eval() |
|
||||||
>> how about removing it from the beginning and add it only if we find it necessary. |
|
||||||
>> This way we would not be tempted to stick with eval() and will be forced to first try to find alternatives |
|
||||||
|
|
||||||
### Object::create() |
|
||||||
|
|
||||||
#### `__construct` issue |
|
||||||
|
|
||||||
Often a class doesn't have `__construct` implementation and `stdClass` doesn't have |
|
||||||
default one either but Object::create() always expects constructor to be |
|
||||||
defined. See `ObjectTest`. Either `method_exists` call or `Object::__construct` needed. |
|
||||||
|
|
||||||
> Added Object::__construct. |
|
||||||
|
|
||||||
#### How to support object factory like we do with CWidgetFactory? |
|
||||||
|
|
||||||
~~~ |
|
||||||
class ObjectConfig |
|
||||||
{ |
|
||||||
public function configure($class) |
|
||||||
{ |
|
||||||
$config = $this->load($class); |
|
||||||
// apply config to $class |
|
||||||
} |
|
||||||
|
|
||||||
private function load($class) |
|
||||||
{ |
|
||||||
// get class properties from a config file |
|
||||||
// in this method we need to walk all the |
|
||||||
// inheritance hierarchy down to Object itself |
|
||||||
return array( |
|
||||||
'property' => 'value', |
|
||||||
// … |
|
||||||
); |
|
||||||
} |
|
||||||
} |
|
||||||
~~~ |
|
||||||
|
|
||||||
Then we need to add `__construct` to `Object` (or implement `Initalbe`): |
|
||||||
|
|
||||||
~~~ |
|
||||||
class Object |
|
||||||
{ |
|
||||||
public function __construct() |
|
||||||
{ |
|
||||||
$conf = new ObjectConfig(); |
|
||||||
$conf->configure($this); |
|
||||||
} |
|
||||||
} |
|
||||||
~~~ |
|
||||||
|
|
||||||
This way we'll be able to set defaults for any object. |
|
||||||
|
|
||||||
> The key issue here is about how to process the config file. Clearly, we cannot |
|
||||||
> do this for every type of component because it would mean an extra file access |
|
||||||
> for every component type |
|
||||||
|
|
||||||
#### Do we need to support lazy class injection? |
|
||||||
|
|
||||||
Currently there's no way to lazy-inject class into another class property via |
|
||||||
config. Do we need it? If yes then we can probably extend component config to support |
|
||||||
the following: |
|
||||||
|
|
||||||
~~~ |
|
||||||
class Foo extends Object |
|
||||||
{ |
|
||||||
public $prop; |
|
||||||
} |
|
||||||
|
|
||||||
class Bar extends Object |
|
||||||
{ |
|
||||||
public $prop; |
|
||||||
} |
|
||||||
|
|
||||||
$config = array( |
|
||||||
'prop' => array( |
|
||||||
'class' => 'Bar', |
|
||||||
'prop' => 'Hello!', |
|
||||||
), |
|
||||||
); |
|
||||||
|
|
||||||
$foo = Foo::create($config); |
|
||||||
echo $foo->bar->prop; |
|
||||||
// will output Hello! |
|
||||||
~~~ |
|
||||||
|
|
||||||
Should it support infinite nesting level? |
|
||||||
|
|
||||||
> I don't think we need this. Foo::$prop cannot be an object unless it needs it to be. |
|
||||||
> In that case, it can be defined with a setter in which it can handle the object creation |
|
||||||
> based on a configuration array. This is a bit inconvenient, but I think such usage is |
|
||||||
> not very common. |
|
||||||
|
|
||||||
### Why `Event` is `Object`? |
|
||||||
|
|
||||||
There's no need to extend from `Object`. Is there a plan to use `Object` features |
|
||||||
later? |
|
||||||
|
|
||||||
> To use properties defined via getter/setter. |
|
||||||
|
|
||||||
|
|
||||||
Behaviors |
|
||||||
--------- |
|
||||||
|
|
||||||
Overall I wasn't able to use behaviors. See `BehaviorTest`. |
|
||||||
|
|
||||||
### Should behaviors be able to define events for owner components? |
|
||||||
|
|
||||||
Why not? Should be a very good feature in order to make behaviors customizable. |
|
||||||
|
|
||||||
> It's a bit hard to implement it efficiently. I tend not to support it for now |
|
||||||
> unless enough people are requesting for it. |
|
||||||
|
|
||||||
### Multiple behaviors can be attached to the same component |
|
||||||
|
|
||||||
What if we'll have multiple methods / properties / events with the same name? |
|
||||||
|
|
||||||
> The first one takes precedence. This is the same as we do in 1.1. |
|
||||||
|
|
||||||
### How to use Behavior::attach? |
|
||||||
|
|
||||||
Looks like it is used by `Component::attachBehavior` but can't be used without it. |
|
||||||
Why it's public then? Can we move it to `Component?` |
|
||||||
|
|
||||||
> It's public because it is called by Component. It is in Behavior such that |
|
||||||
> it can be overridden by behavior classes to customize the attach process. |
|
||||||
|
|
||||||
Events |
|
||||||
------ |
|
||||||
|
|
||||||
Class itself looks OK. Component part is OK as well but I've not tested |
|
||||||
it carefully. Overall it seems concept is the same as in Yii1. |
|
||||||
|
|
||||||
### Event declaration: the on-method is mostly repetitive for every event. Should we choose a different way of declaring events? |
|
||||||
|
|
||||||
Maybe. People complained previously about too many code for event declaration. |
|
||||||
|
|
||||||
### Should we implement some additional event mechanism, such as global events? |
|
||||||
|
|
||||||
Why use two different implementations in a single application? |
|
||||||
|
|
||||||
Exceptions |
|
||||||
---------- |
|
||||||
|
|
||||||
- Should we convert all errors, warnings and notices to exceptions? |
|
||||||
|
|
||||||
> I think not. We used to do this in early versions of 1.0. We found sometimes |
|
||||||
> very mysterious things would happen which makes error fixing harder rather than |
|
||||||
> easier. |
|
||||||
|
|
||||||
Coding style |
|
||||||
------------ |
|
||||||
|
|
||||||
See `docs/code_style.md`. |
|
@ -0,0 +1,136 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* @link http://www.yiiframework.com/ |
||||||
|
* @copyright Copyright (c) 2008 Yii Software LLC |
||||||
|
* @license http://www.yiiframework.com/license/ |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace yii\base; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Qiang Xue <qiang.xue@gmail.com> |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
class ViewContent extends Component |
||||||
|
{ |
||||||
|
const POS_HEAD = 1; |
||||||
|
const POS_BEGIN = 2; |
||||||
|
const POS_END = 3; |
||||||
|
|
||||||
|
/** |
||||||
|
* @var array |
||||||
|
* |
||||||
|
* Each asset bundle should be declared with the following structure: |
||||||
|
* |
||||||
|
* ~~~ |
||||||
|
* array( |
||||||
|
* 'basePath' => '...', |
||||||
|
* 'baseUrl' => '...', // if missing, the bundle will be published to the "www/assets" folder |
||||||
|
* 'js' => array( |
||||||
|
* 'js/main.js', |
||||||
|
* 'js/menu.js', |
||||||
|
* 'js/base.js' => self::POS_HEAD, |
||||||
|
* 'css' => array( |
||||||
|
* 'css/main.css', |
||||||
|
* 'css/menu.css', |
||||||
|
* ), |
||||||
|
* 'depends' => array( |
||||||
|
* 'jquery', |
||||||
|
* 'yii', |
||||||
|
* 'yii/treeview', |
||||||
|
* ), |
||||||
|
* ) |
||||||
|
* ~~~ |
||||||
|
*/ |
||||||
|
public $bundles; |
||||||
|
|
||||||
|
public $title; |
||||||
|
public $metaTags; |
||||||
|
public $linkTags; |
||||||
|
public $css; |
||||||
|
public $js; |
||||||
|
public $cssFiles; |
||||||
|
public $jsFiles; |
||||||
|
|
||||||
|
public function populate($content) |
||||||
|
{ |
||||||
|
return $content; |
||||||
|
} |
||||||
|
|
||||||
|
public function reset() |
||||||
|
{ |
||||||
|
$this->title = null; |
||||||
|
$this->metaTags = null; |
||||||
|
$this->linkTags = null; |
||||||
|
$this->css = null; |
||||||
|
$this->js = null; |
||||||
|
$this->cssFiles = null; |
||||||
|
$this->jsFiles = null; |
||||||
|
} |
||||||
|
|
||||||
|
public function registerBundle($name) |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public function getMetaTag($key) |
||||||
|
{ |
||||||
|
return isset($this->metaTags[$key]) ? $this->metaTags[$key] : null; |
||||||
|
} |
||||||
|
|
||||||
|
public function setMetaTag($key, $tag) |
||||||
|
{ |
||||||
|
$this->metaTags[$key] = $tag; |
||||||
|
} |
||||||
|
|
||||||
|
public function getLinkTag($key) |
||||||
|
{ |
||||||
|
return isset($this->linkTags[$key]) ? $this->linkTags[$key] : null; |
||||||
|
} |
||||||
|
|
||||||
|
public function setLinkTag($key, $tag) |
||||||
|
{ |
||||||
|
$this->linkTags[$key] = $tag; |
||||||
|
} |
||||||
|
|
||||||
|
public function getCss($key) |
||||||
|
{ |
||||||
|
return isset($this->css[$key]) ? $this->css[$key]: null; |
||||||
|
} |
||||||
|
|
||||||
|
public function setCss($key, $css) |
||||||
|
{ |
||||||
|
$this->css[$key] = $css; |
||||||
|
} |
||||||
|
|
||||||
|
public function getCssFile($key) |
||||||
|
{ |
||||||
|
return isset($this->cssFiles[$key]) ? $this->cssFiles[$key]: null; |
||||||
|
} |
||||||
|
|
||||||
|
public function setCssFile($key, $file) |
||||||
|
{ |
||||||
|
$this->cssFiles[$key] = $file; |
||||||
|
} |
||||||
|
|
||||||
|
public function getJs($key, $position = self::POS_END) |
||||||
|
{ |
||||||
|
return isset($this->js[$position][$key]) ? $this->js[$position][$key] : null; |
||||||
|
} |
||||||
|
|
||||||
|
public function setJs($key, $js, $position = self::POS_END) |
||||||
|
{ |
||||||
|
$this->js[$position][$key] = $js; |
||||||
|
} |
||||||
|
|
||||||
|
public function getJsFile($key, $position = self::POS_END) |
||||||
|
{ |
||||||
|
return isset($this->jsFiles[$position][$key]) ? $this->jsFiles[$position][$key] : null; |
||||||
|
} |
||||||
|
|
||||||
|
public function setJsFile($key, $file, $position = self::POS_END) |
||||||
|
{ |
||||||
|
$this->jsFiles[$position][$key] = $file; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,44 @@ |
|||||||
|
<?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 ViewEvent extends Event |
||||||
|
{ |
||||||
|
/** |
||||||
|
* @var string the rendering result of [[View::renderFile()]]. |
||||||
|
* Event handlers may modify this property and the modified output will be |
||||||
|
* returned by [[View::renderFile()]]. This property is only used |
||||||
|
* by [[View::EVENT_AFTER_RENDER]] event. |
||||||
|
*/ |
||||||
|
public $output; |
||||||
|
/** |
||||||
|
* @var string the view file path that is being rendered by [[View::renderFile()]]. |
||||||
|
*/ |
||||||
|
public $viewFile; |
||||||
|
/** |
||||||
|
* @var boolean whether to continue rendering the view file. Event handlers of |
||||||
|
* [[View::EVENT_BEFORE_RENDER]] may set this property to decide whether |
||||||
|
* to continue rendering the current view file. |
||||||
|
*/ |
||||||
|
public $isValid = true; |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor. |
||||||
|
* @param string $viewFile the view file path that is being rendered by [[View::renderFile()]]. |
||||||
|
* @param array $config name-value pairs that will be used to initialize the object properties |
||||||
|
*/ |
||||||
|
public function __construct($viewFile, $config = array()) |
||||||
|
{ |
||||||
|
$this->viewFile = $viewFile; |
||||||
|
parent::__construct($config); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,246 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* @link http://www.yiiframework.com/ |
||||||
|
* @copyright Copyright (c) 2008 Yii Software LLC |
||||||
|
* @license http://www.yiiframework.com/license/ |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace yii\web; |
||||||
|
|
||||||
|
use yii\widgets\ActiveForm; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Qiang Xue <qiang.xue@gmail.com> |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
class UploadedFile extends \yii\base\Object |
||||||
|
{ |
||||||
|
private static $_files; |
||||||
|
private $_name; |
||||||
|
private $_tempName; |
||||||
|
private $_type; |
||||||
|
private $_size; |
||||||
|
private $_error; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor. |
||||||
|
* Instead of using the constructor to create a new instance, |
||||||
|
* you should normally call [[getInstance()]] or [[getInstances()]] |
||||||
|
* to obtain new instances. |
||||||
|
* @param string $name the original name of the file being uploaded |
||||||
|
* @param string $tempName the path of the uploaded file on the server. |
||||||
|
* @param string $type the MIME-type of the uploaded file (such as "image/gif"). |
||||||
|
* @param integer $size the actual size of the uploaded file in bytes |
||||||
|
* @param integer $error the error code |
||||||
|
*/ |
||||||
|
public function __construct($name, $tempName, $type, $size, $error) |
||||||
|
{ |
||||||
|
$this->_name = $name; |
||||||
|
$this->_tempName = $tempName; |
||||||
|
$this->_type = $type; |
||||||
|
$this->_size = $size; |
||||||
|
$this->_error = $error; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* String output. |
||||||
|
* This is PHP magic method that returns string representation of an object. |
||||||
|
* The implementation here returns the uploaded file's name. |
||||||
|
* @return string the string representation of the object |
||||||
|
*/ |
||||||
|
public function __toString() |
||||||
|
{ |
||||||
|
return $this->_name; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns an uploaded file for the given model attribute. |
||||||
|
* The file should be uploaded using [[ActiveForm::fileInput()]]. |
||||||
|
* @param \yii\base\Model $model the data model |
||||||
|
* @param string $attribute the attribute name. The attribute name may contain array indexes. |
||||||
|
* For example, '[1]file' for tabular file uploading; and 'file[1]' for an element in a file array. |
||||||
|
* @return UploadedFile the instance of the uploaded file. |
||||||
|
* Null is returned if no file is uploaded for the specified model attribute. |
||||||
|
* @see getInstanceByName |
||||||
|
*/ |
||||||
|
public static function getInstance($model, $attribute) |
||||||
|
{ |
||||||
|
$name = ActiveForm::getInputName($model, $attribute); |
||||||
|
return static::getInstanceByName($name); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns all uploaded files for the given model attribute. |
||||||
|
* @param \yii\base\Model $model the data model |
||||||
|
* @param string $attribute the attribute name. The attribute name may contain array indexes |
||||||
|
* for tabular file uploading, e.g. '[1]file'. |
||||||
|
* @return UploadedFile[] array of UploadedFile objects. |
||||||
|
* Empty array is returned if no available file was found for the given attribute. |
||||||
|
*/ |
||||||
|
public static function getInstances($model, $attribute) |
||||||
|
{ |
||||||
|
$name = ActiveForm::getInputName($model, $attribute); |
||||||
|
return static::getInstancesByName($name); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns an uploaded file according to the given file input name. |
||||||
|
* The name can be a plain string or a string like an array element (e.g. 'Post[imageFile]', or 'Post[0][imageFile]'). |
||||||
|
* @param string $name the name of the file input field. |
||||||
|
* @return UploadedFile the instance of the uploaded file. |
||||||
|
* Null is returned if no file is uploaded for the specified name. |
||||||
|
*/ |
||||||
|
public static function getInstanceByName($name) |
||||||
|
{ |
||||||
|
$files = static::loadFiles(); |
||||||
|
return isset($files[$name]) ? $files[$name] : null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns an array of uploaded files corresponding to the specified file input name. |
||||||
|
* This is mainly used when multiple files were uploaded and saved as 'files[0]', 'files[1]', |
||||||
|
* 'files[n]'..., and you can retrieve them all by passing 'files' as the name. |
||||||
|
* @param string $name the name of the array of files |
||||||
|
* @return UploadedFile[] the array of CUploadedFile objects. Empty array is returned |
||||||
|
* if no adequate upload was found. Please note that this array will contain |
||||||
|
* all files from all sub-arrays regardless how deeply nested they are. |
||||||
|
*/ |
||||||
|
public static function getInstancesByName($name) |
||||||
|
{ |
||||||
|
$files = static::loadFiles(); |
||||||
|
if (isset($files[$name])) { |
||||||
|
return array($files[$name]); |
||||||
|
} |
||||||
|
$results = array(); |
||||||
|
foreach ($files as $key => $file) { |
||||||
|
if (strpos($key, "{$name}[") === 0) { |
||||||
|
$results[] = self::$_files[$key]; |
||||||
|
} |
||||||
|
} |
||||||
|
return $results; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Cleans up the loaded UploadedFile instances. |
||||||
|
* This method is mainly used by test scripts to set up a fixture. |
||||||
|
*/ |
||||||
|
public static function reset() |
||||||
|
{ |
||||||
|
self::$_files = null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Saves the uploaded file. |
||||||
|
* Note that this method uses php's move_uploaded_file() method. If the target file `$file` |
||||||
|
* already exists, it will be overwritten. |
||||||
|
* @param string $file the file path used to save the uploaded file |
||||||
|
* @param boolean $deleteTempFile whether to delete the temporary file after saving. |
||||||
|
* If true, you will not be able to save the uploaded file again in the current request. |
||||||
|
* @return boolean true whether the file is saved successfully |
||||||
|
* @see error |
||||||
|
*/ |
||||||
|
public function saveAs($file, $deleteTempFile = true) |
||||||
|
{ |
||||||
|
if ($this->_error == UPLOAD_ERR_OK) { |
||||||
|
if ($deleteTempFile) { |
||||||
|
return move_uploaded_file($this->_tempName, $file); |
||||||
|
} elseif (is_uploaded_file($this->_tempName)) { |
||||||
|
return copy($this->_tempName, $file); |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return string the original name of the file being uploaded |
||||||
|
*/ |
||||||
|
public function getName() |
||||||
|
{ |
||||||
|
return $this->_name; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return string the path of the uploaded file on the server. |
||||||
|
* Note, this is a temporary file which will be automatically deleted by PHP |
||||||
|
* after the current request is processed. |
||||||
|
*/ |
||||||
|
public function getTempName() |
||||||
|
{ |
||||||
|
return $this->_tempName; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return string the MIME-type of the uploaded file (such as "image/gif"). |
||||||
|
* Since this MIME type is not checked on the server side, do not take this value for granted. |
||||||
|
* Instead, use [[FileHelper::getMimeType()]] to determine the exact MIME type. |
||||||
|
*/ |
||||||
|
public function getType() |
||||||
|
{ |
||||||
|
return $this->_type; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return integer the actual size of the uploaded file in bytes |
||||||
|
*/ |
||||||
|
public function getSize() |
||||||
|
{ |
||||||
|
return $this->_size; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns an error code describing the status of this file uploading. |
||||||
|
* @return integer the error code |
||||||
|
* @see http://www.php.net/manual/en/features.file-upload.errors.php |
||||||
|
*/ |
||||||
|
public function getError() |
||||||
|
{ |
||||||
|
return $this->_error; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return boolean whether there is an error with the uploaded file. |
||||||
|
* Check [[error]] for detailed error code information. |
||||||
|
*/ |
||||||
|
public function getHasError() |
||||||
|
{ |
||||||
|
return $this->_error != UPLOAD_ERR_OK; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Creates UploadedFile instances from $_FILE. |
||||||
|
* @return array the UploadedFile instances |
||||||
|
*/ |
||||||
|
private static function loadFiles() |
||||||
|
{ |
||||||
|
if (self::$_files === null) { |
||||||
|
self::$_files = array(); |
||||||
|
if (isset($_FILES) && is_array($_FILES)) { |
||||||
|
foreach ($_FILES as $class => $info) { |
||||||
|
self::loadFilesRecursive($class, $info['name'], $info['tmp_name'], $info['type'], $info['size'], $info['error']); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return self::$_files; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Creates UploadedFile instances from $_FILE recursively. |
||||||
|
* @param string $key key for identifying uploaded file: class name and sub-array indexes |
||||||
|
* @param mixed $names file names provided by PHP |
||||||
|
* @param mixed $tempNames temporary file names provided by PHP |
||||||
|
* @param mixed $types file types provided by PHP |
||||||
|
* @param mixed $sizes file sizes provided by PHP |
||||||
|
* @param mixed $errors uploading issues provided by PHP |
||||||
|
*/ |
||||||
|
private static function loadFilesRecursive($key, $names, $tempNames, $types, $sizes, $errors) |
||||||
|
{ |
||||||
|
if (is_array($names)) { |
||||||
|
foreach ($names as $i => $name) { |
||||||
|
self::loadFilesRecursive($key . '[' . $i . ']', $name, $tempNames[$i], $types[$i], $sizes[$i], $errors[$i]); |
||||||
|
} |
||||||
|
} else { |
||||||
|
self::$_files[$key] = new self($names, $tempNames, $types, $sizes, $errors); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue