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