From 951520accac21ee2bba11cd8ffabd53b57951c96 Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Fri, 13 Apr 2012 20:18:37 -0400 Subject: [PATCH 1/2] improved autoloading. --- framework/YiiBase.php | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/framework/YiiBase.php b/framework/YiiBase.php index c7c8c05..ce196bd 100644 --- a/framework/YiiBase.php +++ b/framework/YiiBase.php @@ -117,8 +117,9 @@ class YiiBase * To import a class or a directory, one can use either path alias or class name (can be namespaced): * * - `@app/components/GoogleMap`: importing the `GoogleMap` class with a path alias; - * - `GoogleMap`: importing the `GoogleMap` class with a class name; - * - `@app/components/*`: importing the whole `components` directory with a path alias. + * - `@app/components/*`: importing the whole `components` directory with a path alias; + * - `GoogleMap`: importing the `GoogleMap` class with a class name. [[autoload()]] will be used + * when this class is used for the first time. * * @param string $alias path alias or a simple class name to be imported * @param boolean $forceInclude whether to include the class file immediately. If false, the class file @@ -160,7 +161,7 @@ class YiiBase require($path . "/$className.php"); self::$_imported[$alias] = $className; } else { - self::$classMap[$className] = $path . "/$className.php"; + self::$classMap[$className] = $path . DIRECTORY_SEPARATOR . "$className.php"; } return $className; } else { @@ -257,33 +258,39 @@ class YiiBase return true; } - // namespaced class, e.g. yii\base\Component if (strpos($className, '\\') !== false) { + // namespaced class, e.g. yii\base\Component // convert namespace to path alias, e.g. yii\base\Component to @yii/base/Component $alias = '@' . str_replace('\\', '/', ltrim($className, '\\')); if (($path = static::getAlias($alias)) !== false) { - include($path . '.php'); - return true; + $classFile = $path . '.php'; } - return false; - } - - // PEAR-styled class, e.g. PHPUnit_Framework_TestCase - if (($pos = strpos($className, '_')) !== false) { + } elseif (($pos = strpos($className, '_')) !== false) { + // PEAR-styled class, e.g. PHPUnit_Framework_TestCase // convert class name to path alias, e.g. PHPUnit_Framework_TestCase to @PHPUnit/Framework/TestCase $alias = '@' . str_replace('_', '/', $className); if (($path = static::getAlias($alias)) !== false) { - include($path . '.php'); - return true; + $classFile = $path . '.php'; } } - // search in include paths - foreach (self::$classPath as $path) { - $classFile = $path . DIRECTORY_SEPARATOR . $className . '.php'; - if (is_file($classFile)) { + if (!isset($classFile)) { + // search in include paths + foreach (self::$classPath as $path) { + $path .= DIRECTORY_SEPARATOR . $className . '.php'; + if (is_file($path)) { + $classFile = $path; + $alias = $className; + } + } + } + + if (isset($classFile, $alias)) { + if (!YII_DEBUG || basename(realpath($classFile)) === basename($alias) . '.php') { include($classFile); return true; + } else { + throw new \yii\base\Exception("Class name '$className' does not match the class file '" . realpath($classFile) . "'. Have you checked their case sensitivity?"); } } From cf6d2699540f8148c197d0d97a1819216b451d33 Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Sat, 14 Apr 2012 23:05:02 -0400 Subject: [PATCH 2/2] ... --- framework/base/Model.php | 4 +- framework/base/View.php | 59 +++++++++++++++-- framework/db/ar/ActiveRecord.php | 6 +- framework/util/File.php | 139 --------------------------------------- framework/util/FileHelper.php | 70 ++++++++++++++++++++ framework/util/StringHelper.php | 86 ++++++++++++++++++++++++ framework/util/Text.php | 86 ------------------------ 7 files changed, 216 insertions(+), 234 deletions(-) delete mode 100644 framework/util/File.php create mode 100644 framework/util/FileHelper.php create mode 100644 framework/util/StringHelper.php delete mode 100644 framework/util/Text.php diff --git a/framework/base/Model.php b/framework/base/Model.php index e15125d..4a3ba3b 100644 --- a/framework/base/Model.php +++ b/framework/base/Model.php @@ -9,7 +9,7 @@ namespace yii\base; -use yii\util\Text; +use yii\util\StringHelper; /** * Model is the base class for data models. @@ -443,7 +443,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess */ public function generateAttributeLabel($name) { - return Text::camel2words($name, true); + return StringHelper::camel2words($name, true); } /** diff --git a/framework/base/View.php b/framework/base/View.php index 8ee2017..001e0e1 100644 --- a/framework/base/View.php +++ b/framework/base/View.php @@ -9,19 +9,70 @@ namespace yii\base; +use yii\util\FileHelper; + /** * @author Qiang Xue * @since 2.0 */ class View extends Component { - public function render($context, $_file_, $_data_ = array()) + public $file; + public $name; + /** + * @var string|array + */ + public $basePath; + public $owner; + public $locale; + + public function render($_params_ = array()) { - // we use special variable names here to avoid conflict with extracted variables - extract($_data_, EXTR_PREFIX_SAME, 'data'); + $this->resolveViewFile(); + extract($_params_, EXTR_OVERWRITE); ob_start(); ob_implicit_flush(false); - require($_file_); + require($this->file); return ob_get_clean(); } + + public function resolveViewFile() + { + if ($this->file !== null) { + return $this->file; + } + if ($this->name === null || $this->basePath) { + + } + + if(empty($viewName)) + return false; + + if($moduleViewPath===null) + $moduleViewPath=$basePath; + + if(($renderer=Yii::app()->getViewRenderer())!==null) + $extension=$renderer->fileExtension; + else + $extension='.php'; + if($viewName[0]==='/') + { + if(strncmp($viewName,'//',2)===0) + $viewFile=$basePath.$viewName; + else + $viewFile=$moduleViewPath.$viewName; + } + else if(strpos($viewName,'.')) + $viewFile=Yii::getPathOfAlias($viewName); + else + $viewFile=$viewPath.DIRECTORY_SEPARATOR.$viewName; + + if(is_file($viewFile.$extension)) + return Yii::app()->findLocalizedFile($viewFile.$extension); + else if($extension!=='.php' && is_file($viewFile.'.php')) + return Yii::app()->findLocalizedFile($viewFile.'.php'); + else + return false; + + } } \ No newline at end of file diff --git a/framework/db/ar/ActiveRecord.php b/framework/db/ar/ActiveRecord.php index b548bf1..35fd221 100644 --- a/framework/db/ar/ActiveRecord.php +++ b/framework/db/ar/ActiveRecord.php @@ -18,7 +18,7 @@ use yii\db\dao\Connection; use yii\db\dao\TableSchema; use yii\db\dao\Query; use yii\db\dao\Expression; -use yii\util\Text; +use yii\util\StringHelper; /** * ActiveRecord is the base class for classes representing relational data. @@ -247,14 +247,14 @@ abstract class ActiveRecord extends Model /** * Declares the name of the database table associated with this AR class. - * By default this method returns the class name as the table name by calling [[Text::camel2id()]]. + * By default this method returns the class name as the table name by calling [[StringHelper::camel2id()]]. * For example, 'Customer' becomes 'customer', and 'OrderDetail' becomes 'order_detail'. * You may override this method if the table is not named after this convention. * @return string the table name */ public static function tableName() { - return Text::camel2id(basename(get_called_class()), '_'); + return StringHelper::camel2id(basename(get_called_class()), '_'); } /** diff --git a/framework/util/File.php b/framework/util/File.php deleted file mode 100644 index 46d1941..0000000 --- a/framework/util/File.php +++ /dev/null @@ -1,139 +0,0 @@ - - * @author Alex Makarov - * @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: - *
    - *
  • source: required, the full path of the file/directory to be copied from
  • - *
  • target: required, the full path of the file/directory to be copied to
  • - *
  • callback: optional, the callback to be invoked when copying a file. The callback function - * should be declared as follows: - *
    -	 *   function foo($source,$params)
    -	 *   
    - * where $source parameter is the source file path, and the content returned - * by the function will be saved into the target file.
  • - *
  • params: optional, the parameters to be passed to the callback
  • - *
- * @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); - } - } -} diff --git a/framework/util/FileHelper.php b/framework/util/FileHelper.php new file mode 100644 index 0000000..93186d4 --- /dev/null +++ b/framework/util/FileHelper.php @@ -0,0 +1,70 @@ + + * @author Alex Makarov + * @since 2.0 + */ +class FileHelper +{ + /** + * Returns the extension name of a file path. + * For example, the path "path/to/something.php" would return "php". + * @param string $path the file path + * @return string the extension name without the dot character. + */ + public static function getExtension($path) + { + return pathinfo($path, PATHINFO_EXTENSION); + } + + /** + * Returns the localized version of a specified file. + * + * The searching is based on the specified language code. In particular, + * a file with the same name will be looked for under the subdirectory + * whose name is same as the language code. For example, given the file "path/to/view.php" + * and language code "zh_cn", the localized file will be looked for as + * "path/to/zh_cn/view.php". If the file is not found, the original file + * will be returned. + * + * If the target and the source language codes are the same, + * the original file will be returned. + * + * For consistency, it is recommended that the language code is given + * in lower case and in the format of LanguageID_RegionID (e.g. "en_us"). + * + * @param string $file the original file + * @param string $targetLanguage the target language that the file should be localized to. + * If not set, the value of [[\yii\base\Application::language]] will be used. + * @param string $sourceLanguage the language that the original file is in. + * If not set, the value of [[\yii\base\Application::sourceLanguage]] will be used. + * @return string the matching localized file, or the original file if the localized version is not found. + * If the target and the source language codes are the same, the original file will be returned. + */ + public static function localize($file, $targetLanguage = null, $sourceLanguage = null) + { + if ($targetLanguage === null) { + $targetLanguage = \Yii::$application->getLanguage(); + } + if ($sourceLanguage === null) { + $sourceLanguage = \Yii::$application->sourceLanguage; + } + if ($targetLanguage === $sourceLanguage) { + return $file; + } + $desiredFile = dirname($file) . DIRECTORY_SEPARATOR . $sourceLanguage . DIRECTORY_SEPARATOR . basename($file); + return is_file($desiredFile) ? $desiredFile : $file; + } +} diff --git a/framework/util/StringHelper.php b/framework/util/StringHelper.php new file mode 100644 index 0000000..caf0c61 --- /dev/null +++ b/framework/util/StringHelper.php @@ -0,0 +1,86 @@ + + * @author Alex Makarov + * @since 2.0 + */ +class StringHelper +{ + /** + * Converts a word to its plural form. + * Note that this is for English only! + * For example, 'apple' will become 'apples', and 'child' will become 'children'. + * @param string $name the word to be pluralized + * @return string the pluralized word + */ + public static function pluralize($name) + { + $rules = array( + '/move$/i' => 'moves', + '/foot$/i' => 'feet', + '/child$/i' => 'children', + '/human$/i' => 'humans', + '/man$/i' => 'men', + '/tooth$/i' => 'teeth', + '/person$/i' => 'people', + '/([m|l])ouse$/i' => '\1ice', + '/(x|ch|ss|sh|us|as|is|os)$/i' => '\1es', + '/([^aeiouy]|qu)y$/i' => '\1ies', + '/(?:([^f])fe|([lr])f)$/i' => '\1\2ves', + '/(shea|lea|loa|thie)f$/i' => '\1ves', + '/([ti])um$/i' => '\1a', + '/(tomat|potat|ech|her|vet)o$/i' => '\1oes', + '/(bu)s$/i' => '\1ses', + '/(ax|test)is$/i' => '\1es', + '/s$/' => 's', + ); + foreach ($rules as $rule => $replacement) { + if (preg_match($rule, $name)) { + return preg_replace($rule, $replacement, $name); + } + } + return $name . 's'; + } + + /** + * Converts a CamelCase name into space-separated words. + * For example, 'PostTag' will be converted to 'Post Tag'. + * @param string $name the string to be converted + * @param boolean $ucwords whether to capitalize the first letter in each word + * @return string the resulting words + */ + public static function camel2words($name, $ucwords = true) + { + $label = trim(strtolower(str_replace(array('-', '_', '.'), ' ', preg_replace('/(? - * @author Alex Makarov - * @since 2.0 - */ -class Text -{ - /** - * Converts a word to its plural form. - * Note that this is for English only! - * For example, 'apple' will become 'apples', and 'child' will become 'children'. - * @param string $name the word to be pluralized - * @return string the pluralized word - */ - public static function pluralize($name) - { - $rules = array( - '/move$/i' => 'moves', - '/foot$/i' => 'feet', - '/child$/i' => 'children', - '/human$/i' => 'humans', - '/man$/i' => 'men', - '/tooth$/i' => 'teeth', - '/person$/i' => 'people', - '/([m|l])ouse$/i' => '\1ice', - '/(x|ch|ss|sh|us|as|is|os)$/i' => '\1es', - '/([^aeiouy]|qu)y$/i' => '\1ies', - '/(?:([^f])fe|([lr])f)$/i' => '\1\2ves', - '/(shea|lea|loa|thie)f$/i' => '\1ves', - '/([ti])um$/i' => '\1a', - '/(tomat|potat|ech|her|vet)o$/i' => '\1oes', - '/(bu)s$/i' => '\1ses', - '/(ax|test)is$/i' => '\1es', - '/s$/' => 's', - ); - foreach ($rules as $rule => $replacement) { - if (preg_match($rule, $name)) { - return preg_replace($rule, $replacement, $name); - } - } - return $name . 's'; - } - - /** - * Converts a CamelCase name into space-separated words. - * For example, 'PostTag' will be converted to 'Post Tag'. - * @param string $name the string to be converted - * @param boolean $ucwords whether to capitalize the first letter in each word - * @return string the resulting words - */ - public static function camel2words($name, $ucwords = true) - { - $label = trim(strtolower(str_replace(array('-', '_', '.'), ' ', preg_replace('/(?