Commit 59f57a82 by Qiang Xue

Merge branch 'master' of dev.yiisoft.com:yii2

parents 6f6e739f a33d152d
Errors and Exceptions
=====================
Errors i18n
-----------
A general rule is to tranlate only errors that are shown to end users only. If
it is a regular exception, debug screen etc. then message should not be translated.
\ No newline at end of file
Yii version numbering
=====================
A.B.C
A = For Yii2 it's always 2.
B = Major version. Non-BC changes with upgrade instructions.
C = BC changes and additions.
A.B.CrcD
This is when we want to release release candidate. D is the RC number. Starts with 1 and increments till we're getting a stable release with no critical bugs and BC incompatibility reports.
\ No newline at end of file
......@@ -477,7 +477,7 @@ class YiiBase
/**
* Translates a message to the specified language.
* Starting from version 1.0.2, this method supports choice format (see {@link CChoiceFormat}),
* This method supports choice format (see {@link CChoiceFormat}),
* i.e., the message returned will be chosen from a few candidates according to the given
* number value. This feature is mainly used to solve plural format issue in case
* a message has different plural forms in some languages.
......@@ -486,16 +486,15 @@ class YiiBase
* more interpretation about message category.
* @param string $message the original message
* @param array $params parameters to be applied to the message using <code>strtr</code>.
* Starting from version 1.0.2, the first parameter can be a number without key.
* The first parameter can be a number without key.
* And in this case, the method will call {@link CChoiceFormat::format} to choose
* an appropriate message translation.
* Starting from version 1.1.6 you can pass parameter for {@link CChoiceFormat::format}
* You can pass parameter for {@link CChoiceFormat::format}
* or plural forms format without wrapping it with array.
* @param string $source which message source application component to use.
* Defaults to null, meaning using 'coreMessages' for messages belonging to
* the 'yii' category and using 'messages' for the rest messages.
* @param string $language the target language. If null (default), the {@link CApplication::getLanguage application language} will be used.
* This parameter has been available since version 1.0.3.
* @return string the translated message
* @see CMessageSource
*/
......
......@@ -8,6 +8,8 @@
* @license http://www.yiiframework.com/license/
*/
namespace yii\base;
/**
* Application is the base class for all application classes.
*
......@@ -114,7 +116,7 @@ abstract class Application extends Module
*/
public function __construct($config = null)
{
Yii::setApplication($this);
\Yii::$app = $this;
// set basePath at early as possible to avoid trouble
if (is_string($config))
......@@ -126,9 +128,9 @@ abstract class Application extends Module
}
else
$this->setBasePath('protected');
Yii::setPathOfAlias('application', $this->getBasePath());
Yii::setPathOfAlias('webroot', dirname($_SERVER['SCRIPT_FILENAME']));
Yii::setPathOfAlias('ext', $this->getBasePath() . DIRECTORY_SEPARATOR . 'extensions');
\Yii::setAlias('application', $this->getBasePath());
\Yii::setAlias('webroot', dirname($_SERVER['SCRIPT_FILENAME']));
\Yii::setAlias('ext', $this->getBasePath() . DIRECTORY_SEPARATOR . 'extensions');
$this->preinit();
......@@ -151,10 +153,10 @@ abstract class Application extends Module
*/
public function run()
{
if ($this->hasEventHandler('onBeginRequest'))
if ($this->hasEventHandlers('onBeginRequest'))
$this->onBeginRequest(new CEvent($this));
$this->processRequest();
if ($this->hasEventHandler('onEndRequest'))
if ($this->hasEventHandlers('onEndRequest'))
$this->onEndRequest(new CEvent($this));
}
......@@ -168,7 +170,7 @@ abstract class Application extends Module
*/
public function end($status = 0, $exit = true)
{
if ($this->hasEventHandler('onEndRequest'))
if ($this->hasEventHandlers('onEndRequest'))
$this->onEndRequest(new CEvent($this));
if ($exit)
exit($status);
......@@ -235,7 +237,7 @@ abstract class Application extends Module
public function setBasePath($path)
{
if (($this->_basePath = realpath($path)) === false || !is_dir($this->_basePath))
throw new CException(Yii::t('yii', 'Application base path "{path}" is not a valid directory.',
throw new \yii\base\Exception(\Yii::t('yii', 'Application base path "{path}" is not a valid directory.',
array('{path}' => $path)));
}
......@@ -262,7 +264,7 @@ abstract class Application extends Module
public function setRuntimePath($path)
{
if (($runtimePath = realpath($path)) === false || !is_dir($runtimePath) || !is_writable($runtimePath))
throw new CException(Yii::t('yii', 'Application runtime path "{path}" is not valid. Please make sure it is a directory writable by the Web server process.',
throw new \yii\base\Exception(\Yii::t('yii', 'Application runtime path "{path}" is not valid. Please make sure it is a directory writable by the Web server process.',
array('{path}' => $path)));
$this->_runtimePath = $runtimePath;
}
......@@ -273,7 +275,7 @@ abstract class Application extends Module
*/
public function getExtensionPath()
{
return Yii::getPathOfAlias('ext');
return \Yii::getPathOfAlias('ext');
}
/**
......@@ -283,9 +285,9 @@ abstract class Application extends Module
public function setExtensionPath($path)
{
if (($extensionPath = realpath($path)) === false || !is_dir($extensionPath))
throw new CException(Yii::t('yii', 'Extension path "{path}" does not exist.',
throw new \yii\base\Exception(\Yii::t('yii', 'Extension path "{path}" does not exist.',
array('{path}' => $path)));
Yii::setPathOfAlias('ext', $extensionPath);
\Yii::setAlias('ext', $extensionPath);
}
/**
......@@ -319,7 +321,6 @@ abstract class Application extends Module
* This is a simple wrapper of PHP function date_default_timezone_get().
* @return string the time zone used by this application.
* @see http://php.net/manual/en/function.date-default-timezone-get.php
* @since 1.0.9
*/
public function getTimeZone()
{
......@@ -331,7 +332,6 @@ abstract class Application extends Module
* This is a simple wrapper of PHP function date_default_timezone_set().
* @param string $value the time zone used by this application.
* @see http://php.net/manual/en/function.date-default-timezone-set.php
* @since 1.0.9
*/
public function setTimeZone($value)
{
......@@ -382,17 +382,15 @@ abstract class Application extends Module
/**
* Returns the directory that contains the locale data.
* @return string the directory that contains the locale data. It defaults to 'framework/i18n/data'.
* @since 1.1.0
*/
public function getLocaleDataPath()
{
return CLocale::$dataPath === null ? Yii::getPathOfAlias('system.i18n.data') : CLocale::$dataPath;
return CLocale::$dataPath === null ? \Yii::getPathOfAlias('system.i18n.data') : CLocale::$dataPath;
}
/**
* Sets the directory that contains the locale data.
* @param string $value the directory that contains the locale data.
* @since 1.1.0
*/
public function setLocaleDataPath($value)
{
......@@ -501,7 +499,6 @@ abstract class Application extends Module
/**
* @return CController the currently active controller. Null is returned in this base class.
* @since 1.1.8
*/
public function getController()
{
......@@ -641,7 +638,7 @@ abstract class Application extends Module
/**
* Loads the global state data from persistent storage.
* @see getStatePersister
* @throws CException if the state persister is not available
* @throws \yii\base\Exception if the state persister is not available
*/
public function loadGlobalState()
{
......@@ -688,25 +685,31 @@ abstract class Application extends Module
restore_exception_handler();
$category = 'exception.' . get_class($exception);
if ($exception instanceof CHttpException)
if ($exception instanceof \yii\web\HttpException)
$category .= '.' . $exception->statusCode;
// php <5.2 doesn't support string conversion auto-magically
$message = $exception->__toString();
if (isset($_SERVER['REQUEST_URI']))
$message .= ' REQUEST_URI=' . $_SERVER['REQUEST_URI'];
Yii::log($message, CLogger::LEVEL_ERROR, $category);
\Yii::error($message, $category);
try
{
$event = new CExceptionEvent($this, $exception);
// TODO: do we need separate exception class as it was in 1.1?
//$event = new CExceptionEvent($this, $exception);
$event = new Event($this, array('exception' => $exception));
$this->onException($event);
if (!$event->handled)
{
// try an error handler
if (($handler = $this->getErrorHandler()) !== null)
{
$handler->handle($event);
}
else
{
$this->displayException($exception);
}
}
}
catch(Exception $e)
......@@ -777,11 +780,11 @@ abstract class Application extends Module
}
if (isset($_SERVER['REQUEST_URI']))
$log .= 'REQUEST_URI=' . $_SERVER['REQUEST_URI'];
Yii::log($log, CLogger::LEVEL_ERROR, 'php');
\Yii::error($log, 'php');
try
{
Yii::import('CErrorEvent', true);
\Yii::import('CErrorEvent', true);
$event = new CErrorEvent($this, $code, $message, $file, $line);
$this->onError($event);
if (!$event->handled)
......@@ -940,9 +943,10 @@ abstract class Application extends Module
'messages' => array(
'class' => 'CPhpMessageSource',
),
'errorHandler' => array(
'class' => 'CErrorHandler',
),
// TODO: uncomment when error handler is properly implemented
// 'errorHandler' => array(
// 'class' => 'CErrorHandler',
// ),
'securityManager' => array(
'class' => 'CSecurityManager',
),
......
......@@ -47,7 +47,9 @@ class Event extends Object
/**
* Constructor.
*
* @param mixed $sender sender of the event
* @param mixed $params parameters of the event
*/
public function __construct($sender=null, $params=null)
{
......
......@@ -253,13 +253,17 @@ abstract class Module extends Component
$config = $this->_moduleConfig[$id];
if (!isset($config['enabled']) || $config['enabled'])
{
Yii::trace("Loading \"$id\" module", 'system.base.CModule');
\Yii::trace("Loading \"$id\" module", 'system.base.CModule');
$class = $config['class'];
unset($config['class'], $config['enabled']);
if ($this === Yii::app())
if ($this === \Yii::$app)
{
$module = Yii::create($class, $id, null, $config);
}
else
{
$module = Yii::create($class, $this->getId() . '/' . $id, $this, $config);
}
return $this->_modules[$id] = $module;
}
}
......@@ -269,7 +273,6 @@ abstract class Module extends Component
* Returns a value indicating whether the specified module is installed.
* @param string $id the module ID
* @return boolean whether the specified module is installed.
* @since 1.1.2
*/
public function hasModule($id)
{
......@@ -360,10 +363,9 @@ abstract class Module extends Component
$config = $this->_componentConfig[$id];
if (!isset($config['enabled']) || $config['enabled'])
{
Yii::trace("Loading \"$id\" application component", 'system.CModule');
\Yii::trace("Loading \"$id\" application component", 'system.CModule');
unset($config['enabled']);
$component = Yii::create($config);
$component->init();
$component = \Yii::create($config);
return $this->_components[$id] = $component;
}
}
......
<?php
/**
* Console Application class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2012 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\console;
/**
* \yii\console\Application represents a console application.
*
* \yii\console\Application extends {@link \yii\base\Application} by providing functionalities
* specific to console requests. In particular, it deals with console requests
* through a command-based approach:
* <ul>
* <li>A console application consists of one or several possible user commands;</li>
* <li>Each user command is implemented as a class extending {@link \yii\console\Command};</li>
* <li>User specifies which command to run on the command line;</li>
* <li>The command processes the user request with the specified parameters.</li>
* </ul>
*
* The command classes reside in the directory {@link getCommandPath commandPath}.
* The name of the class follows the pattern: &lt;command-name&gt;Command, and its
* file name is the same the class name. For example, the 'ShellCommand' class defines
* a 'shell' command and the class file name is 'ShellCommand.php'.
*
* To run the console application, enter the following on the command line:
* <pre>
* php path/to/entry_script.php <command name> [param 1] [param 2] ...
* </pre>
*
* You may use the following to see help instructions about a command:
* <pre>
* php path/to/entry_script.php help <command name>
* </pre>
*
* @property string $commandPath The directory that contains the command classes. Defaults to 'protected/commands'.
* @property CommandRunner $commandRunner The command runner.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Application extends \yii\base\Application
{
/**
* @var array mapping from command name to command configurations.
* Each command configuration can be either a string or an array.
* If the former, the string should be the file path of the command class.
* If the latter, the array must contain a 'class' element which specifies
* the command's class name or {@link \YiiBase::getPathOfAlias class path alias}.
* The rest name-value pairs in the array are used to initialize
* the corresponding command properties. For example,
* <pre>
* array(
* 'email'=>array(
* 'class'=>'path.to.Mailer',
* 'interval'=>3600,
* ),
* 'log'=>'path/to/LoggerCommand.php',
* )
* </pre>
*/
public $commandMap=array();
private $_commandPath;
/**
* @var \yii\console\CommandRunner
*/
private $_runner;
/**
* Initializes the application by creating the command runner.
*/
public function init()
{
if(!isset($_SERVER['argv']))
{
die('This script must be run from the command line.');
}
$this->_runner=$this->createCommandRunner();
$this->_runner->commands=$this->commandMap;
$this->_runner->addCommands($this->getCommandPath());
}
/**
* Processes the user request.
* This method creates a console command runner to handle the particular user command.
*/
public function processRequest()
{
$this->_runner->run($_SERVER['argv']);
}
/**
* Creates the command runner instance.
* @return CommandRunner the command runner
*/
protected function createCommandRunner()
{
return new CommandRunner();
}
/**
* Displays the captured PHP error.
* This method displays the error in console mode when there is
* no active error handler.
* @param integer $code error code
* @param string $message error message
* @param string $file error file
* @param string $line error line
*/
public function displayError($code,$message,$file,$line)
{
echo "PHP Error[$code]: $message\n";
echo " in file $file at line $line\n";
$trace=debug_backtrace();
// skip the first 4 stacks as they do not tell the error position
if(count($trace)>4)
$trace=array_slice($trace,4);
foreach($trace as $i=>$t)
{
if(!isset($t['file']))
$t['file']='unknown';
if(!isset($t['line']))
$t['line']=0;
if(!isset($t['function']))
$t['function']='unknown';
echo "#$i {$t['file']}({$t['line']}): ";
if(isset($t['object']) && is_object($t['object']))
echo get_class($t['object']).'->';
echo "{$t['function']}()\n";
}
}
/**
* Displays the uncaught PHP exception.
* This method displays the exception in console mode when there is
* no active error handler.
* @param Exception $exception the uncaught exception
*/
public function displayException($exception)
{
echo $exception;
}
/**
* @return string the directory that contains the command classes. Defaults to 'protected/commands'.
*/
public function getCommandPath()
{
$applicationCommandPath = $this->getBasePath().DIRECTORY_SEPARATOR.'commands';
if($this->_commandPath===null && file_exists($applicationCommandPath))
$this->setCommandPath($applicationCommandPath);
return $this->_commandPath;
}
/**
* @param string $value the directory that contains the command classes.
* @throws CException if the directory is invalid
*/
public function setCommandPath($value)
{
if(($this->_commandPath=realpath($value))===false || !is_dir($this->_commandPath))
throw new \yii\base\Exception(Yii::t('yii','The command path "{path}" is not a valid directory.',
array('{path}'=>$value)));
}
/**
* Returns the command runner.
* @return CConsoleCommandRunner the command runner.
*/
public function getCommandRunner()
{
return $this->_runner;
}
}
<?php
/**
* Command class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\console;
/**
* Command represents an executable console command.
*
* It works like {@link \yii\web\Controller} by parsing command line options and dispatching
* the request to a specific action with appropriate option values.
*
* Users call a console command via the following command format:
* <pre>
* yiic CommandName ActionName --Option1=Value1 --Option2=Value2 ...
* </pre>
*
* Child classes mainly needs to implement various action methods whose name must be
* prefixed with "action". The parameters to an action method are considered as options
* for that specific action. The action specified as {@link defaultAction} will be invoked
* when a user does not specify the action name in his command.
*
* 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>:
* <pre>
* class SitemapCommand {
* public function actionIndex($type) {
* ....
* }
* }
* </pre>
*
* @property string $name The command name.
* @property CommandRunner $commandRunner The command runner instance.
* @property string $help The command description. Defaults to 'Usage: php entry-script.php command-name'.
* @property array $optionHelp The command option help information. Each array element describes
* the help information for a single action.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
abstract class Command extends \yii\base\Component
{
/**
* @var string the name of the default action. Defaults to 'index'.
*/
public $defaultAction='index';
private $_name;
private $_runner;
/**
* Constructor.
* @param string $name name of the command
* @param CConsoleCommandRunner $runner the command runner
*/
public function __construct($name,$runner)
{
$this->_name=$name;
$this->_runner=$runner;
}
/**
* Initializes the command object.
* This method is invoked after a command object is created and initialized with configurations.
* You may override this method to further customize the command before it executes.
*/
public function init()
{
}
/**
* Executes the command.
* The default implementation will parse the input parameters and
* dispatch the command request to an appropriate action with the corresponding
* option values
* @param array $args command line parameters for this command.
*/
public function run($args)
{
list($action, $options, $args)=$this->resolveRequest($args);
$methodName='action'.$action;
if(!preg_match('/^\w+$/',$action) || !method_exists($this,$methodName))
$this->usageError("Unknown action: ".$action);
$method=new \ReflectionMethod($this,$methodName);
$params=array();
// named and unnamed options
foreach($method->getParameters() as $param)
{
$name=$param->getName();
if(isset($options[$name]))
{
if($param->isArray())
$params[]=is_array($options[$name]) ? $options[$name] : array($options[$name]);
else if(!is_array($options[$name]))
$params[]=$options[$name];
else
$this->usageError("Option --$name requires a scalar. Array is given.");
}
else if($name==='args')
$params[]=$args;
else if($param->isDefaultValueAvailable())
$params[]=$param->getDefaultValue();
else
$this->usageError("Missing required option --$name.");
unset($options[$name]);
}
// try global options
if(!empty($options))
{
$class=new \ReflectionClass(get_class($this));
foreach($options as $name=>$value)
{
if($class->hasProperty($name))
{
$property=$class->getProperty($name);
if($property->isPublic() && !$property->isStatic())
{
$this->$name=$value;
unset($options[$name]);
}
}
}
}
if(!empty($options))
$this->usageError("Unknown options: ".implode(', ',array_keys($options)));
if($this->beforeAction($action,$params))
{
$method->invokeArgs($this,$params);
$this->afterAction($action,$params);
}
}
/**
* This method is invoked right before an action is to be executed.
* You may override this method to do last-minute preparation for the action.
* @param string $action the action name
* @param array $params the parameters to be passed to the action method.
* @return boolean whether the action should be executed.
*/
protected function beforeAction($action,$params)
{
return true;
}
/**
* This method is invoked right after an action finishes execution.
* You may override this method to do some postprocessing for the action.
* @param string $action the action name
* @param array $params the parameters to be passed to the action method.
*/
protected function afterAction($action,$params)
{
}
/**
* Parses the command line arguments and determines which action to perform.
* @param array $args command line arguments
* @return array the action name, named options (name=>value), and unnamed options
*/
protected function resolveRequest($args)
{
$options=array(); // named parameters
$params=array(); // unnamed parameters
foreach($args as $arg)
{
if(preg_match('/^--(\w+)(=(.*))?$/',$arg,$matches)) // an option
{
$name=$matches[1];
$value=isset($matches[3]) ? $matches[3] : true;
if(isset($options[$name]))
{
if(!is_array($options[$name]))
$options[$name]=array($options[$name]);
$options[$name][]=$value;
}
else
$options[$name]=$value;
}
else if(isset($action))
$params[]=$arg;
else
$action=$arg;
}
if(!isset($action))
$action=$this->defaultAction;
return array($action,$options,$params);
}
/**
* @return string the command name.
*/
public function getName()
{
return $this->_name;
}
/**
* @return \yii\console\CommandRunner the command runner instance
*/
public function getCommandRunner()
{
return $this->_runner;
}
/**
* Provides the command description.
* This method may be overridden to return the actual command description.
* @return string the command description. Defaults to 'Usage: php entry-script.php command-name'.
*/
public function getHelp()
{
$help='Usage: '.$this->getCommandRunner()->getScriptName().' '.$this->getName();
$options=$this->getOptionHelp();
if(empty($options))
return $help;
if(count($options)===1)
return $help.' '.$options[0];
$help.=" <action>\nActions:\n";
foreach($options as $option)
$help.=' '.$option."\n";
return $help;
}
/**
* Provides the command option help information.
* The default implementation will return all available actions together with their
* corresponding option information.
* @return array the command option help information. Each array element describes
* the help information for a single action.
*/
public function getOptionHelp()
{
$options=array();
$class=new \ReflectionClass(get_class($this));
foreach($class->getMethods(\ReflectionMethod::IS_PUBLIC) as $method)
{
$name=$method->getName();
if(!strncasecmp($name,'action',6) && strlen($name)>6)
{
$name=substr($name,6);
$name[0]=strtolower($name[0]);
$help=$name;
foreach($method->getParameters() as $param)
{
$optional=$param->isDefaultValueAvailable();
$defaultValue=$optional ? $param->getDefaultValue() : null;
$name=$param->getName();
if($optional)
$help.=" [--$name=$defaultValue]";
else
$help.=" --$name=value";
}
$options[]=$help;
}
}
return $options;
}
/**
* Displays a usage error.
* This method will then terminate the execution of the current application.
* @param string $message the error message
*/
public function usageError($message)
{
echo "Error: $message\n\n".$this->getHelp()."\n";
exit(1);
}
/**
* Renders a view file.
* @param string $_viewFile_ view file path
* @param array $_data_ optional data to be extracted as local view variables
* @param boolean $_return_ whether to return the rendering result instead of displaying it
* @return mixed the rendering result if required. Null otherwise.
*/
public function renderFile($_viewFile_,$_data_=null,$_return_=false)
{
if(is_array($_data_))
extract($_data_,EXTR_PREFIX_SAME,'data');
else
$data=$_data_;
if($_return_)
{
ob_start();
ob_implicit_flush(false);
require($_viewFile_);
return ob_get_clean();
}
else
require($_viewFile_);
}
/**
* Reads input via the readline PHP extension if that's available, or fgets() if readline is not installed.
*
* @param string $message to echo out before waiting for user input
* @return mixed line read as a string, or false if input has been closed
*/
public function prompt($message)
{
if(extension_loaded('readline'))
{
$input = readline($message.' ');
readline_add_history($input);
return $input;
}
else
{
echo $message.' ';
return trim(fgets(STDIN));
}
}
/**
* Asks user to confirm by typing y or n.
*
* @param string $message to echo out before waiting for user input
* @return bool if user confirmed
*/
public function confirm($message)
{
echo $message.' [yes|no] ';
return !strncasecmp(trim(fgets(STDIN)),'y',1);
}
}
\ No newline at end of file
<?php
/**
* CConsoleCommandRunner class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\console;
/**
* CConsoleCommandRunner manages commands and executes the requested command.
*
* @property string $scriptName The entry script name.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class CommandRunner extends \yii\base\Component
{
/**
* @var array list of all available commands (command name=>command configuration).
* Each command configuration can be either a string or an array.
* If the former, the string should be the class name or
* {@link YiiBase::getPathOfAlias class path alias} of the command.
* If the latter, the array must contain a 'class' element which specifies
* the command's class name or {@link YiiBase::getPathOfAlias class path alias}.
* The rest name-value pairs in the array are used to initialize
* the corresponding command properties. For example,
* <pre>
* array(
* 'email'=>array(
* 'class'=>'path.to.Mailer',
* 'interval'=>3600,
* ),
* 'log'=>'path.to.LoggerCommand',
* )
* </pre>
*/
public $commands=array();
private $_scriptName;
/**
* Executes the requested command.
* @param array $args list of user supplied parameters (including the entry script name and the command name).
*/
public function run($args)
{
$this->_scriptName=$args[0];
array_shift($args);
if(isset($args[0]))
{
$name=$args[0];
array_shift($args);
}
else
$name='help';
if(($command=$this->createCommand($name))===null)
$command=$this->createCommand('help');
$command->init();
$command->run($args);
}
/**
* @return string the entry script name
*/
public function getScriptName()
{
return $this->_scriptName;
}
/**
* Searches for commands under the specified directory.
* @param string $path the directory containing the command class files.
* @return array list of commands (command name=>command class file)
*/
public function findCommands($path)
{
if(($dir=@opendir($path))===false)
return array();
$commands=array();
while(($name=readdir($dir))!==false)
{
$file=$path.DIRECTORY_SEPARATOR.$name;
if(!strcasecmp(substr($name,-11),'Command.php') && is_file($file))
$commands[strtolower(substr($name,0,-11))]=$file;
}
closedir($dir);
return $commands;
}
/**
* Adds commands from the specified command path.
* If a command already exists, the new one will be ignored.
* @param string $path the alias of the directory containing the command class files.
*/
public function addCommands($path)
{
if(($commands=$this->findCommands($path))!==array())
{
foreach($commands as $name=>$file)
{
if(!isset($this->commands[$name]))
$this->commands[$name]=$file;
}
}
}
/**
* @param string $name command name (case-insensitive)
* @return \yii\console\Command the command object. Null if the name is invalid.
*/
public function createCommand($name)
{
$name=strtolower($name);
if(isset($this->commands[$name]))
{
if(is_string($this->commands[$name])) // class file path or alias
{
if(strpos($this->commands[$name],'/')!==false || strpos($this->commands[$name],'\\')!==false)
{
$className=substr(basename($this->commands[$name]),0,-4);
if(!class_exists($className,false))
require_once($this->commands[$name]);
}
else // an alias
$className=\Yii::import($this->commands[$name]);
return new $className($name,$this);
}
else // an array configuration
return \Yii::create($this->commands[$name],$name,$this);
}
else if($name==='help')
return new HelpCommand('help',$this);
else
return null;
}
}
\ No newline at end of file
<?php
/**
* CHelpCommand class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\console;
/**
* CHelpCommand represents a console help command.
*
* CHelpCommand displays the available command list or the help instructions
* about a specific command.
*
* To use this command, enter the following on the command line:
* <pre>
* php path/to/entry_script.php help [command name]
* </pre>
* In the above, if the command name is not provided, it will display all
* available commands.
*
* @property string $help The command description.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class HelpCommand extends Command
{
/**
* Execute the action.
* @param array $args command line parameters specific for this command
*/
public function run($args)
{
$runner=$this->getCommandRunner();
$commands=$runner->commands;
if(isset($args[0]))
{
$name=strtolower($args[0]);
}
if(!isset($args[0]) || !isset($commands[$name]))
{
if(!empty($commands))
{
echo "Yii command runner (based on Yii v".\Yii::getVersion().")\n";
echo "Usage: ".$runner->getScriptName()." <command-name> [parameters...]\n";
echo "\nThe following commands are available:\n";
$commandNames=array_keys($commands);
sort($commandNames);
echo ' - '.implode("\n - ",$commandNames);
echo "\n\nTo see individual command help, use the following:\n";
echo " ".$runner->getScriptName()." help <command-name>\n";
}
else
{
echo "No available commands.\n";
echo "Please define them under the following directory:\n";
echo "\t".\Yii::$app->getCommandPath()."\n";
}
}
else
echo $runner->createCommand($name)->getHelp();
}
/**
* Provides the command description.
* @return string the command description.
*/
public function getHelp()
{
return parent::getHelp().' [command-name]';
}
}
\ No newline at end of file
......@@ -28,11 +28,9 @@
* applying migrations.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @version $Id: CDbMigration.php 3218 2011-05-13 00:06:44Z alexander.makarow $
* @package system.db
* @since 1.1.6
* @since 2.0
*/
abstract class CDbMigration extends CComponent
abstract class CDbMigration extends yii\base\Component
{
private $_db;
......@@ -94,7 +92,6 @@ abstract class CDbMigration extends CComponent
* Child classes may implement this method instead of {@link up} if the DB logic
* needs to be within a transaction.
* @return boolean
* @since 1.1.7
*/
public function safeUp()
{
......@@ -107,7 +104,6 @@ abstract class CDbMigration extends CComponent
* Child classes may implement this method instead of {@link up} if the DB logic
* needs to be within a transaction.
* @return boolean
* @since 1.1.7
*/
public function safeDown()
{
......@@ -146,7 +142,6 @@ abstract class CDbMigration extends CComponent
* This method executes the specified SQL statement using {@link dbConnection}.
* @param string $sql the SQL statement to be executed
* @param array $params input parameters (name=>value) for the SQL execution. See {@link CDbCommand::execute} for more details.
* @since 1.1.7
*/
public function execute($sql, $params = array())
{
......
......@@ -14,9 +14,7 @@
* that are only defined by {@link CActiveRecord}.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @version $Id: CActiveRecordBehavior.php 2799 2011-01-01 19:31:13Z qiang.xue $
* @package system.db.ar
* @since 1.0.2
* @since 2.0
*/
class CActiveRecordBehavior extends CModelBehavior
{
......@@ -80,7 +78,6 @@ class CActiveRecordBehavior extends CModelBehavior
* Responds to {@link CActiveRecord::onBeforeFind} event.
* Overrides this method if you want to handle the corresponding event of the {@link CBehavior::owner owner}.
* @param CEvent $event event parameter
* @since 1.0.9
*/
public function beforeFind($event)
{
......
......@@ -671,7 +671,6 @@ class Command extends \yii\base\Component
/**
* Sets the LIMIT part of the query.
* @param integer $limit the limit
* @param integer $offset the offset
* @return Command the command object itself
*/
public function limit($limit)
......
......@@ -235,7 +235,6 @@ class Query extends \yii\base\Object
* @param mixed $condition the new condition. It can be either a string or an array of strings.
* @param string $operator the operator to join different conditions. Defaults to 'AND'.
* @return Query the criteria object itself
* @since 1.0.9
*/
public function addCondition($condition, $operator = 'AND')
{
......@@ -269,7 +268,6 @@ class Query extends \yii\base\Object
* Defaults to 'AND'.
* @param string $like the LIKE operator. Defaults to 'LIKE'. You may also set this to be 'NOT LIKE'.
* @return Query the criteria object itself
* @since 1.0.10
*/
public function addSearchCondition($column, $keyword, $escape = true, $operator = 'AND', $like = 'LIKE')
{
......@@ -293,7 +291,6 @@ class Query extends \yii\base\Object
* @param string $operator the operator used to concatenate the new condition with the existing one.
* Defaults to 'AND'.
* @return Query the criteria object itself
* @since 1.0.10
*/
public function addInCondition($column, $values, $operator = 'AND')
{
......@@ -331,7 +328,6 @@ class Query extends \yii\base\Object
* @param string $operator the operator used to concatenate the new condition with the existing one.
* Defaults to 'AND'.
* @return Query the criteria object itself
* @since 1.1.1
*/
public function addNotInCondition($column, $values, $operator = 'AND')
{
......@@ -368,7 +364,6 @@ class Query extends \yii\base\Object
* @param string $operator the operator used to concatenate the new condition with the existing one.
* Defaults to 'AND'.
* @return Query the criteria object itself
* @since 1.0.10
*/
public function addColumnCondition($columns, $columnOperator = 'AND', $operator = 'AND')
{
......@@ -428,7 +423,6 @@ class Query extends \yii\base\Object
* character on both ends. When this parameter is false, the value will be directly used for
* matching without any change.
* @return Query the criteria object itself
* @since 1.1.1
*/
public function compare($column, $value, $partialMatch = false, $operator = 'AND', $escape = true)
{
......@@ -482,7 +476,6 @@ class Query extends \yii\base\Object
* @param string $operator the operator used to concatenate the new condition with the existing one.
* Defaults to 'AND'.
* @return Query the criteria object itself
* @since 1.1.2
*/
public function addBetweenCondition($column, $valueStart, $valueEnd, $operator = 'AND')
{
......
......@@ -110,7 +110,6 @@ class QueryBuilder extends \yii\base\Object
* refer to {@link where} on how to specify conditions.
* @param array $params the parameters to be bound to the query.
* @return integer number of rows affected by the execution.
* @since 1.1.6
*/
public function update($table, $columns, $conditions = '', &$params = array())
{
......@@ -144,7 +143,6 @@ class QueryBuilder extends \yii\base\Object
* refer to {@link where} on how to specify conditions.
* @param array $params the parameters to be bound to the query.
* @return integer number of rows affected by the execution.
* @since 1.1.6
*/
public function delete($table, $conditions = '')
{
......@@ -224,7 +222,6 @@ class QueryBuilder extends \yii\base\Object
* into the physical one. Anything that is not recognized as abstract type will be kept in the generated SQL.
* For example, 'string' will be turned into 'varchar(255)', while 'string not null' will become 'varchar(255) not null'.
* @return string the SQL statement for adding a new column.
* @since 1.1.6
*/
public function addColumn($table, $column, $type)
{
......@@ -238,7 +235,6 @@ class QueryBuilder extends \yii\base\Object
* @param string $table the table whose column is to be dropped. The name will be properly quoted by the method.
* @param string $column the name of the column to be dropped. The name will be properly quoted by the method.
* @return string the SQL statement for dropping a DB column.
* @since 1.1.6
*/
public function dropColumn($table, $column)
{
......@@ -252,7 +248,6 @@ class QueryBuilder extends \yii\base\Object
* @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.
* @return string the SQL statement for renaming a DB column.
* @since 1.1.6
*/
public function renameColumn($table, $name, $newName)
{
......
......@@ -35,7 +35,7 @@ abstract class Schema extends \yii\base\Object
/**
* Constructor.
* @param CDbConnection $conn database connection.
* @param CDbConnection $connection database connection.
*/
public function __construct($connection)
{
......
......@@ -45,7 +45,6 @@ class QueryBuilder extends \yii\db\dao\QueryBuilder
* @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.
* @return string the SQL statement for renaming a DB column.
* @since 1.1.6
*/
public function renameColumn($table, $name, $newName)
{
......@@ -77,7 +76,6 @@ class QueryBuilder extends \yii\db\dao\QueryBuilder
* @param string $name the name of the foreign key constraint to be dropped. The name will be properly quoted by the method.
* @param string $table the table whose foreign is to be dropped. The name will be properly quoted by the method.
* @return string the SQL statement for dropping a foreign key constraint.
* @since 1.1.6
*/
public function dropForeignKey($name, $table)
{
......
......@@ -21,9 +21,7 @@
* </ul>
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @version $Id: CProfileLogRoute.php 3204 2011-05-05 21:36:32Z alexander.makarow $
* @package system.logging
* @since 1.0
* @since 2.0
*/
class CProfileLogRoute extends CWebLogRoute
{
......@@ -32,7 +30,6 @@ class CProfileLogRoute extends CWebLogRoute
* If false, the results will be aggregated by categories.
* Defaults to true. Note that this property only affects the summary report
* that is enabled when {@link report} is 'summary'.
* @since 1.0.6
*/
public $groupByToken = true;
/**
......
......@@ -15,9 +15,7 @@
* or in FireBug console window (if {@link showInFireBug} is set true).
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @version $Id: CWebLogRoute.php 3001 2011-02-24 16:42:44Z alexander.makarow $
* @package system.logging
* @since 1.0
* @since 2.0
*/
class CWebLogRoute extends CLogRoute
{
......@@ -32,7 +30,7 @@ class CWebLogRoute extends CLogRoute
* For example if the ajax call expects a json type result any output from the logger will cause ajax call to fail.
*/
public $ignoreAjaxInFireBug = true;
/**
* Displays the log messages.
* @param array $logs list of log messages
......
<?php
/**
* Filesystem helper class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @author Alex Makarov <sam@rmcreative.ru>
* @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2012 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\util;
/**
* Filesystem helper
*
* @since 2.0
*/
class File
{
/**
* Copies a list of files from one place to another.
* @param array $fileList the list of files to be copied (name=>spec).
* The array keys are names displayed during the copy process, and array values are specifications
* for files to be copied. Each array value must be an array of the following structure:
* <ul>
* <li>source: required, the full path of the file/directory to be copied from</li>
* <li>target: required, the full path of the file/directory to be copied to</li>
* <li>callback: optional, the callback to be invoked when copying a file. The callback function
* should be declared as follows:
* <pre>
* function foo($source,$params)
* </pre>
* where $source parameter is the source file path, and the content returned
* by the function will be saved into the target file.</li>
* <li>params: optional, the parameters to be passed to the callback</li>
* </ul>
* @see buildFileList
*/
public function copyFiles($fileList)
{
$overwriteAll=false;
foreach($fileList as $name=>$file)
{
$source=strtr($file['source'],'/\\',DIRECTORY_SEPARATOR);
$target=strtr($file['target'],'/\\',DIRECTORY_SEPARATOR);
$callback=isset($file['callback']) ? $file['callback'] : null;
$params=isset($file['params']) ? $file['params'] : null;
if(is_dir($source))
{
$this->ensureDirectory($target);
continue;
}
if($callback!==null)
$content=call_user_func($callback,$source,$params);
else
$content=file_get_contents($source);
if(is_file($target))
{
if($content===file_get_contents($target))
{
echo " unchanged $name\n";
continue;
}
if($overwriteAll)
echo " overwrite $name\n";
else
{
echo " exist $name\n";
echo " ...overwrite? [Yes|No|All|Quit] ";
$answer=trim(fgets(STDIN));
if(!strncasecmp($answer,'q',1))
return;
else if(!strncasecmp($answer,'y',1))
echo " overwrite $name\n";
else if(!strncasecmp($answer,'a',1))
{
echo " overwrite $name\n";
$overwriteAll=true;
}
else
{
echo " skip $name\n";
continue;
}
}
}
else
{
$this->ensureDirectory(dirname($target));
echo " generate $name\n";
}
file_put_contents($target,$content);
}
}
/**
* Builds the file list of a directory.
* This method traverses through the specified directory and builds
* a list of files and subdirectories that the directory contains.
* The result of this function can be passed to {@link copyFiles}.
* @param string $sourceDir the source directory
* @param string $targetDir the target directory
* @param string $baseDir base directory
* @return array the file list (see {@link copyFiles})
*/
public function buildFileList($sourceDir, $targetDir, $baseDir='')
{
$list=array();
$handle=opendir($sourceDir);
while(($file=readdir($handle))!==false)
{
if($file==='.' || $file==='..' || $file==='.svn' ||$file==='.yii')
continue;
$sourcePath=$sourceDir.DIRECTORY_SEPARATOR.$file;
$targetPath=$targetDir.DIRECTORY_SEPARATOR.$file;
$name=$baseDir===''?$file : $baseDir.'/'.$file;
$list[$name]=array('source'=>$sourcePath, 'target'=>$targetPath);
if(is_dir($sourcePath))
$list=array_merge($list,$this->buildFileList($sourcePath,$targetPath,$name));
}
closedir($handle);
return $list;
}
/**
* Creates all parent directories if they do not exist.
* @param string $directory the directory to be checked
*/
public function ensureDirectory($directory)
{
if(!is_dir($directory))
{
$this->ensureDirectory(dirname($directory));
echo " mkdir ".strtr($directory,'\\','/')."\n";
mkdir($directory);
}
}
}
<?php
/**
* Text helper class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @author Alex Makarov <sam@rmcreative.ru>
* @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2012 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\util;
/**
* Text helper
*
* @since 2.0
*/
class Text
{
/**
* Converts a word to its plural form.
* @param string $name the word to be pluralized
* @return string the pluralized word
*/
public function pluralize($name)
{
$rules=array(
'/(x|ch|ss|sh|us|as|is|os)$/i' => '\1es',
'/(?:([^f])fe|([lr])f)$/i' => '\1\2ves',
'/(m)an$/i' => '\1en',
'/(child)$/i' => '\1ren',
'/(r)y$/i' => '\1ies',
'/s$/' => 's',
);
foreach($rules as $rule=>$replacement)
{
if(preg_match($rule,$name))
return preg_replace($rule,$replacement,$name);
}
return $name.'s';
}
}
......@@ -16,9 +16,7 @@ namespace yii\validators;
* must be in. If the given date value doesn't follow the format, the attribute is considered as invalid.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @version $Id: CDateValidator.php 2799 2011-01-01 19:31:13Z qiang.xue $
* @package system.validators
* @since 1.1.7
* @since 2.0
*/
class CDateValidator extends Validator
{
......
......@@ -16,9 +16,7 @@ namespace yii\validators;
* that can be found in the foreign table.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @version $Id: CExistValidator.php 2799 2011-01-01 19:31:13Z qiang.xue $
* @package system.validators
* @since 1.0.4
* @since 2.0
*/
class CExistValidator extends Validator
{
......@@ -41,7 +39,6 @@ class CExistValidator extends Validator
* @var array additional query criteria. This will be combined with the condition
* that checks if the attribute value exists in the corresponding table column.
* This array will be used to instantiate a {@link CDbCriteria} object.
* @since 1.0.8
*/
public $criteria = array();
/**
......
......@@ -40,9 +40,7 @@ namespace yii\validators;
* You can use {@link CFileValidator} to validate the file attribute.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @version $Id: CFileValidator.php 2799 2011-01-01 19:31:13Z qiang.xue $
* @package system.validators
* @since 1.0
* @since 2.0
*/
class CFileValidator extends Validator
{
......
......@@ -13,8 +13,6 @@ namespace yii\validators;
* CUniqueValidator validates that the attribute value is unique in the corresponding database table.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @version $Id: CUniqueValidator.php 3260 2011-06-13 20:56:54Z alexander.makarow $
* @package system.validators
* @since 1.0
*/
class CUniqueValidator extends Validator
......@@ -35,7 +33,6 @@ class CUniqueValidator extends Validator
* the class of the object currently being validated.
* You may use path alias to reference a class name here.
* @see attributeName
* @since 1.0.8
*/
public $className;
/**
......@@ -43,14 +40,12 @@ class CUniqueValidator extends Validator
* used to look for the attribute value being validated. Defaults to null,
* meaning using the name of the attribute being validated.
* @see className
* @since 1.0.8
*/
public $attributeName;
/**
* @var array additional query criteria. This will be combined with the condition
* that checks if the attribute value exists in the corresponding table column.
* This array will be used to instantiate a {@link CDbCriteria} object.
* @since 1.0.8
*/
public $criteria = array();
/**
......@@ -61,7 +56,6 @@ class CUniqueValidator extends Validator
/**
* @var boolean whether this validation rule should be skipped if when there is already a validation
* error for the current attribute. Defaults to true.
* @since 1.1.1
*/
public $skipOnError = true;
......
<?php
/**
* HttpException class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2012 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\web;
/**
* CHttpException represents an exception caused by invalid operations of end-users.
*
* The HTTP error code can be obtained via {@link statusCode}.
* Error handlers may use this status code to decide how to format the error page.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class HttpException extends \yii\base\Exception
{
/**
* @var integer HTTP status code, such as 403, 404, 500, etc.
*/
public $statusCode;
/**
* Constructor.
* @param integer $status HTTP status code, such as 404, 500, etc.
* @param string $message error message
* @param integer $code error code
*/
public function __construct($status,$message=null,$code=0)
{
$this->statusCode=$status;
parent::__construct($message,$code);
}
}
#!/usr/bin/env php
<?php
/**
* Yii command line script for Unix/Linux.
*
* This is the bootstrap script for running yiic on Unix/Linux.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2012 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
require_once(__DIR__.'/yiic.php');
@echo off
rem -------------------------------------------------------------
rem Yii command line script for Windows.
rem
rem This is the bootstrap script for running yiic on Windows.
rem
rem @author Qiang Xue <qiang.xue@gmail.com>
rem @link http://www.yiiframework.com/
rem @copyright Copyright &copy; 2012 Yii Software LLC
rem @license http://www.yiiframework.com/license/
rem -------------------------------------------------------------
@setlocal
set YII_PATH=%~dp0
if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe
"%PHP_COMMAND%" "%YII_PATH%yiic" %*
@endlocal
\ No newline at end of file
<?php
/**
* Yii console bootstrap file.
*
* @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2012 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
// fcgi doesn't have STDIN defined by default
defined('STDIN') or define('STDIN', fopen('php://stdin', 'r'));
require(__DIR__.'/yii.php');
if(isset($config))
{
$app=new \yii\console\Application($config);
$app->commandRunner->addCommands(YII_PATH.'/cli/commands');
$env=@getenv('YII_CONSOLE_COMMANDS');
if(!empty($env))
$app->commandRunner->addCommands($env);
}
else
{
$app=new \yii\console\Application(array(
'basePath'=>__DIR__.'/cli',
));
}
$app->run();
\ No newline at end of file
......@@ -58,4 +58,6 @@
- assets
* ability to manage scripts order (store these in a vector?)
* http://ryanbigg.com/guides/asset_pipeline.html, http://guides.rubyonrails.org/asset_pipeline.html, use content hash instead of mtime + directory hash.
- Requirement checker
\ No newline at end of file
- Requirement checker
- widgets
* if we're going to supply default ones, these should generate really unique IDs. This will solve a lot of AJAX-nesting problems.
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment