Updated Yii Framework to 1.1.15 (#246)

This commit is contained in:
Lucas Bartholemy 2014-10-21 18:41:31 +02:00
parent 3aad9e1921
commit bc4fb665f7
1071 changed files with 14973 additions and 5697 deletions

View File

@ -24,7 +24,8 @@
* @package humhub.components * @package humhub.components
* @since 0.5 * @since 0.5
*/ */
class HClientScript extends CClientScript { class HClientScript extends CClientScript
{
/** /**
* @var array the registered HTML code blocks (key => code) * @var array the registered HTML code blocks (key => code)
@ -37,28 +38,13 @@ class HClientScript extends CClientScript {
* @param String $name * @param String $name
* @param String $value * @param String $value
*/ */
public function setJavascriptVariable($name, $value) { public function setJavascriptVariable($name, $value)
{
$jsCode = "var " . $name . " = '" . $value . "';\n"; $jsCode = "var " . $name . " = '" . $value . "';\n";
$this->registerScript('jsVar_' . $name, $jsCode, CClientScript::POS_BEGIN); $this->registerScript('jsVar_' . $name, $jsCode, CClientScript::POS_BEGIN);
} }
/**
* Registers a script file
*
* @param String $src
* @param String $position
*/
public function registerScriptFile($src, $position = NULL) {
# if(Yii::app()->getRequest()->getIsAjaxRequest()) {
# Yii::app()->clientScript->registerScript('loadScript_'.$src, "loadJavaScript(\"".$src."\");", CClientScript::POS_BEGIN);
# } else {
return parent::registerScriptFile($src, $position);
# }
#registerScriptFile
}
/** /**
* Registers a piece of html code. * Registers a piece of html code.
* @param string $id ID that uniquely identifies this piece of HTML code * @param string $id ID that uniquely identifies this piece of HTML code
@ -66,7 +52,8 @@ class HClientScript extends CClientScript {
* *
* @return CClientScript the CClientScript object itself (to support method chaining, available since version 1.1.5). * @return CClientScript the CClientScript object itself (to support method chaining, available since version 1.1.5).
*/ */
public function registerHtml($id, $html) { public function registerHtml($id, $html)
{
$this->hasScripts = true; $this->hasScripts = true;
@ -82,7 +69,8 @@ class HClientScript extends CClientScript {
* *
* @param string $output the output to be inserted with scripts. * @param string $output the output to be inserted with scripts.
*/ */
public function renderBodyEnd(&$output) { public function renderBodyEnd(&$output)
{
if (!isset($this->scriptFiles[self::POS_END]) && !isset($this->scripts[self::POS_END]) && !isset($this->scripts[self::POS_READY]) && !isset($this->scripts[self::POS_LOAD]) && !count($this->htmls) == 0) if (!isset($this->scriptFiles[self::POS_END]) && !isset($this->scripts[self::POS_END]) && !isset($this->scripts[self::POS_READY]) && !isset($this->scripts[self::POS_LOAD]) && !count($this->htmls) == 0)
return; return;

1660
protected/vendors/yii/CHANGELOG vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
The Yii framework is free software. It is released under the terms of The Yii framework is free software. It is released under the terms of
the following BSD License. the following BSD License.
Copyright © 2008-2011 by Yii Software LLC (http://www.yiisoft.com) Copyright (c) 2008-2013 by Yii Software LLC (http://www.yiisoft.com)
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without

64
protected/vendors/yii/README vendored Normal file
View File

@ -0,0 +1,64 @@
Yii Web Programming Framework
=============================
Thank you for choosing Yii - a high-performance component-based PHP framework.
INSTALLATION
------------
Please make sure the release file is unpacked under a Web-accessible
directory. You shall see the following files and directories:
demos/ demos
framework/ framework source files
requirements/ requirement checker
CHANGELOG describing changes in every Yii release
LICENSE license of Yii
README this file
UPGRADE upgrading instructions
REQUIREMENTS
------------
The minimum requirement by Yii is that your Web server supports
PHP 5.1.0 or above. Yii has been tested with Apache HTTP server
on Windows and Linux operating systems.
Please access the following URL to check if your Web server reaches
the requirements by Yii, assuming "YiiPath" is where Yii is installed:
http://hostname/YiiPath/requirements/index.php
QUICK START
-----------
Yii comes with a command line tool called "yiic" that can create
a skeleton Yii application for you to start with.
On command line, type in the following commands:
$ cd YiiPath/framework (Linux)
cd YiiPath\framework (Windows)
$ ./yiic webapp ../testdrive (Linux)
yiic webapp ..\testdrive (Windows)
The new Yii application will be created at "YiiPath/testdrive".
You can access it with the following URL:
http://hostname/YiiPath/testdrive/index.php
WHAT's NEXT
-----------
Please visit the project website for tutorials, class reference
and join discussions with other Yii users.
The Yii Developer Team
http://www.yiiframework.com

502
protected/vendors/yii/UPGRADE vendored Normal file
View File

@ -0,0 +1,502 @@
Upgrading Instructions for Yii Framework v1.1.15
================================================
!!!IMPORTANT!!!
The following upgrading instructions are cumulative. That is,
if you want to upgrade from version A to version C and there is
version B between A and C, you need to following the instructions
for both A and B.
General upgrade instructions
----------------------------
- Make a backup.
- Clean up your 'assets' folder.
- Replace 'framework' dir with the new one or point GIT to a fresh
release and update.
- Check if everything is OK, if not — revert from backup and post
issues to Yii issue tracker.
Upgrading from v1.1.14
----------------------
Upgrading from v1.1.13
----------------------
- CActiveRecord::count() now respects group by and having. If your code relied
on ignoring it your application may break and should be updated.
- Vendors: phlymail's Net_IDNA was replaced by PEAR Net_IDNA2. The latter library is better maintained than the former.
In case your code relies on bundled phlymail's Net_IDNA you should change it a bit. Old way of encoding IDNs:
require_once(Yii::getPathOfAlias('system.vendors.idna_convert').DIRECTORY_SEPARATOR.'idna_convert.class.php');
$idnaConvert=new idna_convert();
$result=$idnaConvert->encode($value);
New:
require_once(Yii::getPathOfAlias('system.vendors.Net_IDNA2.Net').DIRECTORY_SEPARATOR.'IDNA2.php');
$idna=new Net_IDNA2();
$result=$idna->encode($value);
- CAPTCHA appearance has been changed. Non-free Duality.ttf font (used by CCaptchaAction) replaced by open/free
SpicyRice.ttf. New font is distributed under SIL Open Font License version 1.1. Do not forget to adjust font path
in case your application relies on Duality.ttf font file.
- CSecurityManager::computeHMAC() method is now public and third parameter has been added. You must change signature
of this method in the extended child class to fit new circumstances. Otherwise an E_STRICT error will be issued.
- CClientScript::registerScriptFile() and CClientScript::registerScript() methods signature changed.
Update your subclasses that override registerScriptFile() or registerScript() if any.
- CActiveRecord::refreshMetaData() now clears meta data for all objects of the particular Active Record class.
Also CActiveRecord::refreshMetaData() will not create new meta data at once - new CActiveRecordMetaData instance
will be created on the first demand.
- Oracle related note: in case you're using COciSchema::resetSequence() or CDbSchema::resetSequence() methods with
the Oracle database, keep in mind that its behavior has changed to be consistent with the same methods for
the other database management systems. Please refer to its documentation for more details and don't forget
to adjust your code respectively.
- Signature of the CJuiInputWidget::resolveNameID() method has changed. If you're overriding this method you must
change your code to fit it. This method now accepts two parameters, it means you have to adjust code of the
overlapped descendant method signature as follows:
protected function resolveNameID($nameProperty='name',$attributeProperty='attribute')
And ancestor method call to:
parent::resolveNameID($nameProperty,$attributeProperty);
- In case you've used your own relation types extended from `CHasOneRelation` or
`CHasManyRelation` make sure you update these to reflect moving `through` property
from both these to `CActiveRelation`.
- CSecurityManager::generateRandomKey() has been deprecated in favor of CSecurityManager::generateRandomString().
Try not to use it anymore and avoid CSecurityManager::generateRandomKey() method in your code.
Upgrading from v1.1.12
----------------------
- Both jQuery and jQueryUI were updated. Check [jQuery UI upgrade guide](http://jqueryui.com/upgrade-guide/1.9/)
and [jQuery release notes](http://blog.jquery.com/2012/08/09/jquery-1-8-released/).
- We completed the behavior of CFormatter::sizeFormat() which has been introduced in Yii 1.1.11. If you are using it with your own translation file
you have to move your translations to the `yii` category in `yii.php` file which is handled by the application component `coreMessages`.
We also fixed the default translation strings to be correct English and apply to choice format, so you have to adjust your translation file keys.
- Be sure to clean all your existing cache during the upgrade. The cache values from CDbCommand has been
changed to an array to be able to store false values (returned when no records are found).
- Make sure all your event handlers in behaviors are public methods, as we are not supporting protected methods as event handlers anymore.
- We fixed the calls to CActiveRecord::beforeFind() for consistency so that beforeFind() now always gets called for every relation
on eager loading even if the main query does not return a result. This has been the case for all CActiveRecord::find*()-methods
already but now also applies for findBySql() and findAllBySql().
- Criteria modification in CActiveRecord::beforeFind() did not apply to the query when model was loaded in a relational context.
Since version 1.1.13 changes to query criteria made in beforeFind() now also apply to the query when model is loaded in a relational context.
The main problem here is that you can not use the `t`-alias for your table anymore, you have to change your code to
use the table alias currently in use as this is different in relational context.
You can get that alias by calling `$this->getTableAlias();` in your active record class
or `$this->owner->getTableAlias()` in behavior context.
Example:
$criteria->condition = 't.myfield = 1';
You need to change that to:
$alias = $this->owner->getTableAlias();
$criteria->condition = $alias.'.myfield = 1';
- Make sure you are using `CCaptcha::checkRequirements()` method for checking whether CAPTCHA could be rendered successfully in your environment.
`extension_loaded('gd')` expression is not enough and wrong because CAPTCHA could be rendered via ImageMagick with fallback to GD since 1.1.13
(thus checking code is not simple as it seems).
- In case you're using MSSQL driver make sure authentication credentials you use have permissions to use
`sys.extended_properties` system view. This is critical for retrieving additional metadata on tables.
Upgrading from v1.1.11
----------------------
- Changes in CCookieCollection::add() (introduced in 1.1.11) were reverted as they were triggering E_STRICT on some old PHP-versions
If your application relies on these newly added changes. You should change your code from
$cookies->add(new CHttpCookie($name, $value));
to
$cookies[$name] = new CHttpCookie($name, $value);
- CActiveRecord::resetScope() method signature changed. Please update your subclasses that override resetScope() if any.
Upgrading from v1.1.10
----------------------
- API of public method CConsoleCommand::confirm() changed. If you are overriding this method make sure to update your code.
The method now has a 2nd parameter for the default value which will be used if no selection is made, so you have to
adjust the signature to fit
public function confirm($message,$default=false)
and the parent call to
parent::confirm($message,$default);
- API of protected method CConsoleCommand::afterAction() changed, if you are overriding this method make sure to update your code.
method now has a 3rd parameter for application exit code, so you have to adjust the signature to fit
protected function afterAction($action,$params,$exitCode=0)
and the parent call to
parent::afterAction($action,$params,$exitCode);
- CDateFormat::format() now will return null if the parameter $time is null. Previously it would return 1/1/1970.
- If you are using CJavaScript::encode in your application with parameter coming
from user input, set second argument to true:
CJavaScript::encode($userInput, true);
It will disable prefixing parameters with "js:". If you need to pass JavaScript
expression it's now preferrable to wrap these with CJavaScriptExpression:
CJavaScript::encode(new CJavaScriptExpression('alert("Yii!");'), true);
Note that second "safe" parameter doesn't affect CJavaScriptExpression in any way.
Upgrading from v1.1.9
---------------------
- Previously xSendFile() was returning false if the file was not found.
This has been removed to allow relative file paths. If you are relying on this check,
you will need to do it manually before calling xSendFile().
Upgrading from v1.1.8
---------------------
- CConfiguration::createObject, CController::paginate and CHtml::getActiveId deprecated since 1.0.x were removed. Use
Yii::createComponent, new CPagination directly and CHtml::activeId respectively.
- In CErrorHandler::handleException() the checking for ajax call has been removed
as it was preventing to customize the display of the exception during an ajax call.
- Previously in case of validation error the CSS "error" class was not added to the row container at all when
checkBoxList or radioButtonList where used. This is fixed now and proper "error" CSS class is added to the row
container but in case of validation error, all labels from the list are shown in red because of the CSS rule.
To fix this and display only the attribute label in red:
in <projectdir>/css/form.css the line:
div.form div.error label
should be changed to
div.form div.error label:first-child
- If you've used "through" ActiveRecord option in your relation definitions it's good to update code as shown below.
Old style of defining this option still works but is now deprecated.
Change
~~~
class Group extends CActiveRecord
{
public function relations()
{
return array(
'roles'=>array(self::HAS_MANY,'Role','group_id'),
'users'=>array(self::HAS_MANY,'User','user_id','through'=>'roles'),
);
}
}
~~~
to
~~~
class Group extends CActiveRecord
{
public function relations()
{
return array(
'roles'=>array(self::HAS_MANY,'Role','group_id'),
'users'=>array(self::HAS_MANY,'User',array('user_id'=>'id'),'through'=>'roles'),
);
}
}
~~~
Upgrading from v1.1.7
---------------------
- CDbAuthManager will now quote columns and tables referenced in its SQL code.
If your auth tables were created in a case-insensitive fashion (e.g. on PostgreSQL)
while your DBMS is case-sensitive, this change may cause DB query errors.
To fix this issue, you will have to rename the table names and columns, or re-create
the auth tables by following the SQL code given in framework/web/auth/*.sql.
- jQuery was upgraded to 1.6.1. Check your client side code and if you have issues consider
downgrading to 1.5.1 or 1.4.4.
Upgrading from v1.1.6
---------------------
- Make sure you are using latest stable PHPUnit 3.5 if you are using unit tests.
Upgrading from v1.1.5
---------------------
- In CActiveRecord::relations(), if a relation involves composite foreign keys, the foreign key
columns must be separated by commas now. Previously, the columns can be separated by either
commas or spaces. If your mode code are generated by Gii or yiic shell, you do not need to
worry about this.
- CLDR data was updated to a newest available version so data formats, month
names and other regional data can be changed.
Upgrading from v1.1.4
---------------------
- CHtml will no longer render null attributes for HTML tags. This means if $htmlOptions is
array('class'=>null), it will no longer render the 'class' attribute in the HTML tag.
it would render the class attribute as class="". We expect this will not cause much trouble
in upgrading. However, in case problems happen, you may set the attribute to be an empty string
to solve them.
- Now by default CWebLogRoute does not render logs in FireBug for ajax calls.
To get logs rendered for ajax calls in FireBug set CWebLogRoute::ignoreAjaxInFireBug to false
- The implementation of CCache::flush() was changed a little. Child classes should now implement
a flushValues() method. If you use any custom cache class with flush functionality, you should
rename the flush method accordingly.
- The prompt and empty options used in CHtml methods will NOT be HTML-encoded anymore. It will now
always convert ">" and "<" into "&gt;" and "lt;", respectively. This should be sufficient in most
cases. But if your application uses some other special characters, or if you allow user inputs
to be used as prompt and empty text labels, please call CHtml::encode() explicitly on these option
values.
Upgrading from v1.1.3
---------------------
- Zii was merged into Yii so if you are using SVN to keep framework
up to date, you'll need to delete 'framework/zii' and then update it.
Upgrading from v1.1.2
---------------------
- When using the skin feature, you now need to explicitly configure
the 'enableSkin' property of 'widgetFactory' application component
to be true. Also, if you have configured the 'widgets' property, you
should rename it to be 'skinnableWidgets'. These changes are due to
the introduction of the global widget customization feature.
Please see the guide (the "Theming" section) for more details.
- CAutoComplete is now deprecated and will be removed in Yii 1.2. Consider
using CJuiAutoComplete.
- Now it's not possible to reuse CActiveFinder. So if you have code like this:
$finder = Post::model()->with('comments');
$posts1 = $finder->findAll();
$posts2 = $finder->findAll();
you should rewrite it to:
$posts1 = Post::model()->with('comments');
$posts2 = Post::model()->with('comments');
- The 'condition' declared in the scopes of the related AR classes will now
be put in the 'ON' clause of the JOIN statement when performing relational AR queries.
Upgrading from v1.1.1
---------------------
Upgrading from v1.1.0
---------------------
- CHtml::beginForm() will automatically generate hidden fields to represent
the parameters in the query string when the form uses GET method.
To avoid submitting duplicated query parameters, you may use createUrl()
to explicitly specify the action of the form. You may also need to remove
the hidden fields that you previously render for the same purpose.
- The code generated by yiic tool is changed. If you are using yiic tool
to generate new CRUD code on a previously generated skeleton, you are recommended
to run "yiic webapp" again to re-generate the skeleton. Make sure you backup
your work before you do this.
- CMenu now renders the 'active' CSS class for the 'li' tag instead of the
hyperlink tag. You should adjust your CSS code accordingly if you use CMenu
in your application.
- CUrlManager::parsePathInfo() is changed to be non-static. If you override
this method or your existing code calls this method directly (neither is common),
you need to change your code accordingly.
- CController::forward() will exit the application by default now. If you want
to keep the old behavior, you may pass false as the second parameter.
- The jQuery copy included in the framework has been upgraded to version 1.4.2.
This may cause some incompatibility problems to your existing jQuery code or plugins.
If you want to keep using version 1.3.2, you may do so by configuring
CClientScript::scriptMap property.
- The default theme for JQuery UI widgets was changed from 'smoothness' to 'base'.
If you are using 'smoothness', you will need to manually download this theme from
jqueryui.com and configure the 'theme' property of the JQuery UI widgets accordingly.
Upgrading from v1.1rc
---------------------
- CRudColumn is renamed as CButtonColumn
- CDataColumn.dataField and dataExpression are renamed as name and value, respectively
- The alias name for the primary table in an AR query is fixed to be 't'
Upgrading from v1.1b
--------------------
Upgrading from v1.1a
--------------------
- CSort::attributes is changed. Now the array keys refer to attribute names
and array values refer to virtual attribute definitions. Please read the
API documentation for this property to learn more details. This change will
affect your code only when you explicitly specify this property.
Upgrading from v1.0.x
---------------------
- Application and module parameter names are changed to be case-sensitive.
In 1.0.x, they are case-insensitive.
- For tabular input, using Field[$i] is not valid anymore. Attribute names
should look like [$i]Field in order to support array-typed fields
(e.g. [$i]Field[$index]).
- Please read the Guide for further details on how to upgrade from v1.0.x to v1.1.
Upgrading from v1.0.12
----------------------
Upgrading from v1.0.11
----------------------
Upgrading from v1.0.10
----------------------
Upgrading from v1.0.9
---------------------
Upgrading from v1.0.8
---------------------
- ActiveRecord lazy loading is changed for optimization purpose. Previously,
when lazy loading occurs, the related table will be joined with the primary
table. Now, the related table will be queried without joining the primary table.
As a result, if you are using lazy loading and the corresponding relation
declaration includes reference to the primary table, the query will fail.
To fix this problem, please specify the lazy loading query options with the
actual primary table column values.
Upgrading from v1.0.7
---------------------
- A directory imported using Yii::import() will have precedence over
any existing include paths. For example, if we import 'application.models.*',
then the corresponding directory will be searched before any other
existing include paths. This also means, a directory imported later will
have precedence over directories imported earlier. Previously, this order
was reversed. This change may affect you if you have several classes with
the same name and they are imported via different directories. You will need
to adjust the import order of these directories to make sure your existing
applications are not broken due to this change.
Upgrading from v1.0.6
---------------------
- Default named scope will no longer be applied to INSERT, UPDATE and
DELETE queries. It is only applied to SELECT queries. You should be aware
of this change if you override CActiveRecord::defaultScope() in your code.
- The signature of CWebUser::logout() is changed. If you override this method,
you will need to modify your method declaration accordingly.
Upgrading from v1.0.5
---------------------
Upgrading from v1.0.4
---------------------
- CWebUser::checkAccess() takes an additional parameter to allow caching
the access check results. If you override this method, you will need to
modify your method declaration accordingly. Because the new parameter will
enable caching the access check results by default, please double check
your code containing this method call to make sure the behavior is as expected.
- CDateParser has been renamed to CDateTimeParser
Upgrading from v1.0.3
---------------------
- The signature of CWebModule::init() is modified. Its parameter is removed.
If your application uses modules, you have to modify your module class
files accordingly.
Upgrading from v1.0.2
---------------------
- Controllers that are organized in subdirectories are now referenced
using the ID format "path/to/xyz". Previously it was "path.to.xyz".
If you use "path.to.xyz" in your application, you have to modify it
to "path/to/xyz".
- CHtml::coreScript() is removed. If you used this in your application,
please use the following alternative:
Yii::app()->clientScript->registerCoreScript($name);
Upgrading from v1.0.1
---------------------
- Due to the introduction of the scenario-based massive assignment feature,
we removed CActiveRecord::protectedAttributes(). Please use safeAttributes()
to specify which attributes are safe to be massively assigned.
For more details about scenario-based assignment and validation,
please read the following tutorial section:
http://www.yiiframework.com/doc/guide/form.model#securing-attribute-assignments
- The signature of CModel::validate() has been changed to:
CModel::validate($scenario='', $attributes=null)
That is, the order of the two parameters has been swapped. If your application
contains code that invokes the validate() method (of either a CFormModel
or a CActiveRecord object) with some parameter, please make sure you fix
the parameter order.
- The usage of CActiveRecord::with() and the 'with' option in relations
has been changed. In order to query child relations, we should specify the 'with'
parameter/option like the following now:
Post::model()->with(array('comments', 'author.profile'))->findAll();
Previously, this should be written as:
Post::model()->with(array('comments', 'author'=>'profile'))->findAll();
If your code does not involve child relations (like 'profile' in the above),
nothing needs to be changed.
This change has been introduced in order to support dynamic relational
query options. For example, we can specify that comments be sorted in
descending order (assuming in the relations() method it is specified as
ascending order):
Post::model()->with(array(
'comments'=>array('order'=>'createTime DESC'),
'author.profile',
))->findAll();
Upgrading from v1.0.0
---------------------
- An $scenario parameter is added to both CModel::beforeValidate() and afterValidate().
If you override these methods in your child classes (form models, AR classes),
make sure you change the method signature accordingly.

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
* @package system * @package system
* @since 1.0 * @since 1.0
@ -80,7 +80,7 @@ class YiiBase
*/ */
public static function getVersion() public static function getVersion()
{ {
return '1.1.13'; return '1.1.15';
} }
/** /**
@ -287,8 +287,14 @@ class YiiBase
return $alias; return $alias;
} }
else else
throw new CException(Yii::t('yii','Alias "{alias}" is invalid. Make sure it points to an existing directory.', {
array('{alias}'=>$namespace))); // try to autoload the class with an autoloader
if (class_exists($alias,true))
return self::$_imports[$alias]=$alias;
else
throw new CException(Yii::t('yii','Alias "{alias}" is invalid. Make sure it points to an existing directory or file.',
array('{alias}'=>$namespace)));
}
} }
if(($pos=strrpos($alias,'.'))===false) // a simple class name if(($pos=strrpos($alias,'.'))===false) // a simple class name
@ -612,6 +618,9 @@ class YiiBase
* any other existing autoloaders. * any other existing autoloaders.
* @param callback $callback a valid PHP callback (function name or array($className,$methodName)). * @param callback $callback a valid PHP callback (function name or array($className,$methodName)).
* @param boolean $append whether to append the new autoloader after the default Yii autoloader. * @param boolean $append whether to append the new autoloader after the default Yii autoloader.
* Be careful using this option as it will disable {@link enableIncludePath autoloading via include path}
* when set to true. After this the Yii autoloader can not rely on loading classes via simple include anymore
* and you have to {@link import} all classes explicitly.
*/ */
public static function registerAutoloader($callback, $append=false) public static function registerAutoloader($callback, $append=false)
{ {
@ -656,6 +665,7 @@ class YiiBase
'CEAcceleratorCache' => '/caching/CEAcceleratorCache.php', 'CEAcceleratorCache' => '/caching/CEAcceleratorCache.php',
'CFileCache' => '/caching/CFileCache.php', 'CFileCache' => '/caching/CFileCache.php',
'CMemCache' => '/caching/CMemCache.php', 'CMemCache' => '/caching/CMemCache.php',
'CRedisCache' => '/caching/CRedisCache.php',
'CWinCache' => '/caching/CWinCache.php', 'CWinCache' => '/caching/CWinCache.php',
'CXCache' => '/caching/CXCache.php', 'CXCache' => '/caching/CXCache.php',
'CZendDataCache' => '/caching/CZendDataCache.php', 'CZendDataCache' => '/caching/CZendDataCache.php',
@ -714,6 +724,7 @@ class YiiBase
'COciSchema' => '/db/schema/oci/COciSchema.php', 'COciSchema' => '/db/schema/oci/COciSchema.php',
'COciTableSchema' => '/db/schema/oci/COciTableSchema.php', 'COciTableSchema' => '/db/schema/oci/COciTableSchema.php',
'CPgsqlColumnSchema' => '/db/schema/pgsql/CPgsqlColumnSchema.php', 'CPgsqlColumnSchema' => '/db/schema/pgsql/CPgsqlColumnSchema.php',
'CPgsqlCommandBuilder' => '/db/schema/pgsql/CPgsqlCommandBuilder.php',
'CPgsqlSchema' => '/db/schema/pgsql/CPgsqlSchema.php', 'CPgsqlSchema' => '/db/schema/pgsql/CPgsqlSchema.php',
'CPgsqlTableSchema' => '/db/schema/pgsql/CPgsqlTableSchema.php', 'CPgsqlTableSchema' => '/db/schema/pgsql/CPgsqlTableSchema.php',
'CSqliteColumnSchema' => '/db/schema/sqlite/CSqliteColumnSchema.php', 'CSqliteColumnSchema' => '/db/schema/sqlite/CSqliteColumnSchema.php',
@ -743,7 +754,9 @@ class YiiBase
'CDateTimeParser' => '/utils/CDateTimeParser.php', 'CDateTimeParser' => '/utils/CDateTimeParser.php',
'CFileHelper' => '/utils/CFileHelper.php', 'CFileHelper' => '/utils/CFileHelper.php',
'CFormatter' => '/utils/CFormatter.php', 'CFormatter' => '/utils/CFormatter.php',
'CLocalizedFormatter' => '/utils/CLocalizedFormatter.php',
'CMarkdownParser' => '/utils/CMarkdownParser.php', 'CMarkdownParser' => '/utils/CMarkdownParser.php',
'CPasswordHelper' => '/utils/CPasswordHelper.php',
'CPropertyValue' => '/utils/CPropertyValue.php', 'CPropertyValue' => '/utils/CPropertyValue.php',
'CTimestamp' => '/utils/CTimestamp.php', 'CTimestamp' => '/utils/CTimestamp.php',
'CVarDumper' => '/utils/CVarDumper.php', 'CVarDumper' => '/utils/CVarDumper.php',

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -140,7 +140,18 @@ abstract class CApplication extends CModule
$this->setBasePath('protected'); $this->setBasePath('protected');
Yii::setPathOfAlias('application',$this->getBasePath()); Yii::setPathOfAlias('application',$this->getBasePath());
Yii::setPathOfAlias('webroot',dirname($_SERVER['SCRIPT_FILENAME'])); Yii::setPathOfAlias('webroot',dirname($_SERVER['SCRIPT_FILENAME']));
Yii::setPathOfAlias('ext',$this->getBasePath().DIRECTORY_SEPARATOR.'extensions'); if(isset($config['extensionPath']))
{
$this->setExtensionPath($config['extensionPath']);
unset($config['extensionPath']);
}
else
Yii::setPathOfAlias('ext',$this->getBasePath().DIRECTORY_SEPARATOR.'extensions');
if(isset($config['aliases']))
{
$this->setAliases($config['aliases']);
unset($config['aliases']);
}
$this->preinit(); $this->preinit();
@ -292,6 +303,7 @@ abstract class CApplication extends CModule
/** /**
* Sets the root directory that holds all third-party extensions. * Sets the root directory that holds all third-party extensions.
* @param string $path the directory that contains all third-party extensions. * @param string $path the directory that contains all third-party extensions.
* @throws CException if the directory does not exist
*/ */
public function setExtensionPath($path) public function setExtensionPath($path)
{ {

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -47,7 +47,7 @@ abstract class CApplicationComponent extends CComponent implements IApplicationC
} }
/** /**
* Checks if this application component bas been initialized. * Checks if this application component has been initialized.
* @return boolean whether this application component has been initialized (ie, {@link init()} is invoked). * @return boolean whether this application component has been initialized (ie, {@link init()} is invoked).
*/ */
public function getIsInitialized() public function getIsInitialized()

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -248,6 +248,7 @@ class CComponent
* to implement the behavior feature. * to implement the behavior feature.
* @param string $name the method name * @param string $name the method name
* @param array $parameters method parameters * @param array $parameters method parameters
* @throws CException if current class and its behaviors do not have a method or closure with the given name
* @return mixed the method return value * @return mixed the method return value
*/ */
public function __call($name,$parameters) public function __call($name,$parameters)
@ -318,6 +319,8 @@ class CComponent
* @param string $name the behavior's name. It should uniquely identify this behavior. * @param string $name the behavior's name. It should uniquely identify this behavior.
* @param mixed $behavior the behavior configuration. This is passed as the first * @param mixed $behavior the behavior configuration. This is passed as the first
* parameter to {@link YiiBase::createComponent} to create the behavior object. * parameter to {@link YiiBase::createComponent} to create the behavior object.
* You can also pass an already created behavior instance (the new behavior will replace an already created
* behavior with the same name, if it exists).
* @return IBehavior the behavior object * @return IBehavior the behavior object
*/ */
public function attachBehavior($name,$behavior) public function attachBehavior($name,$behavior)
@ -539,7 +542,6 @@ class CComponent
*/ */
public function raiseEvent($name,$event) public function raiseEvent($name,$event)
{ {
$name=strtolower($name); $name=strtolower($name);
if(isset($this->_e[$name])) if(isset($this->_e[$name]))
{ {
@ -594,6 +596,9 @@ class CComponent
* that can be directly accessed in the expression. See {@link http://us.php.net/manual/en/function.extract.php PHP extract} * that can be directly accessed in the expression. See {@link http://us.php.net/manual/en/function.extract.php PHP extract}
* for more details. In the expression, the component object can be accessed using $this. * for more details. In the expression, the component object can be accessed using $this.
* *
* A PHP expression can be any PHP code that has a value. To learn more about what an expression is,
* please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}.
*
* @param mixed $_expression_ a PHP expression or PHP callback to be evaluated. * @param mixed $_expression_ a PHP expression or PHP callback to be evaluated.
* @param array $_data_ additional parameters to be passed to the above expression/callback. * @param array $_data_ additional parameters to be passed to the above expression/callback.
* @return mixed the expression result * @return mixed the expression result

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -275,6 +275,7 @@ abstract class CModel extends CComponent implements IteratorAggregate, ArrayAcce
/** /**
* Creates validator objects based on the specification in {@link rules}. * Creates validator objects based on the specification in {@link rules}.
* This method is mainly used internally. * This method is mainly used internally.
* @throws CException if current class has an invalid validation rule
* @return CList validators built based on {@link rules()}. * @return CList validators built based on {@link rules()}.
*/ */
public function createValidators() public function createValidators()

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -519,9 +519,8 @@ abstract class CModule extends CComponent
*/ */
protected function preloadComponents() protected function preloadComponents()
{ {
foreach($this->preload as $id) { foreach($this->preload as $id)
$this->getComponent($id); $this->getComponent($id);
}
} }
/** /**

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -80,16 +80,18 @@ class CSecurityManager extends CApplicationComponent
} }
/** /**
* @return string a randomly generated private key * @return string a randomly generated private key.
* @deprecated in favor of {@link generateRandomString()} since 1.1.14. Never use this method.
*/ */
protected function generateRandomKey() protected function generateRandomKey()
{ {
return sprintf('%08x%08x%08x%08x',mt_rand(),mt_rand(),mt_rand(),mt_rand()); return $this->generateRandomString(32);
} }
/** /**
* @return string the private key used to generate HMAC. * @return string the private key used to generate HMAC.
* If the key is not explicitly set, a random one is generated and returned. * If the key is not explicitly set, a random one is generated and returned.
* @throws CException in case random string cannot be generated.
*/ */
public function getValidationKey() public function getValidationKey()
{ {
@ -101,7 +103,10 @@ class CSecurityManager extends CApplicationComponent
$this->setValidationKey($key); $this->setValidationKey($key);
else else
{ {
$key=$this->generateRandomKey(); if(($key=$this->generateRandomString(32,true))===false)
if(($key=$this->generateRandomString(32,false))===false)
throw new CException(Yii::t('yii',
'CSecurityManager::generateRandomString() cannot generate random string in the current environment.'));
$this->setValidationKey($key); $this->setValidationKey($key);
Yii::app()->setGlobalState(self::STATE_VALIDATION_KEY,$key); Yii::app()->setGlobalState(self::STATE_VALIDATION_KEY,$key);
} }
@ -124,6 +129,7 @@ class CSecurityManager extends CApplicationComponent
/** /**
* @return string the private key used to encrypt/decrypt data. * @return string the private key used to encrypt/decrypt data.
* If the key is not explicitly set, a random one is generated and returned. * If the key is not explicitly set, a random one is generated and returned.
* @throws CException in case random string cannot be generated.
*/ */
public function getEncryptionKey() public function getEncryptionKey()
{ {
@ -135,7 +141,10 @@ class CSecurityManager extends CApplicationComponent
$this->setEncryptionKey($key); $this->setEncryptionKey($key);
else else
{ {
$key=$this->generateRandomKey(); if(($key=$this->generateRandomString(32,true))===false)
if(($key=$this->generateRandomString(32,false))===false)
throw new CException(Yii::t('yii',
'CSecurityManager::generateRandomString() cannot generate random string in the current environment.'));
$this->setEncryptionKey($key); $this->setEncryptionKey($key);
Yii::app()->setGlobalState(self::STATE_ENCRYPTION_KEY,$key); Yii::app()->setGlobalState(self::STATE_ENCRYPTION_KEY,$key);
} }
@ -158,7 +167,8 @@ class CSecurityManager extends CApplicationComponent
/** /**
* This method has been deprecated since version 1.1.3. * This method has been deprecated since version 1.1.3.
* Please use {@link hashAlgorithm} instead. * Please use {@link hashAlgorithm} instead.
* @return string * @return string -
* @deprecated
*/ */
public function getValidation() public function getValidation()
{ {
@ -169,6 +179,7 @@ class CSecurityManager extends CApplicationComponent
* This method has been deprecated since version 1.1.3. * This method has been deprecated since version 1.1.3.
* Please use {@link hashAlgorithm} instead. * Please use {@link hashAlgorithm} instead.
* @param string $value - * @param string $value -
* @deprecated
*/ */
public function setValidation($value) public function setValidation($value)
{ {
@ -217,6 +228,7 @@ class CSecurityManager extends CApplicationComponent
/** /**
* Opens the mcrypt module with the configuration specified in {@link cryptAlgorithm}. * Opens the mcrypt module with the configuration specified in {@link cryptAlgorithm}.
* @throws CException if failed to initialize the mcrypt module or PHP mcrypt extension
* @return resource the mycrypt module handle. * @return resource the mycrypt module handle.
* @since 1.1.3 * @since 1.1.3
*/ */
@ -271,37 +283,189 @@ class CSecurityManager extends CApplicationComponent
} }
/** /**
* Computes the HMAC for the data with {@link getValidationKey ValidationKey}. * Computes the HMAC for the data with {@link getValidationKey validationKey}. This method has been made public
* @param string $data data to be generated HMAC * since 1.1.14.
* @param string $key the private key to be used for generating HMAC. Defaults to null, meaning using {@link validationKey}. * @param string $data data to be generated HMAC.
* @return string the HMAC for the data * @param string|null $key the private key to be used for generating HMAC. Defaults to null, meaning using
* {@link validationKey} value.
* @param string|null $hashAlgorithm the name of the hashing algorithm to be used.
* See {@link http://php.net/manual/en/function.hash-algos.php hash-algos} for the list of possible
* hash algorithms. Note that if you are using PHP 5.1.1 or below, you can only use 'sha1' or 'md5'.
* Defaults to null, meaning using {@link hashAlgorithm} value.
* @return string the HMAC for the data.
* @throws CException on unsupported hash algorithm given.
*/ */
protected function computeHMAC($data,$key=null) public function computeHMAC($data,$key=null,$hashAlgorithm=null)
{ {
if($key===null) if($key===null)
$key=$this->getValidationKey(); $key=$this->getValidationKey();
if($hashAlgorithm===null)
$hashAlgorithm=$this->hashAlgorithm;
if(function_exists('hash_hmac')) if(function_exists('hash_hmac'))
return hash_hmac($this->hashAlgorithm, $data, $key); return hash_hmac($hashAlgorithm,$data,$key);
if(!strcasecmp($this->hashAlgorithm,'sha1')) if(0===strcasecmp($hashAlgorithm,'sha1'))
{ {
$pack='H40'; $pack='H40';
$func='sha1'; $func='sha1';
} }
else elseif(0===strcasecmp($hashAlgorithm,'md5'))
{ {
$pack='H32'; $pack='H32';
$func='md5'; $func='md5';
} }
if($this->strlen($key) > 64) else
$key=pack($pack, $func($key)); {
if($this->strlen($key) < 64) throw new CException(Yii::t('yii','Only SHA1 and MD5 hashing algorithms are supported when using PHP 5.1.1 or below.'));
$key=str_pad($key, 64, chr(0)); }
if($this->strlen($key)>64)
$key=pack($pack,$func($key));
if($this->strlen($key)<64)
$key=str_pad($key,64,chr(0));
$key=$this->substr($key,0,64); $key=$this->substr($key,0,64);
return $func((str_repeat(chr(0x5C), 64) ^ $key) . pack($pack, $func((str_repeat(chr(0x36), 64) ^ $key) . $data))); return $func((str_repeat(chr(0x5C), 64) ^ $key) . pack($pack, $func((str_repeat(chr(0x36), 64) ^ $key) . $data)));
} }
/**
* Generate a random ASCII string. Generates only [0-9a-zA-z_~] characters which are all
* transparent in raw URL encoding.
* @param integer $length length of the generated string in characters.
* @param boolean $cryptographicallyStrong set this to require cryptographically strong randomness.
* @return string|boolean random string or false in case it cannot be generated.
* @since 1.1.14
*/
public function generateRandomString($length,$cryptographicallyStrong=true)
{
if(($randomBytes=$this->generateRandomBytes($length+2,$cryptographicallyStrong))!==false)
return strtr($this->substr(base64_encode($randomBytes),0,$length),array('+'=>'_','/'=>'~'));
return false;
}
/**
* Generates a string of random bytes.
* @param integer $length number of random bytes to be generated.
* @param boolean $cryptographicallyStrong whether to fail if a cryptographically strong
* result cannot be generated. The method attempts to read from a cryptographically strong
* pseudorandom number generator (CS-PRNG), see
* {@link https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Requirements Wikipedia}.
* However, in some runtime environments, PHP has no access to a CS-PRNG, in which case
* the method returns false if $cryptographicallyStrong is true. When $cryptographicallyStrong is false,
* the method always returns a pseudorandom result but may fall back to using {@link generatePseudoRandomBlock}.
* This method does not guarantee that entropy, from sources external to the CS-PRNG, was mixed into
* the CS-PRNG state between each successive call. The caller can therefore expect non-blocking
* behavior, unlike, for example, reading from /dev/random on Linux, see
* {@link http://eprint.iacr.org/2006/086.pdf Gutterman et al 2006}.
* @return boolean|string generated random binary string or false on failure.
* @since 1.1.14
*/
public function generateRandomBytes($length,$cryptographicallyStrong=true)
{
$bytes='';
if(function_exists('openssl_random_pseudo_bytes'))
{
$bytes=openssl_random_pseudo_bytes($length,$strong);
if($this->strlen($bytes)>=$length && ($strong || !$cryptographicallyStrong))
return $this->substr($bytes,0,$length);
}
if(function_exists('mcrypt_create_iv') &&
($bytes=mcrypt_create_iv($length, MCRYPT_DEV_URANDOM))!==false &&
$this->strlen($bytes)>=$length)
{
return $this->substr($bytes,0,$length);
}
if(($file=@fopen('/dev/urandom','rb'))!==false &&
($bytes=@fread($file,$length))!==false &&
(fclose($file) || true) &&
$this->strlen($bytes)>=$length)
{
return $this->substr($bytes,0,$length);
}
$i=0;
while($this->strlen($bytes)<$length &&
($byte=$this->generateSessionRandomBlock())!==false &&
++$i<3)
{
$bytes.=$byte;
}
if($this->strlen($bytes)>=$length)
return $this->substr($bytes,0,$length);
if ($cryptographicallyStrong)
return false;
while($this->strlen($bytes)<$length)
$bytes.=$this->generatePseudoRandomBlock();
return $this->substr($bytes,0,$length);
}
/**
* Generate a pseudo random block of data using several sources. On some systems this may be a bit
* better than PHP's {@link mt_rand} built-in function, which is not really random.
* @return string of 64 pseudo random bytes.
* @since 1.1.14
*/
public function generatePseudoRandomBlock()
{
$bytes='';
if (function_exists('openssl_random_pseudo_bytes')
&& ($bytes=openssl_random_pseudo_bytes(512))!==false
&& $this->strlen($bytes)>=512)
{
return $this->substr($bytes,0,512);
}
for($i=0;$i<32;++$i)
$bytes.=pack('S',mt_rand(0,0xffff));
// On UNIX and UNIX-like operating systems the numerical values in `ps`, `uptime` and `iostat`
// ought to be fairly unpredictable. Gather the non-zero digits from those.
foreach(array('ps','uptime','iostat') as $command) {
@exec($command,$commandResult,$retVal);
if(is_array($commandResult) && !empty($commandResult) && $retVal==0)
$bytes.=preg_replace('/[^1-9]/','',implode('',$commandResult));
}
// Gather the current time's microsecond part. Note: this is only a source of entropy on
// the first call! If multiple calls are made, the entropy is only as much as the
// randomness in the time between calls.
$bytes.=$this->substr(microtime(),2,6);
// Concatenate everything gathered, mix it with sha512. hash() is part of PHP core and
// enabled by default but it can be disabled at compile time but we ignore that possibility here.
return hash('sha512',$bytes,true);
}
/**
* Get random bytes from the system entropy source via PHP session manager.
* @return boolean|string 20-byte random binary string or false on error.
* @since 1.1.14
*/
public function generateSessionRandomBlock()
{
ini_set('session.entropy_length',20);
if(ini_get('session.entropy_length')!=20)
return false;
// These calls are (supposed to be, according to PHP manual) safe even if
// there is already an active session for the calling script.
@session_start();
@session_regenerate_id();
$bytes=session_id();
if(!$bytes)
return false;
// $bytes has 20 bytes of entropy but the session manager converts the binary
// random bytes into something readable. We have to convert that back.
// SHA-1 should do it without losing entropy.
return sha1($bytes,true);
}
/** /**
* Returns the length of the given string. * Returns the length of the given string.
* If available uses the multibyte string function mb_strlen. * If available uses the multibyte string function mb_strlen.

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -39,7 +39,7 @@ class CApcCache extends CCache
* Retrieves a value from cache with a specified key. * Retrieves a value from cache with a specified key.
* This is the implementation of the method declared in the parent class. * This is the implementation of the method declared in the parent class.
* @param string $key a unique key identifying the cached value * @param string $key a unique key identifying the cached value
* @return string the value stored in cache, false if the value is not in the cache or expired. * @return string|boolean the value stored in cache, false if the value is not in the cache or expired.
*/ */
protected function getValue($key) protected function getValue($key)
{ {

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -238,7 +238,7 @@ abstract class CCache extends CApplicationComponent implements ICache, ArrayAcce
* in {@link get()} already. So only the implementation of data retrieval * in {@link get()} already. So only the implementation of data retrieval
* is needed. * is needed.
* @param string $key a unique key identifying the cached value * @param string $key a unique key identifying the cached value
* @return string the value stored in cache, false if the value is not in the cache or expired. * @return string|boolean the value stored in cache, false if the value is not in the cache or expired.
* @throws CException if this method is not overridden by child classes * @throws CException if this method is not overridden by child classes
*/ */
protected function getValue($key) protected function getValue($key)

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -176,7 +176,7 @@ EOD;
* Retrieves a value from cache with a specified key. * Retrieves a value from cache with a specified key.
* This is the implementation of the method declared in the parent class. * This is the implementation of the method declared in the parent class.
* @param string $key a unique key identifying the cached value * @param string $key a unique key identifying the cached value
* @return string the value stored in cache, false if the value is not in the cache or expired. * @return string|boolean the value stored in cache, false if the value is not in the cache or expired.
*/ */
protected function getValue($key) protected function getValue($key)
{ {

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -4,7 +4,7 @@
* *
* @author Steffen Dietz <steffo.dietz[at]googlemail[dot]com> * @author Steffen Dietz <steffo.dietz[at]googlemail[dot]com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -40,7 +40,7 @@ class CEAcceleratorCache extends CCache
* Retrieves a value from cache with a specified key. * Retrieves a value from cache with a specified key.
* This is the implementation of the method declared in the parent class. * This is the implementation of the method declared in the parent class.
* @param string $key a unique key identifying the cached value * @param string $key a unique key identifying the cached value
* @return string the value stored in cache, false if the value is not in the cache or expired. * @return string|boolean the value stored in cache, false if the value is not in the cache or expired.
*/ */
protected function getValue($key) protected function getValue($key)
{ {

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -41,6 +41,15 @@ class CFileCache extends CCache
* The value of this property should not exceed 16 (less than 3 is recommended). * The value of this property should not exceed 16 (less than 3 is recommended).
*/ */
public $directoryLevel=0; public $directoryLevel=0;
/**
* @var boolean whether cache entry expiration time should be embedded into a physical file.
* Defaults to false meaning that the file modification time will be used to store expire value.
* True value means that first ten bytes of the file would be reserved and used to store expiration time.
* On some systems PHP is not allowed to change file modification time to be in future even with 777
* permissions, so this property could be useful in this case.
* @since 1.1.14
*/
public $embedExpiry=false;
private $_gcProbability=100; private $_gcProbability=100;
private $_gced=false; private $_gced=false;
@ -98,13 +107,13 @@ class CFileCache extends CCache
* Retrieves a value from cache with a specified key. * Retrieves a value from cache with a specified key.
* This is the implementation of the method declared in the parent class. * This is the implementation of the method declared in the parent class.
* @param string $key a unique key identifying the cached value * @param string $key a unique key identifying the cached value
* @return string the value stored in cache, false if the value is not in the cache or expired. * @return string|boolean the value stored in cache, false if the value is not in the cache or expired.
*/ */
protected function getValue($key) protected function getValue($key)
{ {
$cacheFile=$this->getCacheFile($key); $cacheFile=$this->getCacheFile($key);
if(($time=@filemtime($cacheFile))>time()) if(($time=$this->filemtime($cacheFile))>time())
return @file_get_contents($cacheFile); return @file_get_contents($cacheFile,false,null,$this->embedExpiry ? 10 : -1);
elseif($time>0) elseif($time>0)
@unlink($cacheFile); @unlink($cacheFile);
return false; return false;
@ -134,10 +143,10 @@ class CFileCache extends CCache
$cacheFile=$this->getCacheFile($key); $cacheFile=$this->getCacheFile($key);
if($this->directoryLevel>0) if($this->directoryLevel>0)
@mkdir(dirname($cacheFile),0777,true); @mkdir(dirname($cacheFile),0777,true);
if(@file_put_contents($cacheFile,$value,LOCK_EX)!==false) if(@file_put_contents($cacheFile,$this->embedExpiry ? $expire.$value : $value,LOCK_EX)!==false)
{ {
@chmod($cacheFile,0777); @chmod($cacheFile,0777);
return @touch($cacheFile,$expire); return $this->embedExpiry ? true : @touch($cacheFile,$expire);
} }
else else
return false; return false;
@ -155,7 +164,7 @@ class CFileCache extends CCache
protected function addValue($key,$value,$expire) protected function addValue($key,$value,$expire)
{ {
$cacheFile=$this->getCacheFile($key); $cacheFile=$this->getCacheFile($key);
if(@filemtime($cacheFile)>time()) if($this->filemtime($cacheFile)>time())
return false; return false;
return $this->setValue($key,$value,$expire); return $this->setValue($key,$value,$expire);
} }
@ -212,9 +221,22 @@ class CFileCache extends CCache
$fullPath=$path.DIRECTORY_SEPARATOR.$file; $fullPath=$path.DIRECTORY_SEPARATOR.$file;
if(is_dir($fullPath)) if(is_dir($fullPath))
$this->gc($expiredOnly,$fullPath); $this->gc($expiredOnly,$fullPath);
elseif($expiredOnly && @filemtime($fullPath)<time() || !$expiredOnly) elseif($expiredOnly && $this->filemtime($fullPath)<time() || !$expiredOnly)
@unlink($fullPath); @unlink($fullPath);
} }
closedir($handle); closedir($handle);
} }
/**
* Returns cache file modification time. {@link $embedExpiry} aware.
* @param string $path to the file, modification time to be retrieved from.
* @return integer file modification time.
*/
private function filemtime($path)
{
if($this->embedExpiry)
return (int)@file_get_contents($path,false,null,0,10);
else
return @filemtime($path);
}
} }

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -142,7 +142,7 @@ class CMemCache extends CCache
* Retrieves a value from cache with a specified key. * Retrieves a value from cache with a specified key.
* This is the implementation of the method declared in the parent class. * This is the implementation of the method declared in the parent class.
* @param string $key a unique key identifying the cached value * @param string $key a unique key identifying the cached value
* @return string the value stored in cache, false if the value is not in the cache or expired. * @return string|boolean the value stored in cache, false if the value is not in the cache or expired.
*/ */
protected function getValue($key) protected function getValue($key)
{ {

View File

@ -0,0 +1,257 @@
<?php
/**
* CRedisCache class file
*
* @author Carsten Brandt <mail@cebe.cc>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
/**
* CRedisCache implements a cache application component based on {@link http://redis.io/ redis}.
*
* CRedisCache needs to be configured with {@link hostname}, {@link port} and {@link database} of the server
* to connect to. By default CRedisCache assumes there is a redis server running on localhost at
* port 6379 and uses the database number 0.
*
* CRedisCache also supports {@link http://redis.io/commands/auth the AUTH command} of redis.
* When the server needs authentication, you can set the {@link password} property to
* authenticate with the server after connect.
*
* See {@link CCache} manual for common cache operations that are supported by CRedisCache.
*
* To use CRedisCache as the cache application component, configure the application as follows,
* <pre>
* array(
* 'components'=>array(
* 'cache'=>array(
* 'class'=>'CRedisCache',
* 'hostname'=>'localhost',
* 'port'=>6379,
* 'database'=>0,
* ),
* ),
* )
* </pre>
*
* The minimum required redis version is 2.0.0.
*
* @author Carsten Brandt <mail@cebe.cc>
* @package system.caching
* @since 1.1.14
*/
class CRedisCache extends CCache
{
/**
* @var string hostname to use for connecting to the redis server. Defaults to 'localhost'.
*/
public $hostname='localhost';
/**
* @var int the port to use for connecting to the redis server. Default port is 6379.
*/
public $port=6379;
/**
* @var string the password to use to authenticate with the redis server. If not set, no AUTH command will be sent.
*/
public $password;
/**
* @var int the redis database to use. This is an integer value starting from 0. Defaults to 0.
*/
public $database=0;
/**
* @var float timeout to use for connection to redis. If not set the timeout set in php.ini will be used: ini_get("default_socket_timeout")
*/
public $timeout=null;
/**
* @var resource redis socket connection
*/
private $_socket;
/**
* Establishes a connection to the redis server.
* It does nothing if the connection has already been established.
* @throws CException if connecting fails
*/
protected function connect()
{
$this->_socket=@stream_socket_client(
$this->hostname.':'.$this->port,
$errorNumber,
$errorDescription,
$this->timeout ? $this->timeout : ini_get("default_socket_timeout")
);
if ($this->_socket)
{
if($this->password!==null)
$this->executeCommand('AUTH',array($this->password));
$this->executeCommand('SELECT',array($this->database));
}
else
throw new CException('Failed to connect to redis: '.$errorDescription,(int)$errorNumber);
}
/**
* Executes a redis command.
* For a list of available commands and their parameters see {@link http://redis.io/commands}.
*
* @param string $name the name of the command
* @param array $params list of parameters for the command
* @return array|bool|null|string Dependend on the executed command this method
* will return different data types:
* <ul>
* <li><code>true</code> for commands that return "status reply".</li>
* <li><code>string</code> for commands that return "integer reply"
* as the value is in the range of a signed 64 bit integer.</li>
* <li><code>string</code> or <code>null</code> for commands that return "bulk reply".</li>
* <li><code>array</code> for commands that return "Multi-bulk replies".</li>
* </ul>
* See {@link http://redis.io/topics/protocol redis protocol description}
* for details on the mentioned reply types.
* @trows CException for commands that return {@link http://redis.io/topics/protocol#error-reply error reply}.
*/
public function executeCommand($name,$params=array())
{
if($this->_socket===null)
$this->connect();
array_unshift($params,$name);
$command='*'.count($params)."\r\n";
foreach($params as $arg)
$command.='$'.strlen($arg)."\r\n".$arg."\r\n";
fwrite($this->_socket,$command);
return $this->parseResponse(implode(' ',$params));
}
/**
* Reads the result from socket and parses it
* @return array|bool|null|string
* @throws CException socket or data problems
*/
private function parseResponse()
{
if(($line=fgets($this->_socket))===false)
throw new CException('Failed reading data from redis connection socket.');
$type=$line[0];
$line=substr($line,1,-2);
switch($type)
{
case '+': // Status reply
return true;
case '-': // Error reply
throw new CException('Redis error: '.$line);
case ':': // Integer reply
// no cast to int as it is in the range of a signed 64 bit integer
return $line;
case '$': // Bulk replies
if($line=='-1')
return null;
$length=$line+2;
$data='';
while($length>0)
{
if(($block=fread($this->_socket,$length))===false)
throw new CException('Failed reading data from redis connection socket.');
$data.=$block;
$length-=(function_exists('mb_strlen') ? mb_strlen($block,'8bit') : strlen($block));
}
return substr($data,0,-2);
case '*': // Multi-bulk replies
$count=(int)$line;
$data=array();
for($i=0;$i<$count;$i++)
$data[]=$this->parseResponse();
return $data;
default:
throw new CException('Unable to parse data received from redis.');
}
}
/**
* Retrieves a value from cache with a specified key.
* This is the implementation of the method declared in the parent class.
* @param string $key a unique key identifying the cached value
* @return string|boolean the value stored in cache, false if the value is not in the cache or expired.
*/
protected function getValue($key)
{
return $this->executeCommand('GET',array($key));
}
/**
* Retrieves multiple values from cache with the specified keys.
* @param array $keys a list of keys identifying the cached values
* @return array a list of cached values indexed by the keys
*/
protected function getValues($keys)
{
$response=$this->executeCommand('MGET',$keys);
$result=array();
$i=0;
foreach($keys as $key)
$result[$key]=$response[$i++];
return $result;
}
/**
* Stores a value identified by a key in cache.
* This is the implementation of the method declared in the parent class.
*
* @param string $key the key identifying the value to be cached
* @param string $value the value to be cached
* @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire.
* @return boolean true if the value is successfully stored into cache, false otherwise
*/
protected function setValue($key,$value,$expire)
{
if ($expire==0)
return (bool)$this->executeCommand('SET',array($key,$value));
return (bool)$this->executeCommand('SETEX',array($key,$expire,$value));
}
/**
* Stores a value identified by a key into cache if the cache does not contain this key.
* This is the implementation of the method declared in the parent class.
*
* @param string $key the key identifying the value to be cached
* @param string $value the value to be cached
* @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire.
* @return boolean true if the value is successfully stored into cache, false otherwise
*/
protected function addValue($key,$value,$expire)
{
if ($expire == 0)
return (bool)$this->executeCommand('SETNX',array($key,$value));
if($this->executeCommand('SETNX',array($key,$value)))
{
$this->executeCommand('EXPIRE',array($key,$expire));
return true;
}
else
return false;
}
/**
* Deletes a value with the specified key from cache
* This is the implementation of the method declared in the parent class.
* @param string $key the key of the value to be deleted
* @return boolean if no error happens during deletion
*/
protected function deleteValue($key)
{
return (bool)$this->executeCommand('DEL',array($key));
}
/**
* Deletes all values from cache.
* This is the implementation of the method declared in the parent class.
* @return boolean whether the flush operation was successful.
*/
protected function flushValues()
{
return $this->executeCommand('FLUSHDB');
}
}

View File

@ -4,7 +4,7 @@
* *
* @author Alexander Makarov <sam@rmcreative.ru> * @author Alexander Makarov <sam@rmcreative.ru>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -39,7 +39,7 @@ class CWinCache extends CCache {
* Retrieves a value from cache with a specified key. * Retrieves a value from cache with a specified key.
* This is the implementation of the method declared in the parent class. * This is the implementation of the method declared in the parent class.
* @param string $key a unique key identifying the cached value * @param string $key a unique key identifying the cached value
* @return string the value stored in cache, false if the value is not in the cache or expired. * @return string|boolean the value stored in cache, false if the value is not in the cache or expired.
*/ */
protected function getValue($key) protected function getValue($key)
{ {

View File

@ -4,7 +4,7 @@
* *
* @author Wei Zhuo <weizhuo[at]gmail[dot]com> * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -38,7 +38,7 @@ class CXCache extends CCache
* Retrieves a value from cache with a specified key. * Retrieves a value from cache with a specified key.
* This is the implementation of the method declared in the parent class. * This is the implementation of the method declared in the parent class.
* @param string $key a unique key identifying the cached value * @param string $key a unique key identifying the cached value
* @return string the value stored in cache, false if the value is not in the cache or expired. * @return string|boolean the value stored in cache, false if the value is not in the cache or expired.
*/ */
protected function getValue($key) protected function getValue($key)
{ {

View File

@ -4,7 +4,7 @@
* *
* @author Steffen Dietz <steffo.dietz[at]googlemail[dot]com> * @author Steffen Dietz <steffo.dietz[at]googlemail[dot]com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -38,7 +38,7 @@ class CZendDataCache extends CCache
* Retrieves a value from cache with a specified key. * Retrieves a value from cache with a specified key.
* This is the implementation of the method declared in the parent class. * This is the implementation of the method declared in the parent class.
* @param string $key a unique key identifying the cached value * @param string $key a unique key identifying the cached value
* @return string the value stored in cache, false if the value is not in the cache or expired. * @return string|boolean the value stored in cache, false if the value is not in the cache or expired.
*/ */
protected function getValue($key) protected function getValue($key)
{ {

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -53,7 +53,7 @@ class CCacheDependency extends CComponent implements ICacheDependency
if ($this->reuseDependentData) if ($this->reuseDependentData)
{ {
$hash=$this->getHash(); $hash=$this->getHash();
if (!isset(self::$_reusableData[$hash]['dependentData'])) if(!isset(self::$_reusableData[$hash]['dependentData']))
self::$_reusableData[$hash]['dependentData']=$this->generateDependentData(); self::$_reusableData[$hash]['dependentData']=$this->generateDependentData();
$this->_data=self::$_reusableData[$hash]['dependentData']; $this->_data=self::$_reusableData[$hash]['dependentData'];
} }
@ -69,13 +69,9 @@ class CCacheDependency extends CComponent implements ICacheDependency
if ($this->reuseDependentData) if ($this->reuseDependentData)
{ {
$hash=$this->getHash(); $hash=$this->getHash();
if (!isset(self::$_reusableData[$hash]['hasChanged'])) if(!isset(self::$_reusableData[$hash]['dependentData']))
{ self::$_reusableData[$hash]['dependentData']=$this->generateDependentData();
if (!isset(self::$_reusableData[$hash]['dependentData'])) return self::$_reusableData[$hash]['dependentData']!=$this->_data;
self::$_reusableData[$hash]['dependentData']=$this->generateDependentData();
self::$_reusableData[$hash]['hasChanged']=self::$_reusableData[$hash]['dependentData']!=$this->_data;
}
return self::$_reusableData[$hash]['hasChanged'];
} }
else else
return $this->generateDependentData()!=$this->_data; return $this->generateDependentData()!=$this->_data;
@ -90,6 +86,15 @@ class CCacheDependency extends CComponent implements ICacheDependency
return $this->_data; return $this->_data;
} }
/**
* Resets cached data for reusable dependencies.
* @since 1.1.14
*/
public static function resetReusableData()
{
self::$_reusableData=array();
}
/** /**
* Generates the data needed to determine if dependency has been changed. * Generates the data needed to determine if dependency has been changed.
* Derived classes should override this method to generate actual dependent data. * Derived classes should override this method to generate actual dependent data.

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -52,7 +52,7 @@ class CChainedCacheDependency extends CComponent implements ICacheDependency
/** /**
* @param array $values list of dependency objects or configurations to be added to this chain. * @param array $values list of dependency objects or configurations to be added to this chain.
* If a depedency is specified as a configuration, it must be an array that can be recognized * If a dependency is specified as a configuration, it must be an array that can be recognized
* by {@link YiiBase::createComponent}. * by {@link YiiBase::createComponent}.
*/ */
public function setDependencies($values) public function setDependencies($values)

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -62,6 +62,7 @@ class CDbCacheDependency extends CCacheDependency
/** /**
* Generates the data needed to determine if dependency has been changed. * Generates the data needed to determine if dependency has been changed.
* This method returns the value of the global state. * This method returns the value of the global state.
* @throws CException if {@link sql} is empty
* @return mixed the data needed to determine if dependency has been changed. * @return mixed the data needed to determine if dependency has been changed.
*/ */
protected function generateDependentData() protected function generateDependentData()

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -60,6 +60,7 @@ class CDirectoryCacheDependency extends CCacheDependency
/** /**
* Generates the data needed to determine if dependency has been changed. * Generates the data needed to determine if dependency has been changed.
* This method returns the modification timestamps for files under the directory. * This method returns the modification timestamps for files under the directory.
* @throws CException if {@link directory} is empty
* @return mixed the data needed to determine if dependency has been changed. * @return mixed the data needed to determine if dependency has been changed.
*/ */
protected function generateDependentData() protected function generateDependentData()
@ -75,6 +76,7 @@ class CDirectoryCacheDependency extends CCacheDependency
* This method may go recursively into subdirectories if {@link recursiveLevel} is not 0. * This method may go recursively into subdirectories if {@link recursiveLevel} is not 0.
* @param string $directory the directory name * @param string $directory the directory name
* @param integer $level level of the recursion * @param integer $level level of the recursion
* @throws CException if given directory is not valid
* @return array list of file modification time indexed by the file path * @return array list of file modification time indexed by the file path
*/ */
protected function generateTimestamps($directory,$level=0) protected function generateTimestamps($directory,$level=0)

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -25,7 +25,12 @@ class CExpressionDependency extends CCacheDependency
/** /**
* @var string the PHP expression whose result is used to determine the dependency. * @var string the PHP expression whose result is used to determine the dependency.
* The expression can also be a valid serializable PHP callback. * The expression can also be a valid serializable PHP callback.
* The callback will be passed with a parameter which is the dependency object itself. * It will be passed with a parameter which is the dependency object itself.
*
* The PHP expression will be evaluated using {@link evaluateExpression}.
*
* A PHP expression can be any PHP code that has a value. To learn more about what an expression is,
* please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}.
*/ */
public $expression; public $expression;

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -40,6 +40,7 @@ class CFileCacheDependency extends CCacheDependency
/** /**
* Generates the data needed to determine if dependency has been changed. * Generates the data needed to determine if dependency has been changed.
* This method returns the file's last modification time. * This method returns the file's last modification time.
* @throws CException if {@link fileName} is empty
* @return mixed the data needed to determine if dependency has been changed. * @return mixed the data needed to determine if dependency has been changed.
*/ */
protected function generateDependentData() protected function generateDependentData()

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -41,6 +41,7 @@ class CGlobalStateCacheDependency extends CCacheDependency
/** /**
* Generates the data needed to determine if dependency has been changed. * Generates the data needed to determine if dependency has been changed.
* This method returns the value of the global state. * This method returns the value of the global state.
* @throws CException if {@link stateName} is empty
* @return mixed the data needed to determine if dependency has been changed. * @return mixed the data needed to determine if dependency has been changed.
*/ */
protected function generateDependentData() protected function generateDependentData()

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -67,7 +67,7 @@ EOD;
/** /**
* Execute the action. * Execute the action.
* @param array command line parameters specific for this command * @param array $args command line parameters specific for this command
*/ */
public function run($args) public function run($args)
{ {
@ -76,7 +76,7 @@ EOD;
if(!is_file($args[0])) if(!is_file($args[0]))
$this->usageError("the configuration file {$args[0]} does not exist."); $this->usageError("the configuration file {$args[0]} does not exist.");
$config=require_once($args[0]); $config=require($args[0]);
$translator='Yii::t'; $translator='Yii::t';
extract($config); extract($config);
@ -132,7 +132,7 @@ EOD;
foreach ($translator as $currentTranslator) foreach ($translator as $currentTranslator)
{ {
$n=preg_match_all('/\b'.$currentTranslator.'\s*\(\s*(\'[\w.]*?(?<!\.)\'|"[\w.]*?(?<!\.)")\s*,\s*(\'.*?(?<!\\\\)\'|".*?(?<!\\\\)")\s*[,\)]/s',$subject,$matches,PREG_SET_ORDER); $n=preg_match_all('/\b'.$currentTranslator.'\s*\(\s*(\'[\w.\/]*?(?<!\.)\'|"[\w.]*?(?<!\.)")\s*,\s*(\'.*?(?<!\\\\)\'|".*?(?<!\\\\)")\s*[,\)]/s',$subject,$matches,PREG_SET_ORDER);
for($i=0;$i<$n;++$i) for($i=0;$i<$n;++$i)
{ {
@ -164,7 +164,7 @@ EOD;
$untranslated=array(); $untranslated=array();
foreach($messages as $message) foreach($messages as $message)
{ {
if(!empty($translated[$message])) if(array_key_exists($message,$translated) && strlen($translated[$message])>0)
$merged[$message]=$translated[$message]; $merged[$message]=$translated[$message];
else else
$untranslated[]=$message; $untranslated[]=$message;

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -449,7 +449,7 @@ class MigrateCommand extends CConsoleCommand
protected function getMigrationHistory($limit) protected function getMigrationHistory($limit)
{ {
$db=$this->getDbConnection(); $db=$this->getDbConnection();
if($db->schema->getTable($this->migrationTable)===null) if($db->schema->getTable($this->migrationTable,true)===null)
{ {
$this->createMigrationHistoryTable(); $this->createMigrationHistoryTable();
} }

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -74,7 +74,7 @@ EOD;
/** /**
* Execute the action. * Execute the action.
* @param array command line parameters specific for this command * @param array $args command line parameters specific for this command
* @return integer|null non zero application exit code for help or null on success * @return integer|null non zero application exit code for help or null on success
*/ */
public function run($args) public function run($args)

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -81,7 +81,7 @@ EOD;
/** /**
* Execute the action. * Execute the action.
* @param array command line parameters specific for this command * @param array $args command line parameters specific for this command
* @return integer|null non zero application exit code for help or null on success * @return integer|null non zero application exit code for help or null on success
*/ */
public function run($args) public function run($args)

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -58,7 +58,7 @@ EOD;
/** /**
* Execute the action. * Execute the action.
* @param array command line parameters specific for this command * @param array $args command line parameters specific for this command
* @return integer|null non zero application exit code for help or null on success * @return integer|null non zero application exit code for help or null on success
*/ */
public function run($args) public function run($args)

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -21,7 +21,7 @@ class HelpCommand extends CConsoleCommand
{ {
/** /**
* Execute the action. * Execute the action.
* @param array command line parameters specific for this command * @param array $args command line parameters specific for this command
* @return integer non zero application exit code for help * @return integer non zero application exit code for help
*/ */
public function run($args) public function run($args)

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -107,15 +107,15 @@ EOD;
/** /**
* Checks if the given table is a "many to many" helper table. * Checks if the given table is a "many to many" helper table.
* Their PK has 2 fields, and both of those fields are also FK to other separate tables. * Their PK has 2 fields, and both of those fields are also FK to other separate tables.
* @param CDbTableSchema table to inspect * @param CDbTableSchema $table table to inspect
* @return boolean true if table matches description of helpter table. * @return boolean true if table matches description of helper table.
*/ */
protected function isRelationTable($table) protected function isRelationTable($table)
{ {
$pk=$table->primaryKey; $pk=$table->primaryKey;
return (count($pk) === 2 // we want 2 columns return (count($pk) === 2 // we want 2 columns
&& isset($table->foreignKeys[$pk[0]]) // pk column 1 is also a foreign key && isset($table->foreignKeys[$pk[0]]) // pk column 1 is also a foreign key
&& isset($table->foreignKeys[$pk[1]]) // pk column 2 is also a foriegn key && isset($table->foreignKeys[$pk[1]]) // pk column 2 is also a foreign key
&& $table->foreignKeys[$pk[0]][0] !== $table->foreignKeys[$pk[1]][0]); // and the foreign keys point different tables && $table->foreignKeys[$pk[0]][0] !== $table->foreignKeys[$pk[1]][0]); // and the foreign keys point different tables
} }
@ -180,7 +180,7 @@ EOD;
/** /**
* Generates model class name based on a table name * Generates model class name based on a table name
* @param string the table name * @param string $tableName the table name
* @return string the generated model class name * @return string the generated model class name
*/ */
protected function generateClassName($tableName) protected function generateClassName($tableName)
@ -195,8 +195,8 @@ EOD;
/** /**
* Generates the mapping table between table names and class names. * Generates the mapping table between table names and class names.
* @param CDbSchema the database schema * @param CDbSchema $schema the database schema
* @param string a regular expression that may be used to filter table names * @param string $pattern a regular expression that may be used to filter table names
*/ */
protected function generateClassNames($schema,$pattern=null) protected function generateClassNames($schema,$pattern=null)
{ {
@ -218,9 +218,10 @@ EOD;
/** /**
* Generate a name for use as a relation name (inside relations() function in a model). * Generate a name for use as a relation name (inside relations() function in a model).
* @param string the name of the table to hold the relation * @param string $tableName the name of the table to hold the relation
* @param string the foreign key name * @param string $fkName the foreign key name
* @param boolean whether the relation would contain multiple objects * @param boolean $multiple whether the relation would contain multiple objects
* @return string the generated relation name
*/ */
protected function generateRelationName($tableName, $fkName, $multiple) protected function generateRelationName($tableName, $fkName, $multiple)
{ {
@ -243,7 +244,7 @@ EOD;
/** /**
* Execute the action. * Execute the action.
* @param array command line parameters specific for this command * @param array $args command line parameters specific for this command
* @return integer|null non zero application exit code for help or null on success * @return integer|null non zero application exit code for help or null on success
*/ */
public function run($args) public function run($args)

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
* @version $Id: ModuleCommand.php 433 2008-12-30 22:59:17Z qiang.xue $ * @version $Id: ModuleCommand.php 433 2008-12-30 22:59:17Z qiang.xue $
*/ */
@ -43,7 +43,7 @@ EOD;
/** /**
* Execute the action. * Execute the action.
* @param array command line parameters specific for this command * @param array $args command line parameters specific for this command
* @return integer|null non zero application exit code for help or null on success * @return integer|null non zero application exit code for help or null on success
*/ */
public function run($args) public function run($args)

View File

@ -27,7 +27,7 @@ $('.search-button').click(function(){
return false; return false;
}); });
$('.search-form form').submit(function(){ $('.search-form form').submit(function(){
$('#<?php echo $this->class2id($this->modelClass); ?>-grid').yiiGridView('update', { $('#<?php echo $this->class2id($modelClass); ?>-grid').yiiGridView('update', {
data: $(this).serialize() data: $(this).serialize()
}); });
return false; return false;

View File

@ -22,15 +22,6 @@
*/ */
class <?php echo $className; ?> extends CActiveRecord class <?php echo $className; ?> extends CActiveRecord
{ {
/**
* Returns the static model of the specified AR class.
* @return <?php echo $className; ?> the static model class
*/
public static function model($className=__CLASS__)
{
return parent::model($className);
}
/** /**
* @return string the associated database table name * @return string the associated database table name
*/ */
@ -84,6 +75,13 @@ class <?php echo $className; ?> extends CActiveRecord
/** /**
* Retrieves a list of models based on the current search/filter conditions. * Retrieves a list of models based on the current search/filter conditions.
*
* Typical usecase:
* - Initialize the model fields with values from filter form.
* - Execute this method to get CActiveDataProvider instance which will filter
* models according to data in model fields.
* - Pass data provider to CGridView, CListView or any similar widget.
*
* @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions. * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
*/ */
public function search() public function search()
@ -110,4 +108,13 @@ foreach($columns as $name=>$column)
'criteria'=>$criteria, 'criteria'=>$criteria,
)); ));
} }
/**
* Returns the static model of the specified AR class.
* @return <?php echo $className; ?> the static model class
*/
public static function model($className=__CLASS__)
{
return parent::model($className);
}
} }

View File

@ -30,7 +30,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2010 Yii Software LLC * @copyright 2008-2010 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -2,6 +2,6 @@ syntax: glob
syntax: regexp syntax: regexp
# ignore all except .hgkeep # ignore all except .hgkeep
assets/(?!.*\.hgkeep$).+ ^assets/(?!.*\.hgkeep$).+
protected/runtime/(?!.*\.hgkeep$).+ ^protected/runtime/(?!.*\.hgkeep$).+
protected/tests/report/(?!.*\.hgkeep$).+ ^protected/tests/report/(?!.*\.hgkeep$).+

View File

@ -62,7 +62,7 @@ class SiteController extends Controller
$headers="From: $name <{$model->email}>\r\n". $headers="From: $name <{$model->email}>\r\n".
"Reply-To: {$model->email}\r\n". "Reply-To: {$model->email}\r\n".
"MIME-Version: 1.0\r\n". "MIME-Version: 1.0\r\n".
"Content-type: text/plain; charset=UTF-8"; "Content-Type: text/plain; charset=UTF-8";
mail(Yii::app()->params['adminEmail'],$subject,$model->body,$headers); mail(Yii::app()->params['adminEmail'],$subject,$model->body,$headers);
Yii::app()->user->setFlash('contact','Thank you for contacting us. We will respond to you as soon as possible.'); Yii::app()->user->setFlash('contact','Thank you for contacting us. We will respond to you as soon as possible.');

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -203,11 +203,11 @@ class CAttributeCollection extends CMap
{ {
if(!$this->caseSensitive && (is_array($data) || $data instanceof Traversable)) if(!$this->caseSensitive && (is_array($data) || $data instanceof Traversable))
{ {
$d=array(); $d=array();
foreach($data as $key=>$value) foreach($data as $key=>$value)
$d[strtolower($key)]=$value; $d[strtolower($key)]=$value;
return parent::mergeWith($d,$recursive); return parent::mergeWith($d,$recursive);
} }
parent::mergeWith($data,$recursive); parent::mergeWith($data,$recursive);
} }
} }

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -4,12 +4,12 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
/** /**
* CListIterator implements an interator for {@link CList}. * CListIterator implements an iterator for {@link CList}.
* *
* It allows CList to return a new iterator for traversing the items in the list. * It allows CList to return a new iterator for traversing the items in the list.
* *

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -46,7 +46,7 @@ class CMap extends CComponent implements IteratorAggregate,ArrayAccess,Countable
/** /**
* Constructor. * Constructor.
* Initializes the list with an array or an iterable object. * Initializes the list with an array or an iterable object.
* @param array $data the intial data. Default is null, meaning no initialization. * @param array $data the initial data. Default is null, meaning no initialization.
* @param boolean $readOnly whether the list is read-only * @param boolean $readOnly whether the list is read-only
* @throws CException If data is not null and neither an array nor an iterator. * @throws CException If data is not null and neither an array nor an iterator.
*/ */
@ -225,7 +225,7 @@ class CMap extends CComponent implements IteratorAggregate,ArrayAccess,Countable
* If the merge is recursive, the following algorithm is performed: * If the merge is recursive, the following algorithm is performed:
* <ul> * <ul>
* <li>the map data is saved as $a, and the source data is saved as $b;</li> * <li>the map data is saved as $a, and the source data is saved as $b;</li>
* <li>if $a and $b both have an array indxed at the same string key, the arrays will be merged using this algorithm;</li> * <li>if $a and $b both have an array indexed at the same string key, the arrays will be merged using this algorithm;</li>
* <li>any integer-indexed elements in $b will be appended to $a and reindexed accordingly;</li> * <li>any integer-indexed elements in $b will be appended to $a and reindexed accordingly;</li>
* <li>any string-indexed elements in $b will overwrite elements in $a with the same index;</li> * <li>any string-indexed elements in $b will overwrite elements in $a with the same index;</li>
* </ul> * </ul>
@ -272,7 +272,7 @@ class CMap extends CComponent implements IteratorAggregate,ArrayAccess,Countable
* For integer-keyed elements, the elements from the latter array will * For integer-keyed elements, the elements from the latter array will
* be appended to the former array. * be appended to the former array.
* @param array $a array to be merged to * @param array $a array to be merged to
* @param array $b array to be merged from. You can specifiy additional * @param array $b array to be merged from. You can specify additional
* arrays via third argument, fourth argument etc. * arrays via third argument, fourth argument etc.
* @return array the merged array (the original arrays are not changed.) * @return array the merged array (the original arrays are not changed.)
* @see mergeWith * @see mergeWith

View File

@ -4,12 +4,12 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
/** /**
* CMapIterator implements an interator for {@link CMap}. * CMapIterator implements an iterator for {@link CMap}.
* *
* It allows CMap to return a new iterator for traversing the items in the map. * It allows CMap to return a new iterator for traversing the items in the map.
* *

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -45,7 +45,7 @@ class CQueue extends CComponent implements IteratorAggregate,Countable
/** /**
* Constructor. * Constructor.
* Initializes the queue with an array or an iterable object. * Initializes the queue with an array or an iterable object.
* @param array $data the intial data. Default is null, meaning no initialization. * @param array $data the initial data. Default is null, meaning no initialization.
* @throws CException If data is not null and neither an array nor an iterator. * @throws CException If data is not null and neither an array nor an iterator.
*/ */
public function __construct($data=null) public function __construct($data=null)

View File

@ -4,12 +4,12 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
/** /**
* CQueueIterator implements an interator for {@link CQueue}. * CQueueIterator implements an iterator for {@link CQueue}.
* *
* It allows CQueue to return a new iterator for traversing the items in the queue. * It allows CQueue to return a new iterator for traversing the items in the queue.
* *

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -4,12 +4,12 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
/** /**
* CStackIterator implements an interator for {@link CStack}. * CStackIterator implements an iterator for {@link CStack}.
* *
* It allows CStack to return a new iterator for traversing the items in the stack. * It allows CStack to return a new iterator for traversing the items in the stack.
* *

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -38,6 +38,7 @@
* *
* @property string $commandPath The directory that contains the command classes. Defaults to 'protected/commands'. * @property string $commandPath The directory that contains the command classes. Defaults to 'protected/commands'.
* @property CConsoleCommandRunner $commandRunner The command runner. * @property CConsoleCommandRunner $commandRunner The command runner.
* @property CConsoleCommand $command The currently active command.
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @package system.console * @package system.console
@ -175,4 +176,25 @@ class CConsoleApplication extends CApplication
{ {
return $this->_runner; return $this->_runner;
} }
/**
* Returns the currently running command.
* This is shortcut method for {@link CConsoleCommandRunner::getCommand()}.
* @return CConsoleCommand|null the currently active command.
* @since 1.1.14
*/
public function getCommand()
{
return $this->getCommandRunner()->getCommand();
}
/**
* This is shortcut method for {@link CConsoleCommandRunner::setCommand()}.
* @param CConsoleCommand $value the currently active command.
* @since 1.1.14
*/
public function setCommand($value)
{
$this->getCommandRunner()->setCommand($value);
}
} }

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -27,7 +27,7 @@
* Options are bound to action parameters via parameter names. For example, the following * Options are bound to action parameters via parameter names. For example, the following
* action method will allow us to run a command with <code>yiic sitemap --type=News</code>: * action method will allow us to run a command with <code>yiic sitemap --type=News</code>:
* <pre> * <pre>
* class SitemapCommand { * class SitemapCommand extends CConsoleCommand {
* public function actionIndex($type) { * public function actionIndex($type) {
* .... * ....
* } * }
@ -274,9 +274,9 @@ abstract class CConsoleCommand extends CComponent
$help='Usage: '.$this->getCommandRunner()->getScriptName().' '.$this->getName(); $help='Usage: '.$this->getCommandRunner()->getScriptName().' '.$this->getName();
$options=$this->getOptionHelp(); $options=$this->getOptionHelp();
if(empty($options)) if(empty($options))
return $help; return $help."\n";
if(count($options)===1) if(count($options)===1)
return $help.' '.$options[0]; return $help.' '.$options[0]."\n";
$help.=" <action>\nActions:\n"; $help.=" <action>\nActions:\n";
foreach($options as $option) foreach($options as $option)
$help.=' '.$option."\n"; $help.=' '.$option."\n";
@ -308,7 +308,14 @@ abstract class CConsoleCommand extends CComponent
{ {
$optional=$param->isDefaultValueAvailable(); $optional=$param->isDefaultValueAvailable();
$defaultValue=$optional ? $param->getDefaultValue() : null; $defaultValue=$optional ? $param->getDefaultValue() : null;
if(is_array($defaultValue)) {
$defaultValue = str_replace(array("\r\n", "\n", "\r"), "", print_r($defaultValue, true));
}
$name=$param->getName(); $name=$param->getName();
if($name==='args')
continue;
if($optional) if($optional)
$help.=" [--$name=$defaultValue]"; $help.=" [--$name=$defaultValue]";
else else
@ -494,6 +501,7 @@ abstract class CConsoleCommand extends CComponent
'/(c)hild$/i' => '\1hildren', '/(c)hild$/i' => '\1hildren',
'/(h)uman$/i' => '\1umans', '/(h)uman$/i' => '\1umans',
'/(m)an$/i' => '\1en', '/(m)an$/i' => '\1en',
'/(s)taff$/i' => '\1taff',
'/(t)ooth$/i' => '\1eeth', '/(t)ooth$/i' => '\1eeth',
'/(p)erson$/i' => '\1eople', '/(p)erson$/i' => '\1eople',
'/([m|l])ouse$/i' => '\1ice', '/([m|l])ouse$/i' => '\1ice',

View File

@ -4,7 +4,7 @@
* *
* @author Evgeny Blinov <e.a.blinov@gmail.com> * @author Evgeny Blinov <e.a.blinov@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -35,7 +35,7 @@ class CConsoleCommandBehavior extends CBehavior
} }
/** /**
* Responds to {@link CConsoleCommand::onBeforeAction} event. * Responds to {@link CConsoleCommand::onBeforeAction} event.
* Overrides this method if you want to handle the corresponding event of the {@link CBehavior::owner owner}. * Override this method and make it public if you want to handle the corresponding event of the {@link CBehavior::owner owner}.
* @param CConsoleCommandEvent $event event parameter * @param CConsoleCommandEvent $event event parameter
*/ */
protected function beforeAction($event) protected function beforeAction($event)
@ -44,7 +44,7 @@ class CConsoleCommandBehavior extends CBehavior
/** /**
* Responds to {@link CConsoleCommand::onAfterAction} event. * Responds to {@link CConsoleCommand::onAfterAction} event.
* Overrides this method if you want to handle the corresponding event of the {@link CBehavior::owner owner}. * Override this method and make it public if you want to handle the corresponding event of the {@link CBehavior::owner owner}.
* @param CConsoleCommandEvent $event event parameter * @param CConsoleCommandEvent $event event parameter
*/ */
protected function afterAction($event) protected function afterAction($event)

View File

@ -4,7 +4,7 @@
* *
* @author Evgeny Blinov <e.a.blinov@gmail.com> * @author Evgeny Blinov <e.a.blinov@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -12,6 +12,7 @@
* CConsoleCommandRunner manages commands and executes the requested command. * CConsoleCommandRunner manages commands and executes the requested command.
* *
* @property string $scriptName The entry script name. * @property string $scriptName The entry script name.
* @property CConsoleCommand $command The currently active command.
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @package system.console * @package system.console
@ -41,6 +42,7 @@ class CConsoleCommandRunner extends CComponent
public $commands=array(); public $commands=array();
private $_scriptName; private $_scriptName;
private $_command;
/** /**
* Executes the requested command. * Executes the requested command.
@ -61,10 +63,14 @@ class CConsoleCommandRunner extends CComponent
else else
$name='help'; $name='help';
$oldCommand=$this->_command;
if(($command=$this->createCommand($name))===null) if(($command=$this->createCommand($name))===null)
$command=$this->createCommand('help'); $command=$this->createCommand('help');
$this->_command=$command;
$command->init(); $command->init();
return $command->run($args); $exitCode=$command->run($args);
$this->_command=$oldCommand;
return $exitCode;
} }
/** /**
@ -75,6 +81,25 @@ class CConsoleCommandRunner extends CComponent
return $this->_scriptName; return $this->_scriptName;
} }
/**
* Returns the currently running command.
* @return CConsoleCommand|null the currently active command.
* @since 1.1.14
*/
public function getCommand()
{
return $this->_command;
}
/**
* @param CConsoleCommand $value the currently active command.
* @since 1.1.14
*/
public function setCommand($value)
{
$this->_command=$value;
}
/** /**
* Searches for commands under the specified directory. * Searches for commands under the specified directory.
* @param string $path the directory containing the command class files. * @param string $path the directory containing the command class files.

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -22,7 +22,7 @@
* If an SQL statement returns results (such as a SELECT SQL), the results * If an SQL statement returns results (such as a SELECT SQL), the results
* can be accessed via the returned {@link CDbDataReader}. * can be accessed via the returned {@link CDbDataReader}.
* *
* CDbCommand supports SQL statment preparation and parameter binding. * CDbCommand supports SQL statement preparation and parameter binding.
* Call {@link bindParam} to bind a PHP variable to a parameter in SQL. * Call {@link bindParam} to bind a PHP variable to a parameter in SQL.
* Call {@link bindValue} to bind a value to an SQL parameter. * Call {@link bindValue} to bind a value to an SQL parameter.
* When binding a parameter, the SQL statement is automatically prepared. * When binding a parameter, the SQL statement is automatically prepared.
@ -47,7 +47,7 @@
* @property string $from The FROM part (without 'FROM' ) in the query. * @property string $from The FROM part (without 'FROM' ) in the query.
* @property string $where The WHERE part (without 'WHERE' ) in the query. * @property string $where The WHERE part (without 'WHERE' ) in the query.
* @property mixed $join The join part in the query. This can be an array representing * @property mixed $join The join part in the query. This can be an array representing
* multiple join fragments, or a string representing a single jojin fragment. * multiple join fragments, or a string representing a single join fragment.
* Each join fragment will contain the proper join operator (e.g. LEFT JOIN). * Each join fragment will contain the proper join operator (e.g. LEFT JOIN).
* @property string $group The GROUP BY part (without 'GROUP BY' ) in the query. * @property string $group The GROUP BY part (without 'GROUP BY' ) in the query.
* @property string $having The HAVING part (without 'HAVING' ) in the query. * @property string $having The HAVING part (without 'HAVING' ) in the query.
@ -200,6 +200,7 @@ class CDbCommand extends CComponent
* this may improve performance. * this may improve performance.
* For SQL statement with binding parameters, this method is invoked * For SQL statement with binding parameters, this method is invoked
* automatically. * automatically.
* @throws CDbException if CDbCommand failed to prepare the SQL statement
*/ */
public function prepare() public function prepare()
{ {
@ -310,7 +311,7 @@ class CDbCommand extends CComponent
* Please also note that all values are treated as strings in this case, if you need them to be handled as * Please also note that all values are treated as strings in this case, if you need them to be handled as
* their real data types, you have to use {@link bindParam} or {@link bindValue} instead. * their real data types, you have to use {@link bindParam} or {@link bindValue} instead.
* @return integer number of rows affected by the execution. * @return integer number of rows affected by the execution.
* @throws CException execution failed * @throws CDbException execution failed
*/ */
public function execute($params=array()) public function execute($params=array())
{ {
@ -463,6 +464,7 @@ class CDbCommand extends CComponent
* you cannot bind parameters or values using {@link bindParam} or {@link bindValue}, and vice versa. * you cannot bind parameters or values using {@link bindParam} or {@link bindValue}, and vice versa.
* Please also note that all values are treated as strings in this case, if you need them to be handled as * Please also note that all values are treated as strings in this case, if you need them to be handled as
* their real data types, you have to use {@link bindParam} or {@link bindValue} instead. * their real data types, you have to use {@link bindParam} or {@link bindValue} instead.
* @throws CDbException if CDbCommand failed to execute the SQL statement
* @return mixed the method execution result * @return mixed the method execution result
*/ */
private function queryInternal($method,$mode,$params=array()) private function queryInternal($method,$mode,$params=array())
@ -549,6 +551,7 @@ class CDbCommand extends CComponent
* query options are supported: {@link select}, {@link distinct}, {@link from}, * query options are supported: {@link select}, {@link distinct}, {@link from},
* {@link where}, {@link join}, {@link group}, {@link having}, {@link order}, * {@link where}, {@link join}, {@link group}, {@link having}, {@link order},
* {@link limit}, {@link offset} and {@link union}. * {@link limit}, {@link offset} and {@link union}.
* @throws CDbException if "from" key is not present in given query parameter
* @return string the SQL statement * @return string the SQL statement
* @since 1.1.6 * @since 1.1.6
*/ */
@ -1313,7 +1316,7 @@ class CDbCommand extends CComponent
* @param string $table the name of the table to be created. The name will be properly quoted by the method. * @param string $table the name of the table to be created. The name will be properly quoted by the method.
* @param array $columns the columns (name=>definition) in the new table. * @param array $columns the columns (name=>definition) in the new table.
* @param string $options additional SQL fragment that will be appended to the generated SQL. * @param string $options additional SQL fragment that will be appended to the generated SQL.
* @return integer number of rows affected by the execution. * @return integer 0 is always returned. See {@link http://php.net/manual/en/pdostatement.rowcount.php} for more information.
* @since 1.1.6 * @since 1.1.6
*/ */
public function createTable($table, $columns, $options=null) public function createTable($table, $columns, $options=null)
@ -1325,7 +1328,7 @@ class CDbCommand extends CComponent
* Builds and executes a SQL statement for renaming a DB table. * Builds and executes a SQL statement for renaming a DB table.
* @param string $table the table to be renamed. The name will be properly quoted by the method. * @param string $table the table to be renamed. The name will be properly quoted by the method.
* @param string $newName the new table name. The name will be properly quoted by the method. * @param string $newName the new table name. The name will be properly quoted by the method.
* @return integer number of rows affected by the execution. * @return integer 0 is always returned. See {@link http://php.net/manual/en/pdostatement.rowcount.php} for more information.
* @since 1.1.6 * @since 1.1.6
*/ */
public function renameTable($table, $newName) public function renameTable($table, $newName)
@ -1336,7 +1339,7 @@ class CDbCommand extends CComponent
/** /**
* Builds and executes a SQL statement for dropping a DB table. * Builds and executes a SQL statement for dropping a DB table.
* @param string $table the table to be dropped. The name will be properly quoted by the method. * @param string $table the table to be dropped. The name will be properly quoted by the method.
* @return integer number of rows affected by the execution. * @return integer 0 is always returned. See {@link http://php.net/manual/en/pdostatement.rowcount.php} for more information.
* @since 1.1.6 * @since 1.1.6
*/ */
public function dropTable($table) public function dropTable($table)
@ -1474,6 +1477,7 @@ class CDbCommand extends CComponent
/** /**
* Generates the condition string that will be put in the WHERE part * Generates the condition string that will be put in the WHERE part
* @param mixed $conditions the conditions that will be put in the WHERE part. * @param mixed $conditions the conditions that will be put in the WHERE part.
* @throws CDbException if unknown operator is used
* @return string the condition string to put in the WHERE part * @return string the condition string to put in the WHERE part
*/ */
private function processConditions($conditions) private function processConditions($conditions)

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -157,7 +157,7 @@ class CDbConnection extends CApplicationComponent
*/ */
public $queryCachingDuration=0; public $queryCachingDuration=0;
/** /**
* @var CCacheDependency the dependency that will be used when saving query results into cache. * @var CCacheDependency|ICacheDependency the dependency that will be used when saving query results into cache.
* @see queryCachingDuration * @see queryCachingDuration
* @since 1.1.7 * @since 1.1.7
*/ */
@ -343,7 +343,8 @@ class CDbConnection extends CApplicationComponent
* without actually executing the SQL statement. * without actually executing the SQL statement.
* @param integer $duration the number of seconds that query results may remain valid in cache. * @param integer $duration the number of seconds that query results may remain valid in cache.
* If this is 0, the caching will be disabled. * If this is 0, the caching will be disabled.
* @param CCacheDependency $dependency the dependency that will be used when saving the query results into cache. * @param CCacheDependency|ICacheDependency $dependency the dependency that will be used when saving
* the query results into cache.
* @param integer $queryCount number of SQL queries that need to be cached after calling this method. Defaults to 1, * @param integer $queryCount number of SQL queries that need to be cached after calling this method. Defaults to 1,
* meaning that the next SQL query will be cached. * meaning that the next SQL query will be cached.
* @return CDbConnection the connection instance itself. * @return CDbConnection the connection instance itself.
@ -405,7 +406,8 @@ class CDbConnection extends CApplicationComponent
/** /**
* Creates the PDO instance. * Creates the PDO instance.
* When some functionalities are missing in the pdo driver, we may use * When some functionalities are missing in the pdo driver, we may use
* an adapter class to provides them. * an adapter class to provide them.
* @throws CDbException when failed to open DB connection
* @return PDO the pdo instance * @return PDO the pdo instance
*/ */
protected function createPdoInstance() protected function createPdoInstance()
@ -419,8 +421,17 @@ class CDbConnection extends CApplicationComponent
elseif($driver==='sqlsrv') elseif($driver==='sqlsrv')
$pdoClass='CMssqlSqlsrvPdoAdapter'; $pdoClass='CMssqlSqlsrvPdoAdapter';
} }
return new $pdoClass($this->connectionString,$this->username,
$this->password,$this->_attributes); if(!class_exists($pdoClass))
throw new CDbException(Yii::t('yii','CDbConnection is unable to find PDO class "{className}". Make sure PDO is installed correctly.',
array('{className}'=>$pdoClass)));
@$instance=new $pdoClass($this->connectionString,$this->username,$this->password,$this->_attributes);
if(!$instance)
throw new CDbException(Yii::t('yii','CDbConnection failed to open the DB connection.'));
return $instance;
} }
/** /**
@ -498,6 +509,7 @@ class CDbConnection extends CApplicationComponent
/** /**
* Returns the database schema for the current connection * Returns the database schema for the current connection
* @throws CDbException if CDbConnection does not support reading schema for specified database driver
* @return CDbSchema the database schema for the current connection * @return CDbSchema the database schema for the current connection
*/ */
public function getSchema() public function getSchema()

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -137,7 +137,7 @@ class CDbDataReader extends CComponent implements Iterator, Countable
/** /**
* Closes the reader. * Closes the reader.
* This frees up the resources allocated for executing this SQL statement. * This frees up the resources allocated for executing this SQL statement.
* Read attemps after this method call are unpredictable. * Read attempts after this method call are unpredictable.
*/ */
public function close() public function close()
{ {

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -20,6 +20,9 @@
* the database used in an application; while the {@link down} method contains "downgrading" * the database used in an application; while the {@link down} method contains "downgrading"
* logic. The "yiic migrate" command manages all available migrations in an application. * logic. The "yiic migrate" command manages all available migrations in an application.
* *
* By overriding {@link safeUp} or {@link safeDown} methods instead of {@link up} and {@link down}
* the migration logic will be wrapped with a DB transaction.
*
* CDbMigration provides a set of convenient methods for manipulating database data and schema. * CDbMigration provides a set of convenient methods for manipulating database data and schema.
* For example, the {@link insert} method can be used to easily insert a row of data into * For example, the {@link insert} method can be used to easily insert a row of data into
* a database table; the {@link createTable} method can be used to create a database table. * a database table; the {@link createTable} method can be used to create a database table.
@ -40,7 +43,7 @@ abstract class CDbMigration extends CComponent
/** /**
* This method contains the logic to be executed when applying this migration. * This method contains the logic to be executed when applying this migration.
* Child classes may implement this method to provide actual migration logic. * Child classes may implement this method to provide actual migration logic.
* @return boolean * @return boolean Returning false means, the migration will not be applied.
*/ */
public function up() public function up()
{ {
@ -65,9 +68,8 @@ abstract class CDbMigration extends CComponent
/** /**
* This method contains the logic to be executed when removing this migration. * This method contains the logic to be executed when removing this migration.
* The default implementation throws an exception indicating the migration cannot be removed.
* Child classes may override this method if the corresponding migrations can be removed. * Child classes may override this method if the corresponding migrations can be removed.
* @return boolean * @return boolean Returning false means, the migration will not be applied.
*/ */
public function down() public function down()
{ {
@ -96,7 +98,8 @@ abstract class CDbMigration extends CComponent
* be enclosed within a DB transaction. * be enclosed within a DB transaction.
* Child classes may implement this method instead of {@link up} if the DB logic * Child classes may implement this method instead of {@link up} if the DB logic
* needs to be within a transaction. * needs to be within a transaction.
* @return boolean * @return boolean Returning false means, the migration will not be applied and
* the transaction will be rolled back.
* @since 1.1.7 * @since 1.1.7
*/ */
public function safeUp() public function safeUp()
@ -109,7 +112,8 @@ abstract class CDbMigration extends CComponent
* be enclosed within a DB transaction. * be enclosed within a DB transaction.
* Child classes may implement this method instead of {@link up} if the DB logic * Child classes may implement this method instead of {@link up} if the DB logic
* needs to be within a transaction. * needs to be within a transaction.
* @return boolean * @return boolean Returning false means, the migration will not be applied and
* the transaction will be rolled back.
* @since 1.1.7 * @since 1.1.7
*/ */
public function safeDown() public function safeDown()
@ -122,6 +126,7 @@ abstract class CDbMigration extends CComponent
* You can call {@link setDbConnection} to switch to a different database connection. * You can call {@link setDbConnection} to switch to a different database connection.
* Methods such as {@link insert}, {@link createTable} will use this database connection * Methods such as {@link insert}, {@link createTable} will use this database connection
* to perform DB queries. * to perform DB queries.
* @throws CException if "db" application component is not configured
* @return CDbConnection the currently active database connection * @return CDbConnection the currently active database connection
*/ */
public function getDbConnection() public function getDbConnection()
@ -422,9 +427,9 @@ abstract class CDbMigration extends CComponent
*/ */
public function dropPrimaryKey($name,$table) public function dropPrimaryKey($name,$table)
{ {
echo " > alter table $table drop constraint $name primary key $column ..."; echo " > alter table $table drop primary key $name ...";
$time=microtime(true); $time=microtime(true);
$this->getDbConnection()->createCommand()->dropPrimaryKey($name,$table); $this->getDbConnection()->createCommand()->dropPrimaryKey($name,$table);
echo " done (time: ".sprintf('%.3f', microtime(true)-$time)."s)\n"; echo " done (time: ".sprintf('%.3f', microtime(true)-$time)."s)\n";
} }
} }

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -1,10 +1,10 @@
<?php <?php
/** /**
* CActiveRecord class file. * CActiveFinder class file.
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -169,6 +169,19 @@ class CActiveFinder extends CComponent
$this->destroyJoinTree(); $this->destroyJoinTree();
} }
/**
* Given active record class name returns new model instance.
*
* @param string $className active record class name
* @return CActiveRecord active record model instance
*
* @since 1.1.14
*/
public function getModel($className)
{
return CActiveRecord::model($className);
}
private function destroyJoinTree() private function destroyJoinTree()
{ {
if($this->_joinTree!==null) if($this->_joinTree!==null)
@ -181,6 +194,8 @@ class CActiveFinder extends CComponent
* @param CJoinElement $parent the parent tree node * @param CJoinElement $parent the parent tree node
* @param mixed $with the names of the related objects relative to the parent tree node * @param mixed $with the names of the related objects relative to the parent tree node
* @param array $options additional query options to be merged with the relation * @param array $options additional query options to be merged with the relation
* @throws CDbException if given parent tree node is an instance of {@link CStatElement}
* or relation is not defined in the given parent's tree node model class
*/ */
private function buildJoinTree($parent,$with,$options=null) private function buildJoinTree($parent,$with,$options=null)
{ {
@ -212,7 +227,7 @@ class CActiveFinder extends CComponent
array('{class}'=>get_class($parent->model), '{name}'=>$with))); array('{class}'=>get_class($parent->model), '{name}'=>$with)));
$relation=clone $relation; $relation=clone $relation;
$model=CActiveRecord::model($relation->className); $model=$this->getModel($relation->className);
if($relation instanceof CActiveRelation) if($relation instanceof CActiveRelation)
{ {
@ -263,7 +278,7 @@ class CActiveFinder extends CComponent
$element=new CJoinElement($this,$relation,$parent,++$this->_joinCount); $element=new CJoinElement($this,$relation,$parent,++$this->_joinCount);
if(!empty($relation->through)) if(!empty($relation->through))
{ {
$slave=$this->buildJoinTree($parent,$relation->through,array('select'=>false)); $slave=$this->buildJoinTree($parent,$relation->through,array('select'=>''));
$slave->master=$element; $slave->master=$element;
$element->slave=$slave; $element->slave=$slave;
} }
@ -361,7 +376,7 @@ class CJoinElement
{ {
$this->relation=$relation; $this->relation=$relation;
$this->_parent=$parent; $this->_parent=$parent;
$this->model=CActiveRecord::model($relation->className); $this->model=$this->_finder->getModel($relation->className);
$this->_builder=$this->model->getCommandBuilder(); $this->_builder=$this->model->getCommandBuilder();
$this->tableAlias=$relation->alias===null?$relation->name:$relation->alias; $this->tableAlias=$relation->alias===null?$relation->name:$relation->alias;
$this->rawTableAlias=$this->_builder->getSchema()->quoteTableName($this->tableAlias); $this->rawTableAlias=$this->_builder->getSchema()->quoteTableName($this->tableAlias);
@ -458,7 +473,11 @@ class CJoinElement
if(!$this->children) if(!$this->children)
return; return;
$child=end($this->children); // bridge(s) inside, we're taking only last necessary child
$params=array();
foreach($this->children as $child)
if(is_array($child->relation->params))
$params=array_merge($params,$child->relation->params);
$query=new CJoinQuery($child); $query=new CJoinQuery($child);
$query->selects=array($child->getColumnSelect($child->relation->select)); $query->selects=array($child->getColumnSelect($child->relation->select));
@ -470,8 +489,7 @@ class CJoinElement
$query->joins[]=$child->relation->join; $query->joins[]=$child->relation->join;
$query->havings[]=$child->relation->having; $query->havings[]=$child->relation->having;
$query->orders[]=$child->relation->order; $query->orders[]=$child->relation->order;
if(is_array($child->relation->params)) $query->params=$params;
$query->params=$child->relation->params;
$query->elements[$child->id]=true; $query->elements[$child->id]=true;
if($child->relation instanceof CHasManyRelation) if($child->relation instanceof CHasManyRelation)
{ {
@ -511,6 +529,7 @@ class CJoinElement
* Apply Lazy Condition * Apply Lazy Condition
* @param CJoinQuery $query represents a JOIN SQL statements * @param CJoinQuery $query represents a JOIN SQL statements
* @param CActiveRecord $record the active record whose related object is to be fetched. * @param CActiveRecord $record the active record whose related object is to be fetched.
* @throws CDbException if relation in active record class is not specified correctly
*/ */
private function applyLazyCondition($query,$record) private function applyLazyCondition($query,$record)
{ {
@ -598,10 +617,19 @@ class CJoinElement
else else
{ {
$element=$this; $element=$this;
while($element->slave!==null) while(true)
{ {
$query->joins[]=$element->slave->joinOneMany($element->slave,$element->relation->foreignKey,$element,$parent); $condition=$element->relation->condition;
$element=$element->slave; if(!empty($condition))
$query->conditions[]=$condition;
$query->params=array_merge($query->params,$element->relation->params);
if($element->slave!==null)
{
$query->joins[]=$element->slave->joinOneMany($element->slave,$element->relation->foreignKey,$element,$parent);
$element=$element->slave;
}
else
break;
} }
$fks=is_array($element->relation->foreignKey) ? $element->relation->foreignKey : preg_split('/\s*,\s*/',$element->relation->foreignKey,-1,PREG_SPLIT_NO_EMPTY); $fks=is_array($element->relation->foreignKey) ? $element->relation->foreignKey : preg_split('/\s*,\s*/',$element->relation->foreignKey,-1,PREG_SPLIT_NO_EMPTY);
$prefix=$element->getColumnPrefix(); $prefix=$element->getColumnPrefix();
@ -614,16 +642,16 @@ class CJoinElement
$fk=$i; $fk=$i;
} }
if($this->relation instanceof CBelongsToRelation) if($element->relation instanceof CBelongsToRelation)
{ {
if(is_int($i)) if(is_int($i))
{ {
if(isset($parent->_table->foreignKeys[$fk])) // FK defined if(isset($parent->_table->foreignKeys[$fk])) // FK defined
$pk=$parent->_table->foreignKeys[$fk][1]; $pk=$parent->_table->foreignKeys[$fk][1];
elseif(is_array($this->_table->primaryKey)) // composite PK elseif(is_array($element->_table->primaryKey)) // composite PK
$pk=$this->_table->primaryKey[$i]; $pk=$element->_table->primaryKey[$i];
else else
$pk=$this->_table->primaryKey; $pk=$element->_table->primaryKey;
} }
$params[$pk]=$record->$fk; $params[$pk]=$record->$fk;
} }
@ -631,8 +659,8 @@ class CJoinElement
{ {
if(is_int($i)) if(is_int($i))
{ {
if(isset($this->_table->foreignKeys[$fk])) // FK defined if(isset($element->_table->foreignKeys[$fk])) // FK defined
$pk=$this->_table->foreignKeys[$fk][1]; $pk=$element->_table->foreignKeys[$fk][1];
elseif(is_array($parent->_table->primaryKey)) // composite PK elseif(is_array($parent->_table->primaryKey)) // composite PK
$pk=$parent->_table->primaryKey[$i]; $pk=$parent->_table->primaryKey[$i];
else else
@ -699,23 +727,37 @@ class CJoinElement
$this->_finder->joinAll=true; $this->_finder->joinAll=true;
$this->buildQuery($query); $this->buildQuery($query);
$select=is_array($criteria->select) ? implode(',',$criteria->select) : $criteria->select; $query->limit=$query->offset=-1;
if($select!=='*' && !strncasecmp($select,'count',5))
$query->selects=array($select); if(!empty($criteria->group) || !empty($criteria->having))
elseif(is_string($this->_table->primaryKey))
{ {
$prefix=$this->getColumnPrefix(); $query->orders = array();
$schema=$this->_builder->getSchema(); $command=$query->createCommand($this->_builder);
$column=$prefix.$schema->quoteColumnName($this->_table->primaryKey); $sql=$command->getText();
$query->selects=array("COUNT(DISTINCT $column)"); $sql="SELECT COUNT(*) FROM ({$sql}) sq";
$command->setText($sql);
$command->params=$query->params;
return $command->queryScalar();
} }
else else
$query->selects=array("COUNT(*)"); {
$select=is_array($criteria->select) ? implode(',',$criteria->select) : $criteria->select;
if($select!=='*' && !strncasecmp($select,'count',5))
$query->selects=array($select);
elseif(is_string($this->_table->primaryKey))
{
$prefix=$this->getColumnPrefix();
$schema=$this->_builder->getSchema();
$column=$prefix.$schema->quoteColumnName($this->_table->primaryKey);
$query->selects=array("COUNT(DISTINCT $column)");
}
else
$query->selects=array("COUNT(*)");
$query->orders=$query->groups=$query->havings=array(); $query->orders=$query->groups=$query->havings=array();
$query->limit=$query->offset=-1; $command=$query->createCommand($this->_builder);
$command=$query->createCommand($this->_builder); return $command->queryScalar();
return $command->queryScalar(); }
} }
/** /**
@ -857,6 +899,7 @@ class CJoinElement
* Generates the list of columns to be selected. * Generates the list of columns to be selected.
* Columns will be properly aliased and primary keys will be added to selection if they are not specified. * Columns will be properly aliased and primary keys will be added to selection if they are not specified.
* @param mixed $select columns to be selected. Defaults to '*', indicating all columns. * @param mixed $select columns to be selected. Defaults to '*', indicating all columns.
* @throws CDbException if active record class is trying to select an invalid column
* @return string the column selection * @return string the column selection
*/ */
public function getColumnSelect($select='*') public function getColumnSelect($select='*')
@ -977,6 +1020,7 @@ class CJoinElement
} }
/** /**
* @throws CDbException if relation in active record class is not specified correctly
* @return string the join statement (this node joins with its parent) * @return string the join statement (this node joins with its parent)
*/ */
public function getJoinCondition() public function getJoinCondition()
@ -996,21 +1040,30 @@ class CJoinElement
else else
{ {
$fks=is_array($this->relation->foreignKey) ? $this->relation->foreignKey : preg_split('/\s*,\s*/',$this->relation->foreignKey,-1,PREG_SPLIT_NO_EMPTY); $fks=is_array($this->relation->foreignKey) ? $this->relation->foreignKey : preg_split('/\s*,\s*/',$this->relation->foreignKey,-1,PREG_SPLIT_NO_EMPTY);
if($this->relation instanceof CBelongsToRelation) if($this->slave!==null)
{
if($this->relation instanceof CBelongsToRelation)
{
$fks=array_flip($fks);
$pke=$this->slave;
$fke=$this;
}
else
{
$pke=$this;
$fke=$this->slave;
}
}
elseif($this->relation instanceof CBelongsToRelation)
{ {
$pke=$this; $pke=$this;
$fke=$parent; $fke=$parent;
} }
elseif($this->slave===null) else
{ {
$pke=$parent; $pke=$parent;
$fke=$this; $fke=$this;
} }
else
{
$pke=$this;
$fke=$this->slave;
}
return $this->joinOneMany($fke,$fks,$pke,$parent); return $this->joinOneMany($fke,$fks,$pke,$parent);
} }
} }
@ -1020,7 +1073,7 @@ class CJoinElement
* This works for HAS_ONE, HAS_MANY and BELONGS_TO. * This works for HAS_ONE, HAS_MANY and BELONGS_TO.
* @param CJoinElement $fke the join element containing foreign keys * @param CJoinElement $fke the join element containing foreign keys
* @param array $fks the foreign keys * @param array $fks the foreign keys
* @param CJoinElement $pke the join element containg primary keys * @param CJoinElement $pke the join element contains primary keys
* @param CJoinElement $parent the parent join element * @param CJoinElement $parent the parent join element
* @return string the join statement * @return string the join statement
* @throws CDbException if a foreign key is invalid * @throws CDbException if a foreign key is invalid
@ -1344,7 +1397,7 @@ class CStatElement
private function queryOneMany() private function queryOneMany()
{ {
$relation=$this->relation; $relation=$this->relation;
$model=CActiveRecord::model($relation->className); $model=$this->_finder->getModel($relation->className);
$builder=$model->getCommandBuilder(); $builder=$model->getCommandBuilder();
$schema=$builder->getSchema(); $schema=$builder->getSchema();
$table=$model->getTableSchema(); $table=$model->getTableSchema();
@ -1398,7 +1451,7 @@ class CStatElement
// generate and perform query // generate and perform query
if(count($fks)===1) // single column FK if(count($fks)===1) // single column FK
{ {
$col=$table->columns[$fks[0]]->rawName; $col=$tableAlias.'.'.$table->columns[$fks[0]]->rawName;
$sql="SELECT $col AS $c, {$relation->select} AS $s FROM {$table->rawName} ".$tableAlias.$join $sql="SELECT $col AS $c, {$relation->select} AS $s FROM {$table->rawName} ".$tableAlias.$join
.$where.'('.$builder->createInCondition($table,$fks[0],array_keys($records),$tableAlias.'.').')' .$where.'('.$builder->createInCondition($table,$fks[0],array_keys($records),$tableAlias.'.').')'
." GROUP BY $col".$group ." GROUP BY $col".$group
@ -1423,7 +1476,7 @@ class CStatElement
$cols=array(); $cols=array();
foreach($pkTable->primaryKey as $n=>$pk) foreach($pkTable->primaryKey as $n=>$pk)
{ {
$name=$table->columns[$map[$pk]]->rawName; $name=$tableAlias.'.'.$table->columns[$map[$pk]]->rawName;
$cols[$name]=$name.' AS '.$schema->quoteColumnName('c'.$n); $cols[$name]=$name.' AS '.$schema->quoteColumnName('c'.$n);
} }
$sql='SELECT '.implode(', ',$cols).", {$relation->select} AS $s FROM {$table->rawName} ".$tableAlias.$join $sql='SELECT '.implode(', ',$cols).", {$relation->select} AS $s FROM {$table->rawName} ".$tableAlias.$join
@ -1455,7 +1508,7 @@ class CStatElement
private function queryManyMany($joinTableName,$keys) private function queryManyMany($joinTableName,$keys)
{ {
$relation=$this->relation; $relation=$this->relation;
$model=CActiveRecord::model($relation->className); $model=$this->_finder->getModel($relation->className);
$table=$model->getTableSchema(); $table=$model->getTableSchema();
$builder=$model->getCommandBuilder(); $builder=$model->getCommandBuilder();
$schema=$builder->getSchema(); $schema=$builder->getSchema();
@ -1464,7 +1517,7 @@ class CStatElement
$tableAlias=$model->getTableAlias(true); $tableAlias=$model->getTableAlias(true);
if(($joinTable=$builder->getSchema()->getTable($joinTableName))===null) if(($joinTable=$builder->getSchema()->getTable($joinTableName))===null)
throw new CDbException(Yii::t('yii','The relation "{relation}" in active record class "{class}" is not specified correctly. The join table "{joinTable}" given in the foreign key cannot be found in the database.', throw new CDbException(Yii::t('yii','The relation "{relation}" in active record class "{class}" is not specified correctly: the join table "{joinTable}" given in the foreign key cannot be found in the database.',
array('{class}'=>get_class($this->_parent->model), '{relation}'=>$relation->name, '{joinTable}'=>$joinTableName))); array('{class}'=>get_class($this->_parent->model), '{relation}'=>$relation->name, '{joinTable}'=>$joinTableName)));
$fks=preg_split('/\s*,\s*/',$keys,-1,PREG_SPLIT_NO_EMPTY); $fks=preg_split('/\s*,\s*/',$keys,-1,PREG_SPLIT_NO_EMPTY);
@ -1582,4 +1635,4 @@ class CStatElement
foreach($records as $pk=>$record) foreach($records as $pk=>$record)
$record->addRelatedRecord($relation->name,isset($stats[$pk])?$stats[$pk]:$this->relation->defaultValue,false); $record->addRelatedRecord($relation->name,isset($stats[$pk])?$stats[$pk]:$this->relation->defaultValue,false);
} }
} }

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -53,8 +53,8 @@ abstract class CActiveRecord extends CModel
public static $db; public static $db;
private static $_models=array(); // class name => model private static $_models=array(); // class name => model
private static $_md=array(); // class name => meta data
private $_md; // meta data
private $_new=false; // whether this instance is new or not private $_new=false; // whether this instance is new or not
private $_attributes=array(); // attribute name => attribute value private $_attributes=array(); // attribute name => attribute value
private $_related=array(); // attribute name => related objects private $_related=array(); // attribute name => related objects
@ -66,6 +66,8 @@ abstract class CActiveRecord extends CModel
/** /**
* Constructor. * Constructor.
* @param string $scenario scenario name. See {@link CModel::scenario} for more details about this parameter. * @param string $scenario scenario name. See {@link CModel::scenario} for more details about this parameter.
* Note: in order to setup initial model parameters use {@link init()} or {@link afterConstruct()}.
* Do NOT override the constructor unless it is absolutely necessary!
*/ */
public function __construct($scenario='insert') public function __construct($scenario='insert')
{ {
@ -99,7 +101,8 @@ abstract class CActiveRecord extends CModel
* It changes the query caching parameter of the {@link dbConnection} instance. * It changes the query caching parameter of the {@link dbConnection} instance.
* @param integer $duration the number of seconds that query results may remain valid in cache. * @param integer $duration the number of seconds that query results may remain valid in cache.
* If this is 0, the caching will be disabled. * If this is 0, the caching will be disabled.
* @param CCacheDependency $dependency the dependency that will be used when saving the query results into cache. * @param CCacheDependency|ICacheDependency $dependency the dependency that will be used when saving
* the query results into cache.
* @param integer $queryCount number of SQL queries that need to be cached after calling this method. Defaults to 1, * @param integer $queryCount number of SQL queries that need to be cached after calling this method. Defaults to 1,
* meaning that the next SQL query will be cached. * meaning that the next SQL query will be cached.
* @return CActiveRecord the active record instance itself. * @return CActiveRecord the active record instance itself.
@ -118,7 +121,6 @@ abstract class CActiveRecord extends CModel
*/ */
public function __sleep() public function __sleep()
{ {
$this->_md=null;
return array_keys((array)$this); return array_keys((array)$this);
} }
@ -234,7 +236,14 @@ abstract class CActiveRecord extends CModel
* or an empty array. * or an empty array.
* @param string $name the relation name (see {@link relations}) * @param string $name the relation name (see {@link relations})
* @param boolean $refresh whether to reload the related objects from database. Defaults to false. * @param boolean $refresh whether to reload the related objects from database. Defaults to false.
* If the current record is not a new record and it does not have the related objects loaded they
* will be retrieved from the database even if this is set to false.
* If the current record is a new record and this value is false, the related objects will not be
* retrieved from the database.
* @param mixed $params array or CDbCriteria object with additional parameters that customize the query conditions as specified in the relation declaration. * @param mixed $params array or CDbCriteria object with additional parameters that customize the query conditions as specified in the relation declaration.
* If this is supplied the related record(s) will be retrieved from the database regardless of the value or {@link $refresh}.
* The related record(s) retrieved when this is supplied will only be returned by this method and will not be loaded into the current record's relation.
* The value of the relation prior to running this method will still be available for the current record if this is supplied.
* @return mixed the related object(s). * @return mixed the related object(s).
* @throws CDbException if the relation is not specified in {@link relations}. * @throws CDbException if the relation is not specified in {@link relations}.
*/ */
@ -268,7 +277,7 @@ abstract class CActiveRecord extends CModel
$r=$name; $r=$name;
unset($this->_related[$name]); unset($this->_related[$name]);
$finder=new CActiveFinder($this,$r); $finder=$this->getActiveFinder($r);
$finder->lazyFind($this); $finder->lazyFind($this);
if(!isset($this->_related[$name])) if(!isset($this->_related[$name]))
@ -384,7 +393,6 @@ abstract class CActiveRecord extends CModel
else else
{ {
$model=self::$_models[$className]=new $className(null); $model=self::$_models[$className]=new $className(null);
$model->_md=new CActiveRecordMetaData($model);
$model->attachBehaviors($model->behaviors()); $model->attachBehaviors($model->behaviors());
return $model; return $model;
} }
@ -396,10 +404,13 @@ abstract class CActiveRecord extends CModel
*/ */
public function getMetaData() public function getMetaData()
{ {
if($this->_md!==null) $className=get_class($this);
return $this->_md; if(!array_key_exists($className,self::$_md))
else {
return $this->_md=self::model(get_class($this))->_md; self::$_md[$className]=null; // preventing recursive invokes of {@link getMetaData()} via {@link __get()}
self::$_md[$className]=new CActiveRecordMetaData($this);
}
return self::$_md[$className];
} }
/** /**
@ -411,10 +422,9 @@ abstract class CActiveRecord extends CModel
*/ */
public function refreshMetaData() public function refreshMetaData()
{ {
$finder=self::model(get_class($this)); $className=get_class($this);
$finder->_md=new CActiveRecordMetaData($finder); if(array_key_exists($className,self::$_md))
if($this!==$finder) unset(self::$_md[$className]);
$this->_md=$finder->_md;
} }
/** /**
@ -612,6 +622,7 @@ abstract class CActiveRecord extends CModel
* Returns the database connection used by active record. * Returns the database connection used by active record.
* By default, the "db" application component is used as the database connection. * By default, the "db" application component is used as the database connection.
* You may override this method if you want to use a different database connection. * You may override this method if you want to use a different database connection.
* @throws CDbException if "db" application component is not defined
* @return CDbConnection the database connection used by active record. * @return CDbConnection the database connection used by active record.
*/ */
public function getDbConnection() public function getDbConnection()
@ -885,6 +896,35 @@ abstract class CActiveRecord extends CModel
$this->raiseEvent('onAfterFind',$event); $this->raiseEvent('onAfterFind',$event);
} }
/**
* Given 'with' options returns a new active finder instance.
*
* @param mixed $with the relation names to be actively looked for
* @return CActiveFinder active finder for the operation
*
* @since 1.1.14
*/
public function getActiveFinder($with)
{
return new CActiveFinder($this,$with);
}
/**
* This event is raised before an AR finder performs a count call.
* If you want to access or modify the query criteria used for the
* count call, you can use {@link getDbCriteria()} to customize it based on your needs.
* When modifying criteria in beforeCount you have to make sure you are using the right
* table alias which is different on normal count and relational call.
* You can use {@link getTableAlias()} to get the alias used for the upcoming count call.
* @param CModelEvent $event the event parameter
* @see beforeCount
* @since 1.1.14
*/
public function onBeforeCount($event)
{
$this->raiseEvent('onBeforeCount',$event);
}
/** /**
* This method is invoked before saving a record (after validation, if any). * This method is invoked before saving a record (after validation, if any).
* The default implementation raises the {@link onBeforeSave} event. * The default implementation raises the {@link onBeforeSave} event.
@ -968,6 +1008,20 @@ abstract class CActiveRecord extends CModel
} }
} }
/**
* This method is invoked before an AR finder executes a count call.
* The count calls include {@link count} and {@link countByAttributes}
* The default implementation raises the {@link onBeforeCount} event.
* If you override this method, make sure you call the parent implementation
* so that the event is raised properly.
* @since 1.1.14
*/
protected function beforeCount()
{
if($this->hasEventHandler('onBeforeCount'))
$this->onBeforeCount(new CEvent($this));
}
/** /**
* This method is invoked after each record is instantiated by a find method. * This method is invoked after each record is instantiated by a find method.
* The default implementation raises the {@link onAfterFind} event. * The default implementation raises the {@link onAfterFind} event.
@ -1091,8 +1145,8 @@ abstract class CActiveRecord extends CModel
* @param array $attributes attributes to be updated. Each element represents an attribute name * @param array $attributes attributes to be updated. Each element represents an attribute name
* or an attribute value indexed by its name. If the latter, the record's * or an attribute value indexed by its name. If the latter, the record's
* attribute will be changed accordingly before saving. * attribute will be changed accordingly before saving.
* @throws CDbException if the record is new
* @return boolean whether the update is successful * @return boolean whether the update is successful
* @throws CException if the record is new or any database error
*/ */
public function saveAttributes($attributes) public function saveAttributes($attributes)
{ {
@ -1155,8 +1209,8 @@ abstract class CActiveRecord extends CModel
/** /**
* Deletes the row corresponding to this active record. * Deletes the row corresponding to this active record.
* @throws CDbException if the record is new
* @return boolean whether the deletion is successful. * @return boolean whether the deletion is successful.
* @throws CException if the record is new
*/ */
public function delete() public function delete()
{ {
@ -1293,12 +1347,12 @@ abstract class CActiveRecord extends CModel
{ {
if(!$all) if(!$all)
$criteria->limit=1; $criteria->limit=1;
$command=$this->getCommandBuilder()->createFindCommand($this->getTableSchema(),$criteria); $command=$this->getCommandBuilder()->createFindCommand($this->getTableSchema(),$criteria,$this->getTableAlias());
return $all ? $this->populateRecords($command->queryAll(), true, $criteria->index) : $this->populateRecord($command->queryRow()); return $all ? $this->populateRecords($command->queryAll(), true, $criteria->index) : $this->populateRecord($command->queryRow());
} }
else else
{ {
$finder=new CActiveFinder($this,$criteria->with); $finder=$this->getActiveFinder($criteria->with);
return $finder->query($criteria,$all); return $finder->query($criteria,$all);
} }
} }
@ -1407,7 +1461,7 @@ abstract class CActiveRecord extends CModel
* See {@link find()} for detailed explanation about $condition and $params. * See {@link find()} for detailed explanation about $condition and $params.
* @param mixed $condition query condition or criteria. * @param mixed $condition query condition or criteria.
* @param array $params parameters to be bound to an SQL statement. * @param array $params parameters to be bound to an SQL statement.
* @return array list of active records satisfying the specified condition. An empty array is returned if none is found. * @return CActiveRecord[] list of active records satisfying the specified condition. An empty array is returned if none is found.
*/ */
public function findAll($condition='',$params=array()) public function findAll($condition='',$params=array())
{ {
@ -1438,7 +1492,7 @@ abstract class CActiveRecord extends CModel
* @param mixed $pk primary key value(s). Use array for multiple primary keys. For composite key, each key value must be an array (column name=>column value). * @param mixed $pk primary key value(s). Use array for multiple primary keys. For composite key, each key value must be an array (column name=>column value).
* @param mixed $condition query condition or criteria. * @param mixed $condition query condition or criteria.
* @param array $params parameters to be bound to an SQL statement. * @param array $params parameters to be bound to an SQL statement.
* @return array the records found. An empty array is returned if none is found. * @return CActiveRecord[] the records found. An empty array is returned if none is found.
*/ */
public function findAllByPk($pk,$condition='',$params=array()) public function findAllByPk($pk,$condition='',$params=array())
{ {
@ -1472,7 +1526,7 @@ abstract class CActiveRecord extends CModel
* An attribute value can be an array which will be used to generate an IN condition. * An attribute value can be an array which will be used to generate an IN condition.
* @param mixed $condition query condition or criteria. * @param mixed $condition query condition or criteria.
* @param array $params parameters to be bound to an SQL statement. * @param array $params parameters to be bound to an SQL statement.
* @return array the records found. An empty array is returned if none is found. * @return CActiveRecord[] the records found. An empty array is returned if none is found.
*/ */
public function findAllByAttributes($attributes,$condition='',$params=array()) public function findAllByAttributes($attributes,$condition='',$params=array())
{ {
@ -1495,7 +1549,7 @@ abstract class CActiveRecord extends CModel
if(($criteria=$this->getDbCriteria(false))!==null && !empty($criteria->with)) if(($criteria=$this->getDbCriteria(false))!==null && !empty($criteria->with))
{ {
$this->resetScope(false); $this->resetScope(false);
$finder=new CActiveFinder($this,$criteria->with); $finder=$this->getActiveFinder($criteria->with);
return $finder->findBySql($sql,$params); return $finder->findBySql($sql,$params);
} }
else else
@ -1509,7 +1563,7 @@ abstract class CActiveRecord extends CModel
* Finds all active records using the specified SQL statement. * Finds all active records using the specified SQL statement.
* @param string $sql the SQL statement * @param string $sql the SQL statement
* @param array $params parameters to be bound to the SQL statement * @param array $params parameters to be bound to the SQL statement
* @return array the records found. An empty array is returned if none is found. * @return CActiveRecord[] the records found. An empty array is returned if none is found.
*/ */
public function findAllBySql($sql,$params=array()) public function findAllBySql($sql,$params=array())
{ {
@ -1518,7 +1572,7 @@ abstract class CActiveRecord extends CModel
if(($criteria=$this->getDbCriteria(false))!==null && !empty($criteria->with)) if(($criteria=$this->getDbCriteria(false))!==null && !empty($criteria->with))
{ {
$this->resetScope(false); $this->resetScope(false);
$finder=new CActiveFinder($this,$criteria->with); $finder=$this->getActiveFinder($criteria->with);
return $finder->findAllBySql($sql,$params); return $finder->findAllBySql($sql,$params);
} }
else else
@ -1539,6 +1593,7 @@ abstract class CActiveRecord extends CModel
{ {
Yii::trace(get_class($this).'.count()','system.db.ar.CActiveRecord'); Yii::trace(get_class($this).'.count()','system.db.ar.CActiveRecord');
$builder=$this->getCommandBuilder(); $builder=$this->getCommandBuilder();
$this->beforeCount();
$criteria=$builder->createCriteria($condition,$params); $criteria=$builder->createCriteria($condition,$params);
$this->applyScopes($criteria); $this->applyScopes($criteria);
@ -1546,7 +1601,7 @@ abstract class CActiveRecord extends CModel
return $builder->createCountCommand($this->getTableSchema(),$criteria)->queryScalar(); return $builder->createCountCommand($this->getTableSchema(),$criteria)->queryScalar();
else else
{ {
$finder=new CActiveFinder($this,$criteria->with); $finder=$this->getActiveFinder($criteria->with);
return $finder->count($criteria); return $finder->count($criteria);
} }
} }
@ -1566,6 +1621,7 @@ abstract class CActiveRecord extends CModel
Yii::trace(get_class($this).'.countByAttributes()','system.db.ar.CActiveRecord'); Yii::trace(get_class($this).'.countByAttributes()','system.db.ar.CActiveRecord');
$prefix=$this->getTableAlias(true).'.'; $prefix=$this->getTableAlias(true).'.';
$builder=$this->getCommandBuilder(); $builder=$this->getCommandBuilder();
$this->beforeCount();
$criteria=$builder->createColumnCriteria($this->getTableSchema(),$attributes,$condition,$params,$prefix); $criteria=$builder->createColumnCriteria($this->getTableSchema(),$attributes,$condition,$params,$prefix);
$this->applyScopes($criteria); $this->applyScopes($criteria);
@ -1573,7 +1629,7 @@ abstract class CActiveRecord extends CModel
return $builder->createCountCommand($this->getTableSchema(),$criteria)->queryScalar(); return $builder->createCountCommand($this->getTableSchema(),$criteria)->queryScalar();
else else
{ {
$finder=new CActiveFinder($this,$criteria->with); $finder=$this->getActiveFinder($criteria->with);
return $finder->count($criteria); return $finder->count($criteria);
} }
} }
@ -1589,6 +1645,7 @@ abstract class CActiveRecord extends CModel
public function countBySql($sql,$params=array()) public function countBySql($sql,$params=array())
{ {
Yii::trace(get_class($this).'.countBySql()','system.db.ar.CActiveRecord'); Yii::trace(get_class($this).'.countBySql()','system.db.ar.CActiveRecord');
$this->beforeCount();
return $this->getCommandBuilder()->createSqlCommand($sql,$params)->queryScalar(); return $this->getCommandBuilder()->createSqlCommand($sql,$params)->queryScalar();
} }
@ -1610,11 +1667,11 @@ abstract class CActiveRecord extends CModel
$this->applyScopes($criteria); $this->applyScopes($criteria);
if(empty($criteria->with)) if(empty($criteria->with))
return $builder->createFindCommand($table,$criteria)->queryRow()!==false; return $builder->createFindCommand($table,$criteria,$this->getTableAlias(false, false))->queryRow()!==false;
else else
{ {
$criteria->select='*'; $criteria->select='*';
$finder=new CActiveFinder($this,$criteria->with); $finder=$this->getActiveFinder($criteria->with);
return $finder->count($criteria)>0; return $finder->count($criteria)>0;
} }
} }
@ -1820,7 +1877,7 @@ abstract class CActiveRecord extends CModel
* @param boolean $callAfterFind whether to call {@link afterFind} after each record is populated. * @param boolean $callAfterFind whether to call {@link afterFind} after each record is populated.
* @param string $index the name of the attribute whose value will be used as indexes of the query result array. * @param string $index the name of the attribute whose value will be used as indexes of the query result array.
* If null, it means the array will be indexed by zero-based integers. * If null, it means the array will be indexed by zero-based integers.
* @return array list of active records. * @return CActiveRecord[] list of active records.
*/ */
public function populateRecords($data,$callAfterFind=true,$index=null) public function populateRecords($data,$callAfterFind=true,$index=null)
{ {
@ -2089,6 +2146,12 @@ class CActiveRelation extends CBaseActiveRelation
* @since 1.1.9 * @since 1.1.9
*/ */
public $scopes; public $scopes;
/**
* @var string the name of the relation that should be used as the bridge to this relation.
* Defaults to null, meaning don't use any bridge.
* @since 1.1.7
*/
public $through;
/** /**
* Merges this relation with a criteria specified dynamically. * Merges this relation with a criteria specified dynamically.
@ -2155,12 +2218,6 @@ class CBelongsToRelation extends CActiveRelation
*/ */
class CHasOneRelation extends CActiveRelation class CHasOneRelation extends CActiveRelation
{ {
/**
* @var string the name of the relation that should be used as the bridge to this relation.
* Defaults to null, meaning don't use any bridge.
* @since 1.1.7
*/
public $through;
} }
@ -2185,12 +2242,6 @@ class CHasManyRelation extends CActiveRelation
* Defaults to null, meaning using zero-based integer IDs. * Defaults to null, meaning using zero-based integer IDs.
*/ */
public $index; public $index;
/**
* @var string the name of the relation that should be used as the bridge to this relation.
* Defaults to null, meaning don't use any bridge.
* @since 1.1.7
*/
public $through;
/** /**
* Merges this relation with a criteria specified dynamically. * Merges this relation with a criteria specified dynamically.
@ -2295,20 +2346,21 @@ class CActiveRecordMetaData
*/ */
public $attributeDefaults=array(); public $attributeDefaults=array();
private $_model; private $_modelClassName;
/** /**
* Constructor. * Constructor.
* @param CActiveRecord $model the model instance * @param CActiveRecord $model the model instance
* @throws CDbException if specified table for active record class cannot be found in the database
*/ */
public function __construct($model) public function __construct($model)
{ {
$this->_model=$model; $this->_modelClassName=get_class($model);
$tableName=$model->tableName(); $tableName=$model->tableName();
if(($table=$model->getDbConnection()->getSchema()->getTable($tableName))===null) if(($table=$model->getDbConnection()->getSchema()->getTable($tableName))===null)
throw new CDbException(Yii::t('yii','The table "{table}" for active record class "{class}" cannot be found in the database.', throw new CDbException(Yii::t('yii','The table "{table}" for active record class "{class}" cannot be found in the database.',
array('{class}'=>get_class($model),'{table}'=>$tableName))); array('{class}'=>$this->_modelClassName,'{table}'=>$tableName)));
if($table->primaryKey===null) if($table->primaryKey===null)
{ {
$table->primaryKey=$model->primaryKey(); $table->primaryKey=$model->primaryKey();
@ -2347,7 +2399,7 @@ class CActiveRecordMetaData
* @throws CDbException * @throws CDbException
* @param string $name $name Name of the relation. * @param string $name $name Name of the relation.
* @param array $config $config Relation parameters. * @param array $config $config Relation parameters.
* @return void * @return void
* @since 1.1.2 * @since 1.1.2
*/ */
public function addRelation($name,$config) public function addRelation($name,$config)
@ -2355,7 +2407,7 @@ class CActiveRecordMetaData
if(isset($config[0],$config[1],$config[2])) // relation class, AR class, FK if(isset($config[0],$config[1],$config[2])) // relation class, AR class, FK
$this->relations[$name]=new $config[0]($name,$config[1],$config[2],array_slice($config,3)); $this->relations[$name]=new $config[0]($name,$config[1],$config[2],array_slice($config,3));
else else
throw new CDbException(Yii::t('yii','Active record "{class}" has an invalid configuration for relation "{relation}". It must specify the relation type, the related active record class and the foreign key.', array('{class}'=>get_class($this->_model),'{relation}'=>$name))); throw new CDbException(Yii::t('yii','Active record "{class}" has an invalid configuration for relation "{relation}". It must specify the relation type, the related active record class and the foreign key.', array('{class}'=>$this->_modelClassName,'{relation}'=>$name)));
} }
/** /**

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -35,6 +35,7 @@ class CActiveRecordBehavior extends CModelBehavior
'onAfterDelete'=>'afterDelete', 'onAfterDelete'=>'afterDelete',
'onBeforeFind'=>'beforeFind', 'onBeforeFind'=>'beforeFind',
'onAfterFind'=>'afterFind', 'onAfterFind'=>'afterFind',
'onBeforeCount'=>'beforeCount',
)); ));
} }
@ -99,4 +100,15 @@ class CActiveRecordBehavior extends CModelBehavior
protected function afterFind($event) protected function afterFind($event)
{ {
} }
/**
* Responds to {@link CActiveRecord::onBeforeCount} event.
* Override this method and make it public if you want to handle the corresponding event
* of the {@link CBehavior::owner owner}.
* @param CEvent $event event parameter
* @since 1.1.14
*/
protected function beforeCount($event)
{
}
} }

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -237,7 +237,7 @@ class CDbCommandBuilder extends CComponent
foreach($pks as $pk) foreach($pks as $pk)
{ {
$fields[]=$table->getColumn($pk)->rawName; $fields[]=$table->getColumn($pk)->rawName;
$placeholders[]='NULL'; $placeholders[]=$this->getIntegerPrimaryKeyDefaultValue();
} }
} }
$sql="INSERT INTO {$table->rawName} (".implode(', ',$fields).') VALUES ('.implode(', ',$placeholders).')'; $sql="INSERT INTO {$table->rawName} (".implode(', ',$fields).') VALUES ('.implode(', ',$placeholders).')';
@ -249,11 +249,113 @@ class CDbCommandBuilder extends CComponent
return $command; return $command;
} }
/**
* Creates a multiple INSERT command.
* This method could be used to achieve better performance during insertion of the large
* amount of data into the database tables.
* @param mixed $table the table schema ({@link CDbTableSchema}) or the table name (string).
* @param array[] $data list data to be inserted, each value should be an array in format (column name=>column value).
* If a key is not a valid column name, the corresponding value will be ignored.
* @return CDbCommand multiple insert command
* @since 1.1.14
*/
public function createMultipleInsertCommand($table,array $data)
{
return $this->composeMultipleInsertCommand($table,$data);
}
/**
* Creates a multiple INSERT command.
* This method compose the SQL expression via given part templates, providing ability to adjust
* command for different SQL syntax.
* @param mixed $table the table schema ({@link CDbTableSchema}) or the table name (string).
* @param array[] $data list data to be inserted, each value should be an array in format (column name=>column value).
* If a key is not a valid column name, the corresponding value will be ignored.
* @param array $templates templates for the SQL parts.
* @return CDbCommand multiple insert command
*/
protected function composeMultipleInsertCommand($table,array $data,array $templates=array())
{
$templates=array_merge(
array(
'main'=>'INSERT INTO {{tableName}} ({{columnInsertNames}}) VALUES {{rowInsertValues}}',
'columnInsertValue'=>'{{value}}',
'columnInsertValueGlue'=>', ',
'rowInsertValue'=>'({{columnInsertValues}})',
'rowInsertValueGlue'=>', ',
'columnInsertNameGlue'=>', ',
),
$templates
);
$this->ensureTable($table);
$tableName=$this->getDbConnection()->quoteTableName($table->name);
$params=array();
$columnInsertNames=array();
$rowInsertValues=array();
$columns=array();
foreach($data as $rowData)
{
foreach($rowData as $columnName=>$columnValue)
{
if(!in_array($columnName,$columns,true))
if($table->getColumn($columnName)!==null)
$columns[]=$columnName;
}
}
foreach($columns as $name)
$columnInsertNames[$name]=$this->getDbConnection()->quoteColumnName($name);
$columnInsertNamesSqlPart=implode($templates['columnInsertNameGlue'],$columnInsertNames);
foreach($data as $rowKey=>$rowData)
{
$columnInsertValues=array();
foreach($columns as $columnName)
{
$column=$table->getColumn($columnName);
$columnValue=array_key_exists($columnName,$rowData) ? $rowData[$columnName] : new CDbExpression('NULL');
if($columnValue instanceof CDbExpression)
{
$columnInsertValue=$columnValue->expression;
foreach($columnValue->params as $columnValueParamName=>$columnValueParam)
$params[$columnValueParamName]=$columnValueParam;
}
else
{
$columnInsertValue=':'.$columnName.'_'.$rowKey;
$params[':'.$columnName.'_'.$rowKey]=$column->typecast($columnValue);
}
$columnInsertValues[]=strtr($templates['columnInsertValue'],array(
'{{column}}'=>$columnInsertNames[$columnName],
'{{value}}'=>$columnInsertValue,
));
}
$rowInsertValues[]=strtr($templates['rowInsertValue'],array(
'{{tableName}}'=>$tableName,
'{{columnInsertNames}}'=>$columnInsertNamesSqlPart,
'{{columnInsertValues}}'=>implode($templates['columnInsertValueGlue'],$columnInsertValues)
));
}
$sql=strtr($templates['main'],array(
'{{tableName}}'=>$tableName,
'{{columnInsertNames}}'=>$columnInsertNamesSqlPart,
'{{rowInsertValues}}'=>implode($templates['rowInsertValueGlue'], $rowInsertValues),
));
$command=$this->getDbConnection()->createCommand($sql);
foreach($params as $name=>$value)
$command->bindValue($name,$value);
return $command;
}
/** /**
* Creates an UPDATE command. * Creates an UPDATE command.
* @param mixed $table the table schema ({@link CDbTableSchema}) or the table name (string). * @param mixed $table the table schema ({@link CDbTableSchema}) or the table name (string).
* @param array $data list of columns to be updated (name=>value) * @param array $data list of columns to be updated (name=>value)
* @param CDbCriteria $criteria the query criteria * @param CDbCriteria $criteria the query criteria
* @throws CDbException if no columns are being updated for the given table
* @return CDbCommand update command. * @return CDbCommand update command.
*/ */
public function createUpdateCommand($table,$data,$criteria) public function createUpdateCommand($table,$data,$criteria)
@ -306,8 +408,8 @@ class CDbCommandBuilder extends CComponent
* @param mixed $table the table schema ({@link CDbTableSchema}) or the table name (string). * @param mixed $table the table schema ({@link CDbTableSchema}) or the table name (string).
* @param array $counters counters to be updated (counter increments/decrements indexed by column names.) * @param array $counters counters to be updated (counter increments/decrements indexed by column names.)
* @param CDbCriteria $criteria the query criteria * @param CDbCriteria $criteria the query criteria
* @throws CDbException if no columns are being updated for the given table
* @return CDbCommand the created command * @return CDbCommand the created command
* @throws CException if no counter is specified
*/ */
public function createUpdateCounterCommand($table,$counters,$criteria) public function createUpdateCounterCommand($table,$counters,$criteria)
{ {
@ -550,6 +652,7 @@ class CDbCommandBuilder extends CComponent
* This is only used when the third parameter is a string (query condition). * This is only used when the third parameter is a string (query condition).
* In other cases, please use {@link CDbCriteria::params} to set parameters. * In other cases, please use {@link CDbCriteria::params} to set parameters.
* @param string $prefix column prefix (ended with dot). If null, it will be the table name * @param string $prefix column prefix (ended with dot). If null, it will be the table name
* @throws CDbException if specified column is not found in given table
* @return CDbCriteria the created query criteria * @return CDbCriteria the created query criteria
*/ */
public function createColumnCriteria($table,$columns,$condition='',$params=array(),$prefix=null) public function createColumnCriteria($table,$columns,$condition='',$params=array(),$prefix=null)
@ -611,6 +714,7 @@ class CDbCommandBuilder extends CComponent
* @param mixed $keywords search keywords. This can be either a string with space-separated keywords or an array of keywords. * @param mixed $keywords search keywords. This can be either a string with space-separated keywords or an array of keywords.
* @param string $prefix optional column prefix (with dot at the end). If null, the table name will be used as the prefix. * @param string $prefix optional column prefix (with dot at the end). If null, the table name will be used as the prefix.
* @param boolean $caseSensitive whether the search is case-sensitive. Defaults to true. * @param boolean $caseSensitive whether the search is case-sensitive. Defaults to true.
* @throws CDbException if specified column is not found in given table
* @return string SQL search condition matching on a set of columns. An empty string is returned * @return string SQL search condition matching on a set of columns. An empty string is returned
* if either the column array or the keywords are empty. * if either the column array or the keywords are empty.
*/ */
@ -650,6 +754,7 @@ class CDbCommandBuilder extends CComponent
* or an array of column names. If the latter, it stands for a composite key. * or an array of column names. If the latter, it stands for a composite key.
* @param array $values list of key values to be selected within * @param array $values list of key values to be selected within
* @param string $prefix column prefix (ended with dot). If null, it will be the table name * @param string $prefix column prefix (ended with dot). If null, it will be the table name
* @throws CDbException if specified column is not found in given table
* @return string the expression for selection * @return string the expression for selection
*/ */
public function createInCondition($table,$columnName,$values,$prefix=null) public function createInCondition($table,$columnName,$values,$prefix=null)
@ -674,6 +779,7 @@ class CDbCommandBuilder extends CComponent
array('{table}'=>$table->name, '{column}'=>$columnName))); array('{table}'=>$table->name, '{column}'=>$columnName)));
$column=$table->columns[$columnName]; $column=$table->columns[$columnName];
$values=array_values($values);
foreach($values as &$value) foreach($values as &$value)
{ {
$value=$column->typecast($value); $value=$column->typecast($value);
@ -753,4 +859,15 @@ class CDbCommandBuilder extends CComponent
throw new CDbException(Yii::t('yii','Table "{table}" does not exist.', throw new CDbException(Yii::t('yii','Table "{table}" does not exist.',
array('{table}'=>$tableName))); array('{table}'=>$tableName)));
} }
}
/**
* Returns default value of the integer/serial primary key. Default value means that the next
* autoincrement/sequence value would be used.
* @return string default value of the integer/serial primary key.
* @since 1.1.14
*/
protected function getIntegerPrimaryKeyDefaultValue()
{
return 'NULL';
}
}

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -183,7 +183,7 @@ class CDbCriteria extends CComponent
} }
if (!empty($map)) if (!empty($map))
{ {
$sqlContentFieldNames = array( $sqlContentFieldNames=array(
'select', 'select',
'condition', 'condition',
'order', 'order',
@ -191,8 +191,14 @@ class CDbCriteria extends CComponent
'join', 'join',
'having', 'having',
); );
foreach($sqlContentFieldNames as $fieldName) foreach($sqlContentFieldNames as $field)
$this->$fieldName=strtr($this->$fieldName,$map); {
if(is_array($this->$field))
foreach($this->$field as $k=>$v)
$this->{$field}[$k]=strtr($v,$map);
else
$this->$field=strtr($this->$field,$map);
}
} }
$this->params=$params; $this->params=$params;
} }

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -264,10 +264,11 @@ abstract class CDbSchema extends CComponent
/** /**
* Resets the sequence value of a table's primary key. * Resets the sequence value of a table's primary key.
* The sequence will be reset such that the primary key of the next new row inserted * The sequence will be reset such that the primary key of the next new row inserted
* will have the specified value or 1. * will have the specified value or max value of a primary key plus one (i.e. sequence trimming).
* @param CDbTableSchema $table the table schema whose primary key sequence will be reset * @param CDbTableSchema $table the table schema whose primary key sequence will be reset
* @param mixed $value the value for the primary key of the next new row inserted. If this is not set, * @param integer|null $value the value for the primary key of the next new row inserted.
* the next new row's primary key will have a value 1. * If this is not set, the next new row's primary key will have the max value of a primary
* key plus one (i.e. sequence trimming).
* @since 1.1 * @since 1.1
*/ */
public function resetSequence($table,$value=null) public function resetSequence($table,$value=null)
@ -300,6 +301,7 @@ abstract class CDbSchema extends CComponent
* because the default implementation simply throws an exception. * because the default implementation simply throws an exception.
* @param string $schema the schema of the tables. Defaults to empty string, meaning the current or default schema. * @param string $schema the schema of the tables. Defaults to empty string, meaning the current or default schema.
* If not empty, the returned table names will be prefixed with the schema name. * If not empty, the returned table names will be prefixed with the schema name.
* @throws CDbException if current schema does not support fetching all table names
* @return array all table names in the database. * @return array all table names in the database.
*/ */
protected function findTableNames($schema='') protected function findTableNames($schema='')
@ -564,13 +566,15 @@ abstract class CDbSchema extends CComponent
* Builds a SQL statement for adding a primary key constraint to an existing table. * Builds a SQL statement for adding a primary key constraint to an existing table.
* @param string $name the name of the primary key constraint. * @param string $name the name of the primary key constraint.
* @param string $table the table that the primary key constraint will be added to. * @param string $table the table that the primary key constraint will be added to.
* @param string $columns the name of the column to that the constraint will be added on. * @param string|array $columns comma separated string or array of columns that the primary key will consist of.
* Array value can be passed since 1.1.14.
* @return string the SQL statement for adding a primary key constraint to an existing table. * @return string the SQL statement for adding a primary key constraint to an existing table.
* @since 1.1.13 * @since 1.1.13
*/ */
public function addPrimaryKey($name,$table,$columns) public function addPrimaryKey($name,$table,$columns)
{ {
$columns=preg_split('/\s*,\s*/',$columns,-1,PREG_SPLIT_NO_EMPTY); if(is_string($columns))
$columns=preg_split('/\s*,\s*/',$columns,-1,PREG_SPLIT_NO_EMPTY);
foreach($columns as $i=>$col) foreach($columns as $i=>$col)
$columns[$i]=$this->quoteColumnName($col); $columns[$i]=$this->quoteColumnName($col);
return 'ALTER TABLE ' . $this->quoteTableName($table) . ' ADD CONSTRAINT ' return 'ALTER TABLE ' . $this->quoteTableName($table) . ' ADD CONSTRAINT '
@ -578,7 +582,6 @@ abstract class CDbSchema extends CComponent
. implode(', ', $columns). ' )'; . implode(', ', $columns). ' )';
} }
/** /**
* Builds a SQL statement for removing a primary key constraint to an existing table. * Builds a SQL statement for removing a primary key constraint to an existing table.
* @param string $name the name of the primary key constraint to be removed. * @param string $name the name of the primary key constraint to be removed.
@ -591,7 +594,4 @@ abstract class CDbSchema extends CComponent
return 'ALTER TABLE ' . $this->quoteTableName($table) . ' DROP CONSTRAINT ' return 'ALTER TABLE ' . $this->quoteTableName($table) . ' DROP CONSTRAINT '
. $this->quoteColumnName($name); . $this->quoteColumnName($name);
} }
} }

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -5,7 +5,7 @@
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @author Christophe Boulain <Christophe.Boulain@gmail.com> * @author Christophe Boulain <Christophe.Boulain@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -19,20 +19,20 @@
class CMssqlColumnSchema extends CDbColumnSchema class CMssqlColumnSchema extends CDbColumnSchema
{ {
/** /**
* Initializes the column with its DB type and default value. * Initializes the column with its DB type and default value.
* This sets up the column's PHP type, size, precision, scale as well as default value. * This sets up the column's PHP type, size, precision, scale as well as default value.
* @param string $dbType the column's DB type * @param string $dbType the column's DB type
* @param mixed $defaultValue the default value * @param mixed $defaultValue the default value
*/ */
public function init($dbType, $defaultValue) public function init($dbType, $defaultValue)
{ {
if ($defaultValue=='(NULL)') if ($defaultValue=='(NULL)')
{ {
$defaultValue=null; $defaultValue=null;
} }
parent::init($dbType, $defaultValue); parent::init($dbType, $defaultValue);
} }
/** /**

View File

@ -6,7 +6,7 @@
* @author Christophe Boulain <Christophe.Boulain@gmail.com> * @author Christophe Boulain <Christophe.Boulain@gmail.com>
* @author Wei Zhuo <weizhuo[at]gmail[dot]com> * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -55,6 +55,7 @@ class CMssqlCommandBuilder extends CDbCommandBuilder
* @param CDbTableSchema $table the table metadata * @param CDbTableSchema $table the table metadata
* @param array $data list of columns to be updated (name=>value) * @param array $data list of columns to be updated (name=>value)
* @param CDbCriteria $criteria the query criteria * @param CDbCriteria $criteria the query criteria
* @throws CDbException if no columns are being updated
* @return CDbCommand update command. * @return CDbCommand update command.
*/ */
public function createUpdateCommand($table,$data,$criteria) public function createUpdateCommand($table,$data,$criteria)

View File

@ -4,7 +4,7 @@
* *
* @author Christophe Boulain <Christophe.Boulain@gmail.com> * @author Christophe Boulain <Christophe.Boulain@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -25,7 +25,7 @@ class CMssqlPdoAdapter extends PDO
*/ */
public function lastInsertId ($sequence=NULL) public function lastInsertId ($sequence=NULL)
{ {
return $this->query('SELECT CAST(COALESCE(SCOPE_IDENTITY(), @@IDENTITY) AS bigint)')->fetchColumn(); return $this->query('SELECT CAST(COALESCE(SCOPE_IDENTITY(), @@IDENTITY) AS bigint)')->fetchColumn();
} }
/** /**

View File

@ -5,7 +5,7 @@
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @author Christophe Boulain <Christophe.Boulain@gmail.com> * @author Christophe Boulain <Christophe.Boulain@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -24,20 +24,20 @@ class CMssqlSchema extends CDbSchema
* @var array the abstract column types mapped to physical column types. * @var array the abstract column types mapped to physical column types.
* @since 1.1.6 * @since 1.1.6
*/ */
public $columnTypes=array( public $columnTypes=array(
'pk' => 'int IDENTITY PRIMARY KEY', 'pk' => 'int IDENTITY PRIMARY KEY',
'string' => 'varchar(255)', 'string' => 'varchar(255)',
'text' => 'text', 'text' => 'text',
'integer' => 'int', 'integer' => 'int',
'float' => 'float', 'float' => 'float',
'decimal' => 'decimal', 'decimal' => 'decimal',
'datetime' => 'datetime', 'datetime' => 'datetime',
'timestamp' => 'timestamp', 'timestamp' => 'timestamp',
'time' => 'time', 'time' => 'time',
'date' => 'date', 'date' => 'date',
'binary' => 'binary', 'binary' => 'binary',
'boolean' => 'bit', 'boolean' => 'bit',
); );
/** /**
* Quotes a table name for use in a query. * Quotes a table name for use in a query.
@ -81,23 +81,27 @@ class CMssqlSchema extends CDbSchema
/** /**
* Resets the sequence value of a table's primary key. * Resets the sequence value of a table's primary key.
* The sequence will be reset such that the primary key of the next new row inserted * The sequence will be reset such that the primary key of the next new row inserted
* will have the specified value or 1. * will have the specified value or max value of a primary key plus one (i.e. sequence trimming).
* @param CDbTableSchema $table the table schema whose primary key sequence will be reset * @param CDbTableSchema $table the table schema whose primary key sequence will be reset
* @param mixed $value the value for the primary key of the next new row inserted. If this is not set, * @param integer|null $value the value for the primary key of the next new row inserted.
* the next new row's primary key will have a value 1. * If this is not set, the next new row's primary key will have the max value of a primary
* key plus one (i.e. sequence trimming).
* @since 1.1.6 * @since 1.1.6
*/ */
public function resetSequence($table,$value=null) public function resetSequence($table,$value=null)
{ {
if($table->sequenceName!==null) if($table->sequenceName===null)
{ return;
$db=$this->getDbConnection(); if($value!==null)
if($value===null) $value=(int)($value)-1;
$value=$db->createCommand("SELECT MAX(`{$table->primaryKey}`) FROM {$table->rawName}")->queryScalar(); else
$value=(int)$value; $value=(int)$this->getDbConnection()
$name=strtr($table->rawName,array('['=>'',']'=>'')); ->createCommand("SELECT MAX([{$table->primaryKey}]) FROM {$table->rawName}")
$db->createCommand("DBCC CHECKIDENT ('$name', RESEED, $value)")->execute(); ->queryScalar();
} $name=strtr($table->rawName,array('['=>'',']'=>''));
$this->getDbConnection()
->createCommand("DBCC CHECKIDENT ('$name',RESEED,$value)")
->execute();
} }
private $_normalTables=array(); // non-view tables private $_normalTables=array(); // non-view tables
@ -190,13 +194,13 @@ class CMssqlSchema extends CDbSchema
$sql = <<<EOD $sql = <<<EOD
SELECT k.column_name field_name SELECT k.column_name field_name
FROM {$this->quoteTableName($kcu)} k FROM {$this->quoteTableName($kcu)} k
LEFT JOIN {$this->quoteTableName($tc)} c LEFT JOIN {$this->quoteTableName($tc)} c
ON k.table_name = c.table_name ON k.table_name = c.table_name
AND k.constraint_name = c.constraint_name AND k.constraint_name = c.constraint_name
WHERE c.constraint_type ='PRIMARY KEY' WHERE c.constraint_type ='PRIMARY KEY'
AND k.table_name = :table AND k.table_name = :table
AND k.table_schema = :schema AND k.table_schema = :schema
EOD; EOD;
$command = $this->getDbConnection()->createCommand($sql); $command = $this->getDbConnection()->createCommand($sql);
$command->bindValue(':table', $table->name); $command->bindValue(':table', $table->name);
@ -290,8 +294,16 @@ EOD;
"LEFT OUTER JOIN sys.extended_properties AS t2 ON t1.ORDINAL_POSITION = t2.minor_id AND ". "LEFT OUTER JOIN sys.extended_properties AS t2 ON t1.ORDINAL_POSITION = t2.minor_id AND ".
"object_name(t2.major_id) = t1.TABLE_NAME AND t2.class=1 AND t2.class_desc='OBJECT_OR_COLUMN' AND t2.name='MS_Description' ". "object_name(t2.major_id) = t1.TABLE_NAME AND t2.class=1 AND t2.class_desc='OBJECT_OR_COLUMN' AND t2.name='MS_Description' ".
"WHERE ".join(' AND ',$where); "WHERE ".join(' AND ',$where);
if (($columns=$this->getDbConnection()->createCommand($sql)->queryAll())===array()) try
{
$columns=$this->getDbConnection()->createCommand($sql)->queryAll();
if(empty($columns))
return false;
}
catch(Exception $e)
{
return false; return false;
}
foreach($columns as $column) foreach($columns as $column)
{ {
@ -353,7 +365,7 @@ EOD;
else else
$condition="TABLE_TYPE='BASE TABLE'"; $condition="TABLE_TYPE='BASE TABLE'";
$sql=<<<EOD $sql=<<<EOD
SELECT TABLE_NAME, TABLE_SCHEMA FROM [INFORMATION_SCHEMA].[TABLES] SELECT TABLE_NAME FROM [INFORMATION_SCHEMA].[TABLES]
WHERE TABLE_SCHEMA=:schema AND $condition WHERE TABLE_SCHEMA=:schema AND $condition
EOD; EOD;
$command=$this->getDbConnection()->createCommand($sql); $command=$this->getDbConnection()->createCommand($sql);
@ -365,7 +377,7 @@ EOD;
if ($schema == self::DEFAULT_SCHEMA) if ($schema == self::DEFAULT_SCHEMA)
$names[]=$row['TABLE_NAME']; $names[]=$row['TABLE_NAME'];
else else
$names[]=$schema.'.'.$row['TABLE_SCHEMA'].'.'.$row['TABLE_NAME']; $names[]=$schema.'.'.$row['TABLE_NAME'];
} }
return $names; return $names;

View File

@ -4,7 +4,7 @@
* *
* @author Timur Ruziev <resurtm@gmail.com> * @author Timur Ruziev <resurtm@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2012 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -24,7 +24,7 @@ class CMssqlSqlsrvPdoAdapter extends PDO
* string it returns empty string. But when parameter is not specified at all it's working as expected * string it returns empty string. But when parameter is not specified at all it's working as expected
* and returns actual last inserted ID (like other PDO drivers). * and returns actual last inserted ID (like other PDO drivers).
* *
* @param string|null the sequence name. Defaults to null. * @param string|null $sequence the sequence name. Defaults to null.
* @return integer last inserted ID value. * @return integer last inserted ID value.
*/ */
public function lastInsertId($sequence=null) public function lastInsertId($sequence=null)

View File

@ -5,7 +5,7 @@
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @author Christophe Boulain <Christophe.Boulain@gmail.com> * @author Christophe Boulain <Christophe.Boulain@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -42,7 +42,9 @@ class CMysqlColumnSchema extends CDbColumnSchema
*/ */
protected function extractDefault($defaultValue) protected function extractDefault($defaultValue)
{ {
if($this->dbType==='timestamp' && $defaultValue==='CURRENT_TIMESTAMP') if(strncmp($this->dbType,'bit',3)===0)
$this->defaultValue=bindec(trim($defaultValue,'b\''));
elseif($this->dbType==='timestamp' && $defaultValue==='CURRENT_TIMESTAMP')
$this->defaultValue=null; $this->defaultValue=null;
else else
parent::extractDefault($defaultValue); parent::extractDefault($defaultValue);
@ -54,18 +56,19 @@ class CMysqlColumnSchema extends CDbColumnSchema
*/ */
protected function extractLimit($dbType) protected function extractLimit($dbType)
{ {
if (strncmp($dbType, 'enum', 4)===0 && preg_match('/\((.*)\)/',$dbType,$matches)) if (strncmp($dbType, 'enum', 4)===0 && preg_match('/\(([\'"])(.*)\\1\)/',$dbType,$matches))
{ {
$values = explode(',', $matches[1]); // explode by (single or double) quote and comma (ENUM values may contain commas)
$values = explode($matches[1].','.$matches[1], $matches[2]);
$size = 0; $size = 0;
foreach($values as $value) foreach($values as $value)
{ {
if(($n=strlen($value)) > $size) if(($n=strlen($value)) > $size)
$size=$n; $size=$n;
} }
$this->size = $this->precision = $size-2; $this->size = $this->precision = $size;
} }
else else
parent::extractLimit($dbType); parent::extractLimit($dbType);
} }
} }

View File

@ -4,7 +4,7 @@
* *
* @author Carsten Brandt <mail@cebe.cc> * @author Carsten Brandt <mail@cebe.cc>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -20,6 +20,7 @@ class CMysqlCommandBuilder extends CDbCommandBuilder
/** /**
* Alters the SQL to apply JOIN clause. * Alters the SQL to apply JOIN clause.
* This method handles the mysql specific syntax where JOIN has to come before SET in UPDATE statement * This method handles the mysql specific syntax where JOIN has to come before SET in UPDATE statement
* and for DELETE where JOIN has to be after FROM part.
* @param string $sql the SQL statement to be altered * @param string $sql the SQL statement to be altered
* @param string $join the JOIN clause (starting with join type, such as INNER JOIN) * @param string $join the JOIN clause (starting with join type, such as INNER JOIN)
* @return string the altered SQL statement * @return string the altered SQL statement
@ -31,7 +32,12 @@ class CMysqlCommandBuilder extends CDbCommandBuilder
if(strpos($sql,'UPDATE')===0 && ($pos=strpos($sql,'SET'))!==false) if(strpos($sql,'UPDATE')===0 && ($pos=strpos($sql,'SET'))!==false)
return substr($sql,0,$pos).$join.' '.substr($sql,$pos); return substr($sql,0,$pos).$join.' '.substr($sql,$pos);
elseif(strpos($sql,'DELETE FROM ')===0)
{
$tableName=substr($sql,12);
return "DELETE {$tableName} FROM {$tableName} ".$join;
}
else else
return $sql.' '.$join; return $sql.' '.$join;
} }
} }

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
@ -77,22 +77,29 @@ class CMysqlSchema extends CDbSchema
/** /**
* Resets the sequence value of a table's primary key. * Resets the sequence value of a table's primary key.
* The sequence will be reset such that the primary key of the next new row inserted * The sequence will be reset such that the primary key of the next new row inserted
* will have the specified value or 1. * will have the specified value or max value of a primary key plus one (i.e. sequence trimming).
* @param CDbTableSchema $table the table schema whose primary key sequence will be reset * @param CDbTableSchema $table the table schema whose primary key sequence will be reset
* @param mixed $value the value for the primary key of the next new row inserted. If this is not set, * @param integer|null $value the value for the primary key of the next new row inserted.
* the next new row's primary key will have a value 1. * If this is not set, the next new row's primary key will have the max value of a primary
* key plus one (i.e. sequence trimming).
* @since 1.1 * @since 1.1
*/ */
public function resetSequence($table,$value=null) public function resetSequence($table,$value=null)
{ {
if($table->sequenceName!==null) if($table->sequenceName===null)
return;
if($value!==null)
$value=(int)$value;
else
{ {
if($value===null) $value=(int)$this->getDbConnection()
$value=$this->getDbConnection()->createCommand("SELECT MAX(`{$table->primaryKey}`) FROM {$table->rawName}")->queryScalar()+1; ->createCommand("SELECT MAX(`{$table->primaryKey}`) FROM {$table->rawName}")
else ->queryScalar();
$value=(int)$value; $value++;
$this->getDbConnection()->createCommand("ALTER TABLE {$table->rawName} AUTO_INCREMENT=$value")->execute();
} }
$this->getDbConnection()
->createCommand("ALTER TABLE {$table->rawName} AUTO_INCREMENT=$value")
->execute();
} }
/** /**
@ -196,7 +203,8 @@ class CMysqlSchema extends CDbSchema
$c->isForeignKey=false; $c->isForeignKey=false;
$c->init($column['Type'],$column['Default']); $c->init($column['Type'],$column['Default']);
$c->autoIncrement=strpos(strtolower($column['Extra']),'auto_increment')!==false; $c->autoIncrement=strpos(strtolower($column['Extra']),'auto_increment')!==false;
$c->comment=$column['Comment']; if(isset($column['Comment']))
$c->comment=$column['Comment'];
return $c; return $c;
} }
@ -271,6 +279,7 @@ class CMysqlSchema extends CDbSchema
* @param string $table the table whose column is to be renamed. The name will be properly quoted by the method. * @param string $table the table whose column is to be renamed. The name will be properly quoted by the method.
* @param string $name the old name of the column. The name will be properly quoted by the method. * @param string $name the old name of the column. The name will be properly quoted by the method.
* @param string $newName the new name of the column. The name will be properly quoted by the method. * @param string $newName the new name of the column. The name will be properly quoted by the method.
* @throws CDbException if specified column is not found in given table
* @return string the SQL statement for renaming a DB column. * @return string the SQL statement for renaming a DB column.
* @since 1.1.6 * @since 1.1.6
*/ */
@ -331,4 +340,22 @@ class CMysqlSchema extends CDbSchema
return 'ALTER TABLE ' . $this->quoteTableName($table) . ' DROP PRIMARY KEY'; return 'ALTER TABLE ' . $this->quoteTableName($table) . ' DROP PRIMARY KEY';
} }
/**
* Builds a SQL statement for adding a primary key constraint to a table.
* @param string $name not used in the MySQL syntax, the primary key is always called PRIMARY and is reserved.
* @param string $table the table that the primary key constraint will be added to.
* @param string|array $columns comma separated string or array of columns that the primary key will consist of.
* @return string the SQL statement for adding a primary key constraint to an existing table.
* @since 1.1.14
*/
public function addPrimaryKey($name,$table,$columns)
{
if(is_string($columns))
$columns=preg_split('/\s*,\s*/',$columns,-1,PREG_SPLIT_NO_EMPTY);
foreach($columns as $i=>$col)
$columns[$i]=$this->quoteColumnName($col);
return 'ALTER TABLE ' . $this->quoteTableName($table) . ' ADD PRIMARY KEY ('
. implode(', ', $columns). ' )';
}
} }

View File

@ -4,7 +4,7 @@
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */

Some files were not shown because too many files have changed in this diff Show More