diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 37bc6d3..a0f20c4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,22 +1,18 @@ -before_script: - # set stack isolation - - export ISOLATION=buildpipeline${CI_PIPELINE_ID}${CI_BUILD_NAME} - - export COMPOSE_PROJECT_NAME=${ISOLATION} - - export TUPLE_C=$(expr ${CI_BUILD_ID} % 99) - - echo ${TUPLE_C} - # run docker-compose commands from tests environment - - cd tests - - cp .env-dist .env - - docker-compose config +image: docker:latest + +services: + - docker:dind -after_script: - - export ISOLATION=buildpipeline${CI_PIPELINE_ID}${CI_BUILD_NAME} - - export COMPOSE_PROJECT_NAME=${ISOLATION} - # run docker-compose commands from tests environment +variables: + DOCKER_YII2_PHP_IMAGE: yiisoftware/yii2-php:7.1-apache + DOCKER_MYSQL_IMAGE: percona:5.7 + DOCKER_POSTGRES_IMAGE: postgres:9.3 + +before_script: + - apk add --no-cache python py2-pip git + - pip install --no-cache-dir docker-compose==1.16.0 + - docker info - cd tests - - cp .env-dist .env - - docker-compose down -v --remove-orphans - - docker ps -f name=${ISOLATION} stages: - travis diff --git a/.travis.yml b/.travis.yml index 679f8f3..c53afe7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,9 +46,14 @@ cache: - $HOME/.composer/cache - $HOME/.npm -# try running against postgres 9.3 +# try running against postgres 9.6 addons: - postgresql: "9.3" + postgresql: "9.6" + apt: + sources: + - mysql-5.7-trusty + packages: + - mysql-server code_climate: repo_token: 2935307212620b0e2228ab67eadd92c9f5501ddb60549d0d86007a354d56915b @@ -76,10 +81,10 @@ matrix: code_climate: repo_token: 2935307212620b0e2228ab67eadd92c9f5501ddb60549d0d86007a354d56915b apt: + sources: + - mysql-5.7-trusty packages: - - mysql-server-5.6 - - mysql-client-core-5.6 - - mysql-client-5.6 + - mysql-server services: - mysql @@ -89,12 +94,12 @@ matrix: addons: code_climate: repo_token: 2935307212620b0e2228ab67eadd92c9f5501ddb60549d0d86007a354d56915b - postgresql: "9.3" + postgresql: "9.6" apt: + sources: + - mysql-5.7-trusty packages: - - mysql-server-5.6 - - mysql-client-core-5.6 - - mysql-client-5.6 + - mysql-server services: - mysql - postgresql @@ -166,6 +171,7 @@ before_script: - | if [ $TASK_TESTS_PHP == 1 ]; then travis_retry mysql -e 'CREATE DATABASE `yiitest`;'; + mysql -e "SET GLOBAL sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';"; mysql -e "CREATE USER 'travis'@'localhost' IDENTIFIED WITH mysql_native_password;"; mysql -e "GRANT ALL PRIVILEGES ON *.* TO 'travis'@'localhost' WITH GRANT OPTION;"; psql -U postgres -c 'CREATE DATABASE yiitest;'; diff --git a/Dockerfile b/Dockerfile index b890986..77ffdfd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,5 @@ -FROM dmstr/php-yii2:7.0-fpm-1.9-beta2-alpine-nginx +ARG DOCKER_YII2_PHP_IMAGE +FROM ${DOCKER_YII2_PHP_IMAGE} # Project source-code WORKDIR /project diff --git a/README.md b/README.md index e0e79e0..fcbb459 100644 --- a/README.md +++ b/README.md @@ -39,9 +39,10 @@ Community --------- - Participate in [discussions at forums](http://www.yiiframework.com/forum/). -- [Chat in IRC](http://www.yiiframework.com/chat/). +- [Community Slack](https://join.slack.com/t/yii/shared_invite/MjIxMjMxMTk5MTU1LTE1MDE3MDAwMzMtM2VkMTMyMjY1Ng) and [Chat in IRC](http://www.yiiframework.com/chat/). - Follow us on [Facebook](https://www.facebook.com/groups/yiitalk/), [Twitter](https://twitter.com/yiiframework) and [GitHub](https://github.com/yiisoft/yii2). +- Check [other communities](https://github.com/yiisoft/yii2/wiki/communities). Contributing ------------ diff --git a/build/controllers/ClassmapController.php b/build/controllers/ClassmapController.php index a88e6cd..7a4e3b2 100644 --- a/build/controllers/ClassmapController.php +++ b/build/controllers/ClassmapController.php @@ -60,7 +60,7 @@ class ClassmapController extends Controller if (strpos($file, $root) !== 0) { throw new Exception("Something wrong: $file\n"); } - $path = str_replace('\\', '/', substr($file, strlen($root))); + $path = str_replace('\\', '/', substr($file, \strlen($root))); $map[$path] = " 'yii" . substr(str_replace('/', '\\', $path), 0, -4) . "' => YII2_PATH . '$path',"; } ksort($map); diff --git a/build/controllers/DevController.php b/build/controllers/DevController.php index bc26295..c86930f 100644 --- a/build/controllers/DevController.php +++ b/build/controllers/DevController.php @@ -24,19 +24,25 @@ use yii\helpers\FileHelper; */ class DevController extends Controller { + /** + * {@inheritdoc} + */ public $defaultAction = 'all'; - /** * @var bool whether to use HTTP when cloning github repositories */ public $useHttp = false; - + /** + * @var array + */ public $apps = [ 'basic' => 'git@github.com:yiisoft/yii2-app-basic.git', 'advanced' => 'git@github.com:yiisoft/yii2-app-advanced.git', 'benchmark' => 'git@github.com:yiisoft/yii2-app-benchmark.git', ]; - + /** + * @var array + */ public $extensions = [ 'apidoc' => 'git@github.com:yiisoft/yii2-apidoc.git', 'authclient' => 'git@github.com:yiisoft/yii2-authclient.git', @@ -98,17 +104,17 @@ class DevController extends Controller */ public function actionRun($command) { - $command = implode(' ', func_get_args()); + $command = implode(' ', \func_get_args()); // root of the dev repo - $base = dirname(dirname(__DIR__)); + $base = \dirname(\dirname(__DIR__)); $dirs = $this->listSubDirs("$base/extensions"); $dirs = array_merge($dirs, $this->listSubDirs("$base/apps")); asort($dirs); $oldcwd = getcwd(); foreach ($dirs as $dir) { - $displayDir = substr($dir, strlen($base)); + $displayDir = substr($dir, \strlen($base)); $this->stdout("Running '$command' in $displayDir...\n", Console::BOLD); chdir($dir); passthru($command); @@ -137,7 +143,7 @@ class DevController extends Controller public function actionApp($app, $repo = null) { // root of the dev repo - $base = dirname(dirname(__DIR__)); + $base = \dirname(\dirname(__DIR__)); $appDir = "$base/apps/$app"; if (!file_exists($appDir)) { @@ -188,7 +194,7 @@ class DevController extends Controller public function actionExt($extension, $repo = null) { // root of the dev repo - $base = dirname(dirname(__DIR__)); + $base = \dirname(\dirname(__DIR__)); $extensionDir = "$base/extensions/$extension"; if (!file_exists($extensionDir)) { @@ -229,12 +235,12 @@ class DevController extends Controller } /** - * @inheritdoc + * {@inheritdoc} */ public function options($actionID) { $options = parent::options($actionID); - if (in_array($actionID, ['ext', 'app', 'all'], true)) { + if (\in_array($actionID, ['ext', 'app', 'all'], true)) { $options[] = 'useHttp'; } @@ -250,13 +256,13 @@ class DevController extends Controller { if (is_link($link = "$dir/vendor/yiisoft/yii2")) { $this->stdout("Removing symlink $link.\n"); - $this->unlink($link); + FileHelper::unlink($link); } $extensions = $this->findDirs("$dir/vendor/yiisoft"); foreach ($extensions as $ext) { if (is_link($link = "$dir/vendor/yiisoft/yii2-$ext")) { $this->stdout("Removing symlink $link.\n"); - $this->unlink($link); + FileHelper::unlink($link); } } } @@ -294,20 +300,6 @@ class DevController extends Controller } /** - * Properly removes symlinked directory under Windows, MacOS and Linux. - * - * @param string $file path to symlink - */ - protected function unlink($file) - { - if (is_dir($file) && DIRECTORY_SEPARATOR === '\\') { - rmdir($file); - } else { - unlink($file); - } - } - - /** * Get a list of subdirectories for directory specified. * @param string $dir directory to read * diff --git a/build/controllers/MimeTypeController.php b/build/controllers/MimeTypeController.php index 8faf653..2724451 100644 --- a/build/controllers/MimeTypeController.php +++ b/build/controllers/MimeTypeController.php @@ -27,34 +27,60 @@ use yii\helpers\VarDumper; class MimeTypeController extends Controller { /** - * @param string $outFile the file to update. Defaults to @yii/helpers/mimeTypes.php + * @var array MIME type aliases */ - public function actionIndex($outFile = null) + private $aliases = [ + 'text/xml' => 'application/xml', + ]; + + /** + * @param string $outFile the mime file to update. Defaults to @yii/helpers/mimeTypes.php + * @param string $aliasesOutFile the aliases file to update. Defaults to @yii/helpers/mimeAliases.php + */ + public function actionIndex($outFile = null, $aliasesOutFile = null) { if ($outFile === null) { $outFile = Yii::getAlias('@yii/helpers/mimeTypes.php'); } + + if ($aliasesOutFile === null) { + $aliasesOutFile = Yii::getAlias('@yii/helpers/mimeAliases.php'); + } + $this->stdout('downloading mime-type file from apache httpd repository...'); - if ($content = file_get_contents('http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/conf/mime.types?view=co')) { + if ($apacheMimeTypesFileContent = file_get_contents('http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/conf/mime.types?view=co')) { $this->stdout("done.\n", Console::FG_GREEN); - $this->stdout("generating file $outFile..."); - $mimeMap = []; - foreach (explode("\n", $content) as $line) { - $line = trim($line); - if (empty($line) || $line[0] == '#') { // skip comments and empty lines - continue; - } - $parts = preg_split('/\s+/', $line); - $mime = array_shift($parts); - foreach ($parts as $ext) { - if (!empty($ext)) { - $mimeMap[$ext] = $mime; - } + $this->generateMimeTypesFile($outFile, $apacheMimeTypesFileContent); + $this->generateMimeAliasesFile($aliasesOutFile); + } else { + $this->stderr("Failed to download mime.types file from apache SVN.\n"); + } + } + + /** + * @param string $outFile + * @param string $content + */ + private function generateMimeTypesFile($outFile, $content) + { + $this->stdout("generating file $outFile..."); + $mimeMap = []; + foreach (explode("\n", $content) as $line) { + $line = trim($line); + if (empty($line) || $line[0] === '#') { // skip comments and empty lines + continue; + } + $parts = preg_split('/\s+/', $line); + $mime = array_shift($parts); + foreach ($parts as $ext) { + if (!empty($ext)) { + $mimeMap[$ext] = $mime; } } - ksort($mimeMap); - $array = VarDumper::export($mimeMap); - $content = <<stdout("done.\n", Console::FG_GREEN); - } else { - $this->stderr("Failed to download mime.types file from apache SVN.\n"); - } + file_put_contents($outFile, $content); + $this->stdout("done.\n", Console::FG_GREEN); + } + + /** + * @param string $outFile + */ + private function generateMimeAliasesFile($outFile) + { + $this->stdout("generating file $outFile..."); + $array = VarDumper::export($this->aliases); + $content = <<stdout("done.\n", Console::FG_GREEN); } } diff --git a/build/controllers/PhpDocController.php b/build/controllers/PhpDocController.php index 2757c79..19ae5fb 100644 --- a/build/controllers/PhpDocController.php +++ b/build/controllers/PhpDocController.php @@ -11,6 +11,7 @@ use Yii; use yii\console\Controller; use yii\helpers\Console; use yii\helpers\FileHelper; +use yii\helpers\Json; /** * PhpDocController is there to help maintaining PHPDoc annotation in class files. @@ -21,6 +22,9 @@ use yii\helpers\FileHelper; */ class PhpDocController extends Controller { + /** + * {@inheritdoc} + */ public $defaultAction = 'property'; /** * @var bool whether to update class docs directly. Setting this to false will just output docs @@ -82,7 +86,7 @@ class PhpDocController extends Controller $nFilesUpdated = 0; foreach ($files as $file) { $contents = file_get_contents($file); - $sha = sha1($contents); + $hash = $this->hash($contents); // fix line endings $lines = preg_split('/(\r\n|\n|\r)/', $contents); @@ -94,10 +98,10 @@ class PhpDocController extends Controller $lines = array_values($this->fixLineSpacing($lines)); $newContent = implode("\n", $lines); - if ($sha !== sha1($newContent)) { + if ($hash !== $this->hash($newContent)) { + file_put_contents($file, $newContent); $nFilesUpdated++; } - file_put_contents($file, $newContent); $nFilesTotal++; } @@ -106,13 +110,18 @@ class PhpDocController extends Controller } /** - * @inheritdoc + * {@inheritdoc} */ public function options($actionID) { return array_merge(parent::options($actionID), ['updateFiles', 'skipFrameworkRequirements']); } + /** + * @param string $root + * @param bool $needsInclude + * @return array list of files. + */ protected function findFiles($root, $needsInclude = true) { $except = []; @@ -132,7 +141,7 @@ class PhpDocController extends Controller '/generators/extension/default/AutoloadExample.php', ], 'swiftmailer' => [ - '/Logger.php', + 'src/Logger.php', ], 'twig' => [ '/Extension.php', @@ -147,13 +156,9 @@ class PhpDocController extends Controller } if ($root === null) { - $root = dirname(YII2_PATH); + $root = \dirname(YII2_PATH); $extensionPath = "$root/extensions"; - foreach (scandir($extensionPath) as $extension) { - if (ctype_alpha($extension) && is_dir($extensionPath . '/' . $extension)) { - Yii::setAlias("@yii/$extension", "$extensionPath/$extension"); - } - } + $this->setUpExtensionAliases($extensionPath); $except = [ '/apps/', @@ -172,11 +177,11 @@ class PhpDocController extends Controller } } } elseif (preg_match('~extensions/([\w-]+)[\\\\/]?$~', $root, $matches)) { - $extensionPath = dirname(rtrim($root, '\\/')); + $extensionPath = \dirname(rtrim($root, '\\/')); $this->setUpExtensionAliases($extensionPath); list(, $extension) = $matches; - Yii::setAlias("@yii/$extension", "$root"); + Yii::setAlias("@yii/$extension", (string)$root); if (is_file($autoloadFile = Yii::getAlias("@yii/$extension/vendor/autoload.php"))) { include $autoloadFile; } @@ -195,11 +200,11 @@ class PhpDocController extends Controller // return []; // } } elseif (preg_match('~apps/([\w-]+)[\\\\/]?$~', $root, $matches)) { - $extensionPath = dirname(dirname(rtrim($root, '\\/'))) . '/extensions'; + $extensionPath = \dirname(\dirname(rtrim($root, '\\/'))) . '/extensions'; $this->setUpExtensionAliases($extensionPath); list(, $appName) = $matches; - Yii::setAlias("@app-$appName", "$root"); + Yii::setAlias("@app-$appName", (string)$root); if (is_file($autoloadFile = Yii::getAlias("@app-$appName/vendor/autoload.php"))) { include $autoloadFile; } @@ -230,14 +235,30 @@ class PhpDocController extends Controller 'vendor/', ]), ]; + return FileHelper::findFiles($root, $options); } + /** + * @param string $extensionPath root path containing extension repositories. + */ private function setUpExtensionAliases($extensionPath) { foreach (scandir($extensionPath) as $extension) { if (ctype_alpha($extension) && is_dir($extensionPath . '/' . $extension)) { Yii::setAlias("@yii/$extension", "$extensionPath/$extension"); + + $composerConfigFile = $extensionPath . '/' . $extension . '/composer.json'; + if (file_exists($composerConfigFile)) { + $composerConfig = Json::decode(file_get_contents($composerConfigFile)); + if (isset($composerConfig['autoload']['psr-4'])) { + foreach ($composerConfig['autoload']['psr-4'] as $namespace => $subPath) { + $alias = '@' . str_replace('\\', '/', $namespace); + $path = rtrim("$extensionPath/$extension/$subPath", '/'); + Yii::setAlias($alias, $path); + } + } + } } } } @@ -285,6 +306,7 @@ class PhpDocController extends Controller /** * Markdown aware fix of whitespace issues in doc comments. + * @param array $lines */ protected function fixDocBlockIndentation(&$lines) { @@ -326,7 +348,7 @@ class PhpDocController extends Controller $codeBlock = !$codeBlock; $listIndent = ''; } elseif (preg_match('/^(\s*)([0-9]+\.|-|\*|\+) /', $docLine, $matches)) { - $listIndent = str_repeat(' ', strlen($matches[0])); + $listIndent = str_repeat(' ', \strlen($matches[0])); $tag = false; $lines[$i] = $indent . ' * ' . $docLine; continue; @@ -340,6 +362,10 @@ class PhpDocController extends Controller } } + /** + * @param string $line + * @return string + */ protected function fixParamTypes($line) { return preg_replace_callback('~@(param|return) ([\w\\|]+)~i', function ($matches) { @@ -532,10 +558,10 @@ class PhpDocController extends Controller if (trim($oldDoc) != trim($newDoc)) { $fileContent = explode("\n", file_get_contents($file)); $start = $ref->getStartLine() - 2; - $docStart = $start - count(explode("\n", $oldDoc)) + 1; + $docStart = $start - \count(explode("\n", $oldDoc)) + 1; $newFileContent = []; - $n = count($fileContent); + $n = \count($fileContent); for ($i = 0; $i < $n; $i++) { if ($i > $start || $i < $docStart) { $newFileContent[] = $fileContent[$i]; @@ -562,7 +588,7 @@ class PhpDocController extends Controller protected function cleanDocComment($doc) { $lines = explode("\n", $doc); - $n = count($lines); + $n = \count($lines); for ($i = 0; $i < $n; $i++) { $lines[$i] = rtrim($lines[$i]); if (trim($lines[$i]) == '*' && trim($lines[$i + 1]) == '*') { @@ -603,7 +629,7 @@ class PhpDocController extends Controller // if no properties or other tags where present add properties at the end if ($propertyPosition === false) { - $propertyPosition = count($lines) - 2; + $propertyPosition = \count($lines) - 2; } $finalDoc = ''; @@ -626,22 +652,22 @@ class PhpDocController extends Controller $namespace = $namespace['name']; $classes = $this->match('#\n(?:abstract )?class (?\w+)( extends .+)?( implements .+)?\n\{(?.*)\n\}(\n|$)#', $file); - if (count($classes) > 1) { + if (\count($classes) > 1) { $this->stderr("[ERR] There should be only one class in a file: $fileName\n", Console::FG_RED); return false; } - if (count($classes) < 1) { + if (\count($classes) < 1) { $interfaces = $this->match('#\ninterface (?\w+)( extends .+)?\n\{(?.*)\n\}(\n|$)#', $file); - if (count($interfaces) == 1) { + if (\count($interfaces) == 1) { return false; - } elseif (count($interfaces) > 1) { + } elseif (\count($interfaces) > 1) { $this->stderr("[ERR] There should be only one interface in a file: $fileName\n", Console::FG_RED); } else { $traits = $this->match('#\ntrait (?\w+)\n\{(?.*)\n\}(\n|$)#', $file); - if (count($traits) == 1) { + if (\count($traits) == 1) { return false; - } elseif (count($traits) > 1) { + } elseif (\count($traits) > 1) { $this->stderr("[ERR] There should be only one class/trait/interface in a file: $fileName\n", Console::FG_RED); } else { $this->stderr("[ERR] No class in file: $fileName\n", Console::FG_RED); @@ -682,13 +708,13 @@ class PhpDocController extends Controller ksort($props); - if (count($props) > 0) { + if (\count($props) > 0) { $phpdoc .= " *\n"; foreach ($props as $propName => &$prop) { $docline = ' * @'; $docline .= 'property'; // Do not use property-read and property-write as few IDEs support complex syntax. $note = ''; - if (isset($prop['get']) && isset($prop['set'])) { + if (isset($prop['get'], $prop['set'])) { if ($prop['get']['type'] != $prop['set']['type']) { $note = ' Note that the type of this property differs in getter and setter.' . ' See [[get' . ucfirst($propName) . '()]] and [[set' . ucfirst($propName) . '()]] for details.'; @@ -706,7 +732,7 @@ class PhpDocController extends Controller } if (!$parentSetter) { $note = ' This property is read-only.'; -// $docline .= '-read'; + //$docline .= '-read'; } } elseif (isset($prop['set'])) { // check if parent class has getter defined @@ -721,7 +747,7 @@ class PhpDocController extends Controller } if (!$parentGetter) { $note = ' This property is write-only.'; -// $docline .= '-write'; + //$docline .= '-write'; } } else { continue; @@ -773,11 +799,24 @@ class PhpDocController extends Controller return ''; } - return strtoupper(substr($str, 0, 1)) . substr($str, 1) . ($str[strlen($str) - 1] != '.' ? '.' : ''); + return strtoupper(substr($str, 0, 1)) . substr($str, 1) . ($str[\strlen($str) - 1] != '.' ? '.' : ''); } protected function getPropParam($prop, $param) { return isset($prop['property']) ? $prop['property'][$param] : (isset($prop['get']) ? $prop['get'][$param] : $prop['set'][$param]); } + + /** + * Generate a hash value (message digest) + * @param string $string message to be hashed. + * @return string calculated message digest. + */ + private function hash($string) + { + if (!function_exists('hash')) { + return sha1($string); + } + return hash('sha256', $string); + } } diff --git a/build/controllers/ReleaseController.php b/build/controllers/ReleaseController.php index 985f1e7..ff1dfd3 100644 --- a/build/controllers/ReleaseController.php +++ b/build/controllers/ReleaseController.php @@ -82,7 +82,7 @@ class ReleaseController extends Controller throw new Exception('Sorry, but releases should be run interactively to ensure you actually verify what you are doing ;)'); } if ($this->basePath === null) { - $this->basePath = dirname(dirname(__DIR__)); + $this->basePath = \dirname(\dirname(__DIR__)); } $this->basePath = rtrim($this->basePath, '\\/'); return parent::beforeAction($action); @@ -109,7 +109,7 @@ class ReleaseController extends Controller foreach ($items as $item) { $this->stdout("fetching tags for $item..."); if ($item === 'framework') { - $this->gitFetchTags("{$this->basePath}"); + $this->gitFetchTags((string)$this->basePath); } elseif (strncmp('app-', $item, 4) === 0) { $this->gitFetchTags("{$this->basePath}/apps/" . substr($item, 4)); } else { @@ -183,7 +183,7 @@ class ReleaseController extends Controller */ public function actionRelease(array $what) { - if (count($what) > 1) { + if (\count($what) > 1) { $this->stdout("Currently only one simultaneous release is supported.\n"); return 1; } @@ -315,7 +315,7 @@ class ReleaseController extends Controller */ public function actionSortChangelog(array $what) { - if (count($what) > 1) { + if (\count($what) > 1) { $this->stdout("Currently only one simultaneous release is supported.\n"); return 1; } @@ -376,7 +376,7 @@ class ReleaseController extends Controller { foreach ($what as $w) { if (strncmp('app-', $w, 4) === 0) { - if (!empty($limit) && !in_array('app', $limit)) { + if (!empty($limit) && !\in_array('app', $limit)) { throw new Exception('Only the following types are allowed: ' . implode(', ', $limit) . "\n"); } if (!is_dir($appPath = "{$this->basePath}/apps/" . substr($w, 4))) { @@ -386,7 +386,7 @@ class ReleaseController extends Controller $this->ensureGitClean($appPath); } } elseif ($w === 'framework') { - if (!empty($limit) && !in_array('framework', $limit)) { + if (!empty($limit) && !\in_array('framework', $limit)) { throw new Exception('Only the following types are allowed: ' . implode(', ', $limit) . "\n"); } if (!is_dir($fwPath = "{$this->basePath}/framework")) { @@ -396,7 +396,7 @@ class ReleaseController extends Controller $this->ensureGitClean($fwPath); } } else { - if (!empty($limit) && !in_array('ext', $limit)) { + if (!empty($limit) && !\in_array('ext', $limit)) { throw new Exception('Only the following types are allowed: ' . implode(', ', $limit) . "\n"); } if (!is_dir($extPath = "{$this->basePath}/extensions/$w")) { @@ -414,7 +414,7 @@ class ReleaseController extends Controller { $this->stdout("\n"); $this->stdout($h = "Preparing framework release version $version", Console::BOLD); - $this->stdout("\n" . str_repeat('-', strlen($h)) . "\n\n", Console::BOLD); + $this->stdout("\n" . str_repeat('-', \strlen($h)) . "\n\n", Console::BOLD); if (!$this->confirm('Make sure you are on the right branch for this release and that it tracks the correct remote branch! Continue?')) { exit(1); @@ -433,8 +433,8 @@ class ReleaseController extends Controller $this->dryRun || Yii::$app->runAction('classmap', [$frameworkPath]); $this->stdout("done.\n", Console::FG_GREEN, Console::BOLD); - $this->stdout('updating mimetype magic file...', Console::BOLD); - $this->dryRun || Yii::$app->runAction('mime-type', ["$frameworkPath/helpers/mimeTypes.php"]); + $this->stdout('updating mimetype magic file and mime aliases...', Console::BOLD); + $this->dryRun || Yii::$app->runAction('mime-type', ["$frameworkPath/helpers/mimeTypes.php"], ["$frameworkPath/helpers/mimeAliases.php"]); $this->stdout("done.\n", Console::FG_GREEN, Console::BOLD); $this->stdout("fixing various PHPDoc style issues...\n", Console::BOLD); @@ -552,7 +552,7 @@ class ReleaseController extends Controller { $this->stdout("\n"); $this->stdout($h = "Preparing release for application $name version $version", Console::BOLD); - $this->stdout("\n" . str_repeat('-', strlen($h)) . "\n\n", Console::BOLD); + $this->stdout("\n" . str_repeat('-', \strlen($h)) . "\n\n", Console::BOLD); if (!$this->confirm('Make sure you are on the right branch for this release and that it tracks the correct remote branch! Continue?')) { exit(1); @@ -670,7 +670,7 @@ class ReleaseController extends Controller { $this->stdout("\n"); $this->stdout($h = "Preparing release for extension $name version $version", Console::BOLD); - $this->stdout("\n" . str_repeat('-', strlen($h)) . "\n\n", Console::BOLD); + $this->stdout("\n" . str_repeat('-', \strlen($h)) . "\n\n", Console::BOLD); if (!$this->confirm('Make sure you are on the right branch for this release and that it tracks the correct remote branch! Continue?')) { exit(1); @@ -817,7 +817,7 @@ class ReleaseController extends Controller $headline = $version . ' ' . date('F d, Y'); $this->sed( '/' . $v . ' under development\n(-+?)\n/', - $headline . "\n" . str_repeat('-', strlen($headline)) . "\n", + $headline . "\n" . str_repeat('-', \strlen($headline)) . "\n", $this->getChangelogs($what) ); } @@ -825,7 +825,7 @@ class ReleaseController extends Controller protected function openChangelogs($what, $version) { $headline = "\n$version under development\n"; - $headline .= str_repeat('-', strlen($headline) - 2) . "\n\n- no changes in this release.\n"; + $headline .= str_repeat('-', \strlen($headline) - 2) . "\n\n- no changes in this release.\n"; foreach ($this->getChangelogs($what) as $file) { $lines = explode("\n", file_get_contents($file)); $hl = [ @@ -874,7 +874,7 @@ class ReleaseController extends Controller $state = 'end'; } // add continued lines to the last item to keep them together - if (!empty(${$state}) && trim($line !== '') && strpos($line, '- ') !== 0) { + if (!empty(${$state}) && trim($line) !== '' && strncmp($line, '- ', 2) !== 0) { end(${$state}); ${$state}[key(${$state})] .= "\n" . $line; } else { @@ -919,7 +919,7 @@ class ReleaseController extends Controller protected function getChangelogs($what) { $changelogs = []; - if (in_array('framework', $what)) { + if (\in_array('framework', $what)) { $changelogs[] = $this->getFrameworkChangelog(); } @@ -947,13 +947,13 @@ class ReleaseController extends Controller protected function composerSetStability($what, $version) { $apps = []; - if (in_array('app-advanced', $what)) { + if (\in_array('app-advanced', $what)) { $apps[] = $this->basePath . '/apps/advanced/composer.json'; } - if (in_array('app-basic', $what)) { + if (\in_array('app-basic', $what)) { $apps[] = $this->basePath . '/apps/basic/composer.json'; } - if (in_array('app-benchmark', $what)) { + if (\in_array('app-benchmark', $what)) { $apps[] = $this->basePath . '/apps/benchmark/composer.json'; } if (empty($apps)) { diff --git a/build/controllers/Utf8Controller.php b/build/controllers/Utf8Controller.php index 64e8c0a..ca5175d 100644 --- a/build/controllers/Utf8Controller.php +++ b/build/controllers/Utf8Controller.php @@ -29,7 +29,7 @@ class Utf8Controller extends Controller public function actionCheckGuide($directory = null) { if ($directory === null) { - $directory = dirname(dirname(__DIR__)) . '/docs'; + $directory = \dirname(\dirname(__DIR__)) . '/docs'; } if (is_file($directory)) { $files = [$directory]; @@ -90,7 +90,7 @@ class Utf8Controller extends Controller } $hexcode = dechex($this->unicodeOrd($char)); - $hexcode = str_repeat('0', max(4 - strlen($hexcode), 0)) . $hexcode; + $hexcode = str_repeat('0', max(4 - \strlen($hexcode), 0)) . $hexcode; $this->stdout(" at $line:$pos FOUND $what: 0x$hexcode '$char' http://unicode-table.com/en/$hexcode/\n"); } @@ -105,20 +105,20 @@ class Utf8Controller extends Controller */ private function unicodeOrd($c) { - $h = ord($c[0]); + $h = \ord($c[0]); if ($h <= 0x7F) { return $h; } elseif ($h < 0xC2) { return false; } elseif ($h <= 0xDF) { - return ($h & 0x1F) << 6 | (ord($c[1]) & 0x3F); + return ($h & 0x1F) << 6 | (\ord($c[1]) & 0x3F); } elseif ($h <= 0xEF) { - return ($h & 0x0F) << 12 | (ord($c[1]) & 0x3F) << 6 - | (ord($c[2]) & 0x3F); + return ($h & 0x0F) << 12 | (\ord($c[1]) & 0x3F) << 6 + | (\ord($c[2]) & 0x3F); } elseif ($h <= 0xF4) { - return ($h & 0x0F) << 18 | (ord($c[1]) & 0x3F) << 12 - | (ord($c[2]) & 0x3F) << 6 - | (ord($c[3]) & 0x3F); + return ($h & 0x0F) << 18 | (\ord($c[1]) & 0x3F) << 12 + | (\ord($c[2]) & 0x3F) << 6 + | (\ord($c[3]) & 0x3F); } return false; diff --git a/composer.lock b/composer.lock index d9ef2af..ccd7209 100644 --- a/composer.lock +++ b/composer.lock @@ -4,21 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "4708f40ee8cd75e770ca3207cfada97f", - "content-hash": "50ec7b3fadeb5044752b5074e84acd74", + "content-hash": "c5363e83fd40667959bed938186dbdf2", "packages": [ { "name": "bower-asset/inputmask", - "version": "3.3.7", + "version": "3.3.11", "source": { "type": "git", "url": "https://github.com/RobinHerbots/Inputmask.git", - "reference": "9835731cb78cac749734d94a1cb5bd70da4d3b10" + "reference": "5e670ad62f50c738388d4dcec78d2888505ad77b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/RobinHerbots/Inputmask/zipball/9835731cb78cac749734d94a1cb5bd70da4d3b10", - "reference": "9835731cb78cac749734d94a1cb5bd70da4d3b10", + "url": "https://api.github.com/repos/RobinHerbots/Inputmask/zipball/5e670ad62f50c738388d4dcec78d2888505ad77b", + "reference": "5e670ad62f50c738388d4dcec78d2888505ad77b", "shasum": null }, "require": { @@ -31,33 +30,21 @@ }, { "name": "bower-asset/jquery", - "version": "2.2.4", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/jquery/jquery-dist.git", - "reference": "c0185ab7c75aab88762c5aae780b9d83b80eda72" + "reference": "77d2a51d0520d2ee44173afdf4e40a9201f5964e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jquery/jquery-dist/zipball/c0185ab7c75aab88762c5aae780b9d83b80eda72", - "reference": "c0185ab7c75aab88762c5aae780b9d83b80eda72", - "shasum": "" - }, - "type": "bower-asset-library", - "extra": { - "bower-asset-main": "dist/jquery.js", - "bower-asset-ignore": [ - "package.json" - ] + "url": "https://api.github.com/repos/jquery/jquery-dist/zipball/77d2a51d0520d2ee44173afdf4e40a9201f5964e", + "reference": "77d2a51d0520d2ee44173afdf4e40a9201f5964e", + "shasum": null }, + "type": "bower-asset", "license": [ "MIT" - ], - "keywords": [ - "browser", - "javascript", - "jquery", - "library" ] }, { @@ -90,34 +77,22 @@ }, { "name": "bower-asset/yii2-pjax", - "version": "v2.0.6", + "version": "2.0.7.1", "source": { "type": "git", "url": "https://github.com/yiisoft/jquery-pjax.git", - "reference": "60728da6ade5879e807a49ce59ef9a72039b8978" + "reference": "aef7b953107264f00234902a3880eb50dafc48be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/yiisoft/jquery-pjax/zipball/60728da6ade5879e807a49ce59ef9a72039b8978", - "reference": "60728da6ade5879e807a49ce59ef9a72039b8978", - "shasum": "" + "url": "https://api.github.com/repos/yiisoft/jquery-pjax/zipball/aef7b953107264f00234902a3880eb50dafc48be", + "reference": "aef7b953107264f00234902a3880eb50dafc48be", + "shasum": null }, "require": { "bower-asset/jquery": ">=1.8" }, - "type": "bower-asset-library", - "extra": { - "bower-asset-main": "./jquery.pjax.js", - "bower-asset-ignore": [ - ".travis.yml", - "Gemfile", - "Gemfile.lock", - "CONTRIBUTING.md", - "vendor/", - "script/", - "test/" - ] - }, + "type": "bower-asset", "license": [ "MIT" ] @@ -180,7 +155,7 @@ "markdown", "markdown-extra" ], - "time": "2017-07-16 21:13:23" + "time": "2017-07-16T21:13:23+00:00" }, { "name": "ezyang/htmlpurifier", @@ -227,7 +202,7 @@ "keywords": [ "html" ], - "time": "2017-06-03 02:28:16" + "time": "2017-06-03T02:28:16+00:00" }, { "name": "yiisoft/yii2-composer", @@ -277,7 +252,7 @@ "extension installer", "yii2" ], - "time": "2016-12-20 13:26:02" + "time": "2016-12-20T13:26:02+00:00" } ], "packages-dev": [ @@ -312,7 +287,69 @@ } ], "description": "a small tool to convert text file indentation", - "time": "2014-05-23 14:40:08" + "time": "2014-05-23T14:40:08+00:00" + }, + { + "name": "composer/semver", + "version": "1.4.2", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/c7cb9a2095a074d131b65a8a0cd294479d785573", + "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.5 || ^5.0.5", + "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "time": "2016-08-30T16:08:34+00:00" }, { "name": "doctrine/annotations", @@ -380,7 +417,7 @@ "docblock", "parser" ], - "time": "2015-08-31 12:32:49" + "time": "2015-08-31T12:32:49+00:00" }, { "name": "doctrine/instantiator", @@ -434,7 +471,7 @@ "constructor", "instantiate" ], - "time": "2015-06-14 21:17:01" + "time": "2015-06-14T21:17:01+00:00" }, { "name": "doctrine/lexer", @@ -488,40 +525,41 @@ "lexer", "parser" ], - "time": "2014-09-09 13:34:57" + "time": "2014-09-09T13:34:57+00:00" }, { "name": "friendsofphp/php-cs-fixer", - "version": "v2.2.4", + "version": "v2.2.12", "source": { "type": "git", "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "5191e01d0fa0f579eb709350306cd11ad6427ca6" + "reference": "362ad63e80d05a238fbe542d75cc1f8e9246797e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/5191e01d0fa0f579eb709350306cd11ad6427ca6", - "reference": "5191e01d0fa0f579eb709350306cd11ad6427ca6", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/362ad63e80d05a238fbe542d75cc1f8e9246797e", + "reference": "362ad63e80d05a238fbe542d75cc1f8e9246797e", "shasum": "" }, "require": { + "composer/semver": "^1.4", "doctrine/annotations": "^1.2", "ext-json": "*", "ext-tokenizer": "*", "gecko-packages/gecko-php-unit": "^2.0", - "php": "^5.3.6 || >=7.0 <7.2", + "php": "^5.3.6 || >=7.0 <7.3", "sebastian/diff": "^1.4", - "symfony/console": "^2.4 || ^3.0", - "symfony/event-dispatcher": "^2.1 || ^3.0", - "symfony/filesystem": "^2.4 || ^3.0", - "symfony/finder": "^2.2 || ^3.0", - "symfony/options-resolver": "^2.6 || ^3.0", + "symfony/console": "^2.4 || ^3.0 || ^4.0", + "symfony/event-dispatcher": "^2.1 || ^3.0 || ^4.0", + "symfony/filesystem": "^2.4 || ^3.0 || ^4.0", + "symfony/finder": "^2.2 || ^3.0 || ^4.0", + "symfony/options-resolver": "^2.6 || ^3.0 || ^4.0", "symfony/polyfill-php54": "^1.0", "symfony/polyfill-php55": "^1.3", "symfony/polyfill-php70": "^1.0", - "symfony/polyfill-xml": "^1.3", - "symfony/process": "^2.3 || ^3.0", - "symfony/stopwatch": "^2.5 || ^3.0" + "symfony/polyfill-php72": "^1.4", + "symfony/process": "^2.3 || ^3.0 || ^4.0", + "symfony/stopwatch": "^2.5 || ^3.0 || ^4.0" }, "conflict": { "hhvm": "<3.18" @@ -529,13 +567,12 @@ "require-dev": { "johnkary/phpunit-speedtrap": "^1.0.1", "justinrainbow/json-schema": "^5.0", + "php-coveralls/php-coveralls": "^1.0.2", "phpunit/phpunit": "^4.8.35 || ^5.4.3", - "satooshi/php-coveralls": "^1.0", - "symfony/phpunit-bridge": "^3.2.2" + "symfony/phpunit-bridge": "^3.2.2 || ^4.0" }, "suggest": { "ext-mbstring": "For handling non-UTF8 characters in cache signature.", - "ext-xml": "For better performance.", "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." }, "bin": [ @@ -550,7 +587,13 @@ "autoload": { "psr-4": { "PhpCsFixer\\": "src/" - } + }, + "classmap": [ + "tests/Test/AbstractFixerTestCase.php", + "tests/Test/AbstractIntegrationTestCase.php", + "tests/Test/IntegrationCase.php", + "tests/Test/IntegrationCaseFactory.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -567,20 +610,20 @@ } ], "description": "A tool to automatically fix PHP code style", - "time": "2017-05-24 21:55:27" + "time": "2017-11-26T20:41:43+00:00" }, { "name": "gecko-packages/gecko-php-unit", - "version": "v2.1", + "version": "v2.2", "source": { "type": "git", "url": "https://github.com/GeckoPackages/GeckoPHPUnit.git", - "reference": "5b9e9622c7efd3b22655270b80c03f9e52878a6e" + "reference": "ab525fac9a9ffea219687f261b02008b18ebf2d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/GeckoPackages/GeckoPHPUnit/zipball/5b9e9622c7efd3b22655270b80c03f9e52878a6e", - "reference": "5b9e9622c7efd3b22655270b80c03f9e52878a6e", + "url": "https://api.github.com/repos/GeckoPackages/GeckoPHPUnit/zipball/ab525fac9a9ffea219687f261b02008b18ebf2d1", + "reference": "ab525fac9a9ffea219687f261b02008b18ebf2d1", "shasum": "" }, "require": { @@ -589,24 +632,29 @@ "require-dev": { "phpunit/phpunit": "^4.8.35 || ^5.4.3" }, + "suggest": { + "ext-dom": "When testing with xml.", + "ext-libxml": "When testing with xml.", + "phpunit/phpunit": "This is an extension for it so make sure you have it some way." + }, "type": "library", "autoload": { "psr-4": { - "GeckoPackages\\PHPUnit\\": "src\\PHPUnit" + "GeckoPackages\\PHPUnit\\": "src/PHPUnit" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "Additional PHPUnit tests.", + "description": "Additional PHPUnit asserts and constraints.", "homepage": "https://github.com/GeckoPackages", "keywords": [ "extension", "filesystem", "phpunit" ], - "time": "2017-06-20 11:22:48" + "time": "2017-08-23T07:39:54+00:00" }, { "name": "ircmaxell/password-compat", @@ -648,20 +696,20 @@ "hashing", "password" ], - "time": "2014-11-20 16:49:30" + "time": "2014-11-20T16:49:30+00:00" }, { "name": "paragonie/random_compat", - "version": "v2.0.10", + "version": "v2.0.11", "source": { "type": "git", "url": "https://github.com/paragonie/random_compat.git", - "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d" + "reference": "5da4d3c796c275c55f057af5a643ae297d96b4d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/634bae8e911eefa89c1abfbf1b66da679ac8f54d", - "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/5da4d3c796c275c55f057af5a643ae297d96b4d8", + "reference": "5da4d3c796c275c55f057af5a643ae297d96b4d8", "shasum": "" }, "require": { @@ -696,7 +744,7 @@ "pseudorandom", "random" ], - "time": "2017-03-13 16:27:32" + "time": "2017-09-27T21:40:39+00:00" }, { "name": "phpdocumentor/reflection-docblock", @@ -745,37 +793,37 @@ "email": "mike.vanriel@naenius.com" } ], - "time": "2016-01-25 08:17:30" + "time": "2016-01-25T08:17:30+00:00" }, { "name": "phpspec/prophecy", - "version": "v1.7.0", + "version": "1.7.3", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "93d39f1f7f9326d746203c7c056f300f7f126073" + "reference": "e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073", - "reference": "93d39f1f7f9326d746203c7c056f300f7f126073", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf", + "reference": "e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", "sebastian/comparator": "^1.1|^2.0", "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, "require-dev": { "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8 || ^5.6.5" + "phpunit/phpunit": "^4.8.35 || ^5.7" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6.x-dev" + "dev-master": "1.7.x-dev" } }, "autoload": { @@ -808,7 +856,7 @@ "spy", "stub" ], - "time": "2017-03-02 20:05:34" + "time": "2017-11-24T13:59:53+00:00" }, { "name": "phpunit/php-code-coverage", @@ -870,20 +918,20 @@ "testing", "xunit" ], - "time": "2015-10-06 15:47:00" + "time": "2015-10-06T15:47:00+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "1.4.2", + "version": "1.4.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", "shasum": "" }, "require": { @@ -917,7 +965,7 @@ "filesystem", "iterator" ], - "time": "2016-10-03 07:40:28" + "time": "2017-11-27T13:52:08+00:00" }, { "name": "phpunit/php-text-template", @@ -958,7 +1006,7 @@ "keywords": [ "template" ], - "time": "2015-06-21 13:50:34" + "time": "2015-06-21T13:50:34+00:00" }, { "name": "phpunit/php-timer", @@ -1007,7 +1055,7 @@ "keywords": [ "timer" ], - "time": "2017-02-26 11:10:40" + "time": "2017-02-26T11:10:40+00:00" }, { "name": "phpunit/php-token-stream", @@ -1056,7 +1104,7 @@ "keywords": [ "tokenizer" ], - "time": "2017-02-27 10:12:30" + "time": "2017-02-27T10:12:30+00:00" }, { "name": "phpunit/phpunit", @@ -1128,7 +1176,7 @@ "testing", "xunit" ], - "time": "2017-01-26 16:15:36" + "time": "2017-01-26T16:15:36+00:00" }, { "name": "phpunit/phpunit-mock-objects", @@ -1184,7 +1232,7 @@ "mock", "xunit" ], - "time": "2015-10-02 06:51:40" + "time": "2015-10-02T06:51:40+00:00" }, { "name": "psr/log", @@ -1231,7 +1279,7 @@ "psr", "psr-3" ], - "time": "2016-10-10 12:19:37" + "time": "2016-10-10T12:19:37+00:00" }, { "name": "sebastian/comparator", @@ -1295,7 +1343,7 @@ "compare", "equality" ], - "time": "2017-01-29 09:50:25" + "time": "2017-01-29T09:50:25+00:00" }, { "name": "sebastian/diff", @@ -1347,7 +1395,7 @@ "keywords": [ "diff" ], - "time": "2017-05-22 07:24:03" + "time": "2017-05-22T07:24:03+00:00" }, { "name": "sebastian/environment", @@ -1397,7 +1445,7 @@ "environment", "hhvm" ], - "time": "2016-08-18 05:49:44" + "time": "2016-08-18T05:49:44+00:00" }, { "name": "sebastian/exporter", @@ -1464,7 +1512,7 @@ "export", "exporter" ], - "time": "2016-06-17 09:04:28" + "time": "2016-06-17T09:04:28+00:00" }, { "name": "sebastian/global-state", @@ -1515,7 +1563,7 @@ "keywords": [ "global state" ], - "time": "2015-10-12 03:26:01" + "time": "2015-10-12T03:26:01+00:00" }, { "name": "sebastian/recursion-context", @@ -1568,7 +1616,7 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2016-10-03 07:41:43" + "time": "2016-10-03T07:41:43+00:00" }, { "name": "sebastian/version", @@ -1603,20 +1651,20 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-06-21 13:59:46" + "time": "2015-06-21T13:59:46+00:00" }, { "name": "symfony/console", - "version": "v2.8.25", + "version": "v2.8.31", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "46e65f8d98c9ab629bbfcc16a4ff023f61c37fb2" + "reference": "7cad097cf081c0ab3d0322cc38d34ee80484d86f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/46e65f8d98c9ab629bbfcc16a4ff023f61c37fb2", - "reference": "46e65f8d98c9ab629bbfcc16a4ff023f61c37fb2", + "url": "https://api.github.com/repos/symfony/console/zipball/7cad097cf081c0ab3d0322cc38d34ee80484d86f", + "reference": "7cad097cf081c0ab3d0322cc38d34ee80484d86f", "shasum": "" }, "require": { @@ -1664,20 +1712,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2017-07-03 08:04:30" + "time": "2017-11-16T15:20:19+00:00" }, { "name": "symfony/debug", - "version": "v2.8.25", + "version": "v2.8.31", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "8470d7701177a88edeb0cec59b44d50ef4477e9b" + "reference": "a0a29e9867debabdace779a20a9385c623a23bbd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/8470d7701177a88edeb0cec59b44d50ef4477e9b", - "reference": "8470d7701177a88edeb0cec59b44d50ef4477e9b", + "url": "https://api.github.com/repos/symfony/debug/zipball/a0a29e9867debabdace779a20a9385c623a23bbd", + "reference": "a0a29e9867debabdace779a20a9385c623a23bbd", "shasum": "" }, "require": { @@ -1721,20 +1769,20 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2017-06-01 20:52:29" + "time": "2017-10-24T13:48:52+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v2.8.25", + "version": "v2.8.31", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "1377400fd641d7d1935981546aaef780ecd5bf6d" + "reference": "b59aacf238fadda50d612c9de73b74751872a903" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/1377400fd641d7d1935981546aaef780ecd5bf6d", - "reference": "1377400fd641d7d1935981546aaef780ecd5bf6d", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b59aacf238fadda50d612c9de73b74751872a903", + "reference": "b59aacf238fadda50d612c9de73b74751872a903", "shasum": "" }, "require": { @@ -1781,20 +1829,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2017-06-02 07:47:27" + "time": "2017-11-05T15:25:56+00:00" }, { "name": "symfony/filesystem", - "version": "v2.8.25", + "version": "v2.8.31", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "714b1036010c354ae2b25d7f9ca27e14e265e9f2" + "reference": "10507c5f24577b0ad971b0d22097c823b2b45dd3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/714b1036010c354ae2b25d7f9ca27e14e265e9f2", - "reference": "714b1036010c354ae2b25d7f9ca27e14e265e9f2", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/10507c5f24577b0ad971b0d22097c823b2b45dd3", + "reference": "10507c5f24577b0ad971b0d22097c823b2b45dd3", "shasum": "" }, "require": { @@ -1830,20 +1878,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2017-07-11 07:12:11" + "time": "2017-11-07T14:08:47+00:00" }, { "name": "symfony/finder", - "version": "v2.8.25", + "version": "v2.8.31", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "4f4e84811004e065a3bb5ceeb1d9aa592630f9ad" + "reference": "efeceae6a05a9b2fcb3391333f1d4a828ff44ab8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/4f4e84811004e065a3bb5ceeb1d9aa592630f9ad", - "reference": "4f4e84811004e065a3bb5ceeb1d9aa592630f9ad", + "url": "https://api.github.com/repos/symfony/finder/zipball/efeceae6a05a9b2fcb3391333f1d4a828ff44ab8", + "reference": "efeceae6a05a9b2fcb3391333f1d4a828ff44ab8", "shasum": "" }, "require": { @@ -1879,20 +1927,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2017-06-01 20:52:29" + "time": "2017-11-05T15:25:56+00:00" }, { "name": "symfony/options-resolver", - "version": "v2.8.25", + "version": "v2.8.31", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "55bf349a3395afad81a369d57b3b99c373fbbdf5" + "reference": "e4e64cb8e01981425098bfb6000ac397206dfc25" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/55bf349a3395afad81a369d57b3b99c373fbbdf5", - "reference": "55bf349a3395afad81a369d57b3b99c373fbbdf5", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/e4e64cb8e01981425098bfb6000ac397206dfc25", + "reference": "e4e64cb8e01981425098bfb6000ac397206dfc25", "shasum": "" }, "require": { @@ -1933,20 +1981,20 @@ "configuration", "options" ], - "time": "2017-04-12 14:07:15" + "time": "2017-11-05T15:25:56+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.4.0", + "version": "v1.6.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "f29dca382a6485c3cbe6379f0c61230167681937" + "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/f29dca382a6485c3cbe6379f0c61230167681937", - "reference": "f29dca382a6485c3cbe6379f0c61230167681937", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296", + "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296", "shasum": "" }, "require": { @@ -1958,7 +2006,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "1.6-dev" } }, "autoload": { @@ -1992,20 +2040,20 @@ "portable", "shim" ], - "time": "2017-06-09 14:24:12" + "time": "2017-10-11T12:05:26+00:00" }, { "name": "symfony/polyfill-php54", - "version": "v1.4.0", + "version": "v1.6.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php54.git", - "reference": "7dd1a8b9f0442273fdfeb1c4f5eaff6890a82789" + "reference": "d7810a14b2c6c1aff415e1bb755f611b3d5327bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php54/zipball/7dd1a8b9f0442273fdfeb1c4f5eaff6890a82789", - "reference": "7dd1a8b9f0442273fdfeb1c4f5eaff6890a82789", + "url": "https://api.github.com/repos/symfony/polyfill-php54/zipball/d7810a14b2c6c1aff415e1bb755f611b3d5327bc", + "reference": "d7810a14b2c6c1aff415e1bb755f611b3d5327bc", "shasum": "" }, "require": { @@ -2014,7 +2062,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "1.6-dev" } }, "autoload": { @@ -2050,20 +2098,20 @@ "portable", "shim" ], - "time": "2017-06-09 08:25:21" + "time": "2017-10-11T12:05:26+00:00" }, { "name": "symfony/polyfill-php55", - "version": "v1.4.0", + "version": "v1.6.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php55.git", - "reference": "94566239a7720cde0820f15f0cc348ddb51ba51d" + "reference": "b64e7f0c37ecf144ecc16668936eef94e628fbfd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php55/zipball/94566239a7720cde0820f15f0cc348ddb51ba51d", - "reference": "94566239a7720cde0820f15f0cc348ddb51ba51d", + "url": "https://api.github.com/repos/symfony/polyfill-php55/zipball/b64e7f0c37ecf144ecc16668936eef94e628fbfd", + "reference": "b64e7f0c37ecf144ecc16668936eef94e628fbfd", "shasum": "" }, "require": { @@ -2073,7 +2121,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "1.6-dev" } }, "autoload": { @@ -2106,20 +2154,20 @@ "portable", "shim" ], - "time": "2017-06-09 08:25:21" + "time": "2017-10-11T12:05:26+00:00" }, { "name": "symfony/polyfill-php70", - "version": "v1.4.0", + "version": "v1.6.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "032fd647d5c11a9ceab8ee8747e13b5448e93874" + "reference": "0442b9c0596610bd24ae7b5f0a6cdbbc16d9fcff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/032fd647d5c11a9ceab8ee8747e13b5448e93874", - "reference": "032fd647d5c11a9ceab8ee8747e13b5448e93874", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/0442b9c0596610bd24ae7b5f0a6cdbbc16d9fcff", + "reference": "0442b9c0596610bd24ae7b5f0a6cdbbc16d9fcff", "shasum": "" }, "require": { @@ -2129,7 +2177,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "1.6-dev" } }, "autoload": { @@ -2165,20 +2213,20 @@ "portable", "shim" ], - "time": "2017-06-09 14:24:12" + "time": "2017-10-11T12:05:26+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.4.0", + "version": "v1.6.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "d3a71580c1e2cab33b6d705f0ec40e9015e14d5c" + "reference": "6de4f4884b97abbbed9f0a84a95ff2ff77254254" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/d3a71580c1e2cab33b6d705f0ec40e9015e14d5c", - "reference": "d3a71580c1e2cab33b6d705f0ec40e9015e14d5c", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/6de4f4884b97abbbed9f0a84a95ff2ff77254254", + "reference": "6de4f4884b97abbbed9f0a84a95ff2ff77254254", "shasum": "" }, "require": { @@ -2187,7 +2235,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "1.6-dev" } }, "autoload": { @@ -2220,68 +2268,20 @@ "portable", "shim" ], - "time": "2017-06-09 08:25:21" - }, - { - "name": "symfony/polyfill-xml", - "version": "v1.4.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-xml.git", - "reference": "89326af9d173053826ae8fe26a6f49597ba4e9f3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-xml/zipball/89326af9d173053826ae8fe26a6f49597ba4e9f3", - "reference": "89326af9d173053826ae8fe26a6f49597ba4e9f3", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "symfony/polyfill-php72": "~1.4" - }, - "type": "metapackage", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for xml's utf8_encode and utf8_decode functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "time": "2017-06-09 08:25:21" + "time": "2017-10-11T12:05:26+00:00" }, { "name": "symfony/process", - "version": "v2.8.25", + "version": "v2.8.31", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "57e52a0a6a80ea0aec4fc1b785a7920a95cb88a8" + "reference": "d25449e031f600807949aab7cadbf267712f4eee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/57e52a0a6a80ea0aec4fc1b785a7920a95cb88a8", - "reference": "57e52a0a6a80ea0aec4fc1b785a7920a95cb88a8", + "url": "https://api.github.com/repos/symfony/process/zipball/d25449e031f600807949aab7cadbf267712f4eee", + "reference": "d25449e031f600807949aab7cadbf267712f4eee", "shasum": "" }, "require": { @@ -2317,20 +2317,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2017-07-03 08:04:30" + "time": "2017-11-05T15:25:56+00:00" }, { "name": "symfony/stopwatch", - "version": "v2.8.25", + "version": "v2.8.31", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "e02577b841394a78306d7b547701bb7bb705bad5" + "reference": "533bb9d7c2da1c6d2da163ecf0f22043ea98f59b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/e02577b841394a78306d7b547701bb7bb705bad5", - "reference": "e02577b841394a78306d7b547701bb7bb705bad5", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/533bb9d7c2da1c6d2da163ecf0f22043ea98f59b", + "reference": "533bb9d7c2da1c6d2da163ecf0f22043ea98f59b", "shasum": "" }, "require": { @@ -2366,20 +2366,20 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2017-04-12 14:07:15" + "time": "2017-11-10T18:59:36+00:00" }, { "name": "symfony/yaml", - "version": "v2.8.25", + "version": "v2.8.31", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "4c29dec8d489c4e37cf87ccd7166cd0b0e6a45c5" + "reference": "d819bf267e901727141fe828ae888486fd21236e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/4c29dec8d489c4e37cf87ccd7166cd0b0e6a45c5", - "reference": "4c29dec8d489c4e37cf87ccd7166cd0b0e6a45c5", + "url": "https://api.github.com/repos/symfony/yaml/zipball/d819bf267e901727141fe828ae888486fd21236e", + "reference": "d819bf267e901727141fe828ae888486fd21236e", "shasum": "" }, "require": { @@ -2415,7 +2415,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2017-06-01 20:52:29" + "time": "2017-11-05T15:25:56+00:00" } ], "aliases": [], diff --git a/contrib/completion/bash/yii b/contrib/completion/bash/yii index 084325a..bc06b7a 100644 --- a/contrib/completion/bash/yii +++ b/contrib/completion/bash/yii @@ -15,6 +15,7 @@ _yii() local cur opts yii command COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" yii="${COMP_WORDS[0]}" # exit if ./yii does not exist @@ -31,9 +32,10 @@ _yii() [[ $cur == $command ]] && state="command" [[ $cur != $command ]] && state="option" [[ $cur = *=* ]] && state="value" + [[ $prev == "help" ]] && state="help" case $state in - command) + command|help) # complete command/route if not given # fetch available commands from ./yii help/list command opts=$($yii help/list 2> /dev/null) diff --git a/contrib/completion/zsh/_yii b/contrib/completion/zsh/_yii index e85ebc3..01f4765 100644 --- a/contrib/completion/zsh/_yii +++ b/contrib/completion/zsh/_yii @@ -3,6 +3,7 @@ _yii() { local state command lastArgument commands options executive lastArgument=${words[${#words[@]}]} + prevArgument=${words[${#words[@]}-1]} executive=$words[1] # lookup for command @@ -16,9 +17,10 @@ _yii() { [[ $lastArgument == $command ]] && state="command" [[ $lastArgument != $command ]] && state="option" + [[ $prevArgument == "help" ]] && state="help" case $state in - command) + command|help) commands=("${(@f)$(${executive} help/list 2>/dev/null)}") _describe 'command' commands ;; diff --git a/docs/guide-es/caching-data.md b/docs/guide-es/caching-data.md index 6280c4b..2c70061 100644 --- a/docs/guide-es/caching-data.md +++ b/docs/guide-es/caching-data.md @@ -79,8 +79,8 @@ se muestra un listado con los componentes de caché disponibles: * [[yii\caching\MemCache]]: utiliza las extensiones de PHP [memcache](http://php.net/manual/es/book.memcache.php) y [memcached](http://php.net/manual/es/book.memcached.php). Esta opción puede ser considerada como la más rápida cuando la caché es manejada en una aplicación distribuida (ej. con varios servidores, con balance de carga, etc..) * [[yii\redis\Cache]]: implementa un componente de caché basado en [Redis](http://redis.io/) que almacenan pares clave-valor (requiere la versión 2.6.12 de redis). * [[yii\caching\WinCache]]: utiliza la extensión de PHP [WinCache](http://iis.net/downloads/microsoft/wincache-extension) ([ver también](http://php.net/manual/es/book.wincache.php)). -* [[yii\caching\XCache]]: utiliza la extensión de PHP [XCache](http://xcache.lighttpd.net/). -* [[yii\caching\ZendDataCache]]: utiliza [Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm) como el medio fundamental de caché. +* [[yii\caching\XCache]] _(deprecated)_: utiliza la extensión de PHP [XCache](http://xcache.lighttpd.net/). +* [[yii\caching\ZendDataCache]] _(deprecated)_: utiliza [Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm) como el medio fundamental de caché. > Tip: Puedes utilizar diferentes tipos de almacenamiento de caché en la misma aplicación. Una estrategia común es la de usar almacenamiento de caché en memoria para almacenar datos que son pequeños pero que son utilizados constantemente (ej. datos estadísticos), y utilizar el almacenamiento de caché en archivos o en base de datos para guardar datos que son grandes y utilizados con menor frecuencia (ej. contenido de página). diff --git a/docs/guide-es/concept-di-container.md b/docs/guide-es/concept-di-container.md index 391de0a..e8d13fc 100644 --- a/docs/guide-es/concept-di-container.md +++ b/docs/guide-es/concept-di-container.md @@ -75,7 +75,7 @@ En este caso, el contenedor usará una llamada de retorno PHP registrada para co clase. La llamada de retorno se responsabiliza de que dependencias debe inyectar al nuevo objeto creado. Por ejemplo, ```php -$container->set('Foo', function () { +$container->set('Foo', function ($container, $params, $config) { return new Foo(new Bar); }); diff --git a/docs/guide-es/concept-events.md b/docs/guide-es/concept-events.md index 65ae841..2cce5cc 100644 --- a/docs/guide-es/concept-events.md +++ b/docs/guide-es/concept-events.md @@ -218,7 +218,7 @@ use yii\base\Event; use yii\db\ActiveRecord; Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) { - Yii::trace(get_class($event->sender) . ' is inserted'); + Yii::debug(get_class($event->sender) . ' is inserted'); }); ``` diff --git a/docs/guide-es/runtime-logging.md b/docs/guide-es/runtime-logging.md index a09ec93..bb01a21 100644 --- a/docs/guide-es/runtime-logging.md +++ b/docs/guide-es/runtime-logging.md @@ -20,7 +20,7 @@ En esta sección, se describirán principalmente los dos primeros pasos. Registrar mensajes de anotación es tan simple como llamar a uno de los siguientes métodos de registro de anotaciones. -* [[Yii::trace()]]: registra un mensaje para trazar el funcionamiento de una sección de código. Se usa principalmente +* [[Yii::debug()]]: registra un mensaje para trazar el funcionamiento de una sección de código. Se usa principalmente para tareas de desarrollo. * [[Yii::info()]]: registra un mensaje que transmite información útil. * [[Yii::warning()]]: registra un mensaje de advertencia que indica que ha sucedido algo inesperado. @@ -32,7 +32,7 @@ tiene que ser registrado, mientras que `$category` es la categoría del registro ejemplo registra la huella del mensaje para la categoría `application`: ```php -Yii::trace('start calculating average revenue'); +Yii::debug('start calculating average revenue'); ``` > Info: Los mensajes de registro pueden ser tanto cadenas de texto como datos complejos, como arrays u objetos. @@ -47,7 +47,7 @@ efectiva de organizarlos es usar la constante predefinida (magic constant) de PH categoría. Además este es el enfoque que se usa en el código del núcleo (core) del framework Yii. Por ejemplo, ```php -Yii::trace('start calculating average revenue', __METHOD__); +Yii::debug('start calculating average revenue', __METHOD__); ``` La constante `__METHOD__` equivale al nombre del método (con el prefijo del nombre completo del nombre de clase) donde @@ -131,7 +131,7 @@ La propiedad [[yii\log\Target::levels|levels]] es un array que consta de uno o v * `error`: correspondiente a los mensajes registrados por [[Yii::error()]]. * `warning`: correspondiente a los mensajes registrados por [[Yii::warning()]]. * `info`: correspondiente a los mensajes registrados por [[Yii::info()]]. -* `trace`: correspondiente a los mensajes registrados por [[Yii::trace()]]. +* `trace`: correspondiente a los mensajes registrados por [[Yii::debug()]]. * `profile`: correspondiente a los mensajes registrados por [[Yii::beginProfile()]] y [[Yii::endProfile()]], que se explicará más detalladamente en la subsección [Perfiles](#performance-profiling). @@ -290,7 +290,7 @@ número configurando la propiedad [[yii\log\Target::exportInterval|exportInterva ``` Debido al nivel de configuración de la liberación y exportación de mensajes, de forma predeterminada cuando se llama a -`Yii::trace()` o cualquier otro método de registro de mensajes, NO veremos el registro de mensaje inmediatamente en +`Yii::debug()` o cualquier otro método de registro de mensajes, NO veremos el registro de mensaje inmediatamente en los destinos de registros. Esto podría ser un problema para algunas aplicaciones de consola de ejecución prolongada (long-running). Para hacer que los mensajes de registro aparezcan inmediatamente en los destinos de registro se deben establecer [[yii\log\Dispatcher::flushInterval|flushInterval]] y diff --git a/docs/guide-es/start-installation.md b/docs/guide-es/start-installation.md index 62d0e5a..70a57e4 100644 --- a/docs/guide-es/start-installation.md +++ b/docs/guide-es/start-installation.md @@ -189,7 +189,7 @@ DocumentRoot "path/to/basic/web" Para utilizar [Nginx](http://wiki.nginx.org/), debes instalar PHP como un [FPM SAPI](http://php.net/install.fpm). Utiliza la siguiente configuración de Nginx, reemplazando `path/to/basic/web` con la ruta real a -`basic/web` y `mysite.local` con el hostname real a servir. +`basic/web` y `mysite.test` con el hostname real a servir. ``` server { @@ -199,7 +199,7 @@ server { listen 80; ## listen for ipv4 #listen [::]:80 default_server ipv6only=on; ## listen for ipv6 - server_name mysite.local; + server_name mysite.test; root /path/to/basic/web; index index.php; diff --git a/docs/guide-es/structure-filters.md b/docs/guide-es/structure-filters.md index 39b9158..a54ddc3 100644 --- a/docs/guide-es/structure-filters.md +++ b/docs/guide-es/structure-filters.md @@ -94,7 +94,7 @@ class ActionTimeFilter extends ActionFilter public function afterAction($action, $result) { $time = microtime(true) - $this->_startTime; - Yii::trace("Action '{$action->uniqueId}' spent $time second."); + Yii::debug("Action '{$action->uniqueId}' spent $time second."); return parent::afterAction($action, $result); } } diff --git a/docs/guide-fr/caching-data.md b/docs/guide-fr/caching-data.md index 6302394..41b8590 100644 --- a/docs/guide-fr/caching-data.md +++ b/docs/guide-fr/caching-data.md @@ -100,8 +100,8 @@ Yii prend en charge un large panel de supports de stockage pour cache. Ce qui su (une version de redis égale ou supérieure à 2.6.12 est nécessaire). * [[yii\caching\WinCache]]: utilise le [WinCache](http://iis.net/downloads/microsoft/wincache-extension) PHP ([voir aussi l'extension](http://php.net/manual/en/book.wincache.php)). -* [[yii\caching\XCache]]: utilise l'extension PHP [XCache](http://xcache.lighttpd.net/). -* [[yii\caching\ZendDataCache]]: utilise le +* [[yii\caching\XCache]] _(deprecated)_: utilise l'extension PHP [XCache](http://xcache.lighttpd.net/). +* [[yii\caching\ZendDataCache]] _(deprecated)_: utilise le [cache de données Zend](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm) en tant que médium de cache sous-jacent. diff --git a/docs/guide-fr/concept-di-container.md b/docs/guide-fr/concept-di-container.md index 06af821..0aeb060 100644 --- a/docs/guide-fr/concept-di-container.md +++ b/docs/guide-fr/concept-di-container.md @@ -99,7 +99,7 @@ $container->get('Foo', [], [ Dans ce cas, le conteneur utilise une fonction de rappel PRP enregistrée pour construire de nouvelles instances d'une classe. À chaque fois que [[yii\di\Container::get()]] est appelée, la fonction de rappel correspondante est invoquée. Cette fonction de rappel est chargée de la résolution des dépendances et de leur injection appropriée dans les objets nouvellement créés. Par exemple : ```php -$container->set('Foo', function () { +$container->set('Foo', function ($container, $params, $config) { $foo = new Foo(new Bar); // ... autres initialisations ... return $foo; @@ -113,7 +113,7 @@ Pour cacher la logique complexe de construction des nouveaux objets, vous pouvez ```php class FooBuilder { - public static function build() + public static function build($container, $params, $config) { $foo = new Foo(new Bar); // ... autres initialisations ... diff --git a/docs/guide-fr/concept-events.md b/docs/guide-fr/concept-events.md index d88d514..3d3afcc 100644 --- a/docs/guide-fr/concept-events.md +++ b/docs/guide-fr/concept-events.md @@ -186,7 +186,7 @@ use yii\base\Event; use yii\db\ActiveRecord; Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) { - Yii::trace(get_class($event->sender) . ' is inserted'); + Yii::debug(get_class($event->sender) . ' is inserted'); }); ``` @@ -263,7 +263,7 @@ Pour gérer l'évenement `EVENT_DANCE` déclenché par n'importe laquelle de ces ```php Event::on('app\interfaces\DanceEventInterface', DanceEventInterface::EVENT_DANCE, function ($event) { - Yii::trace(get_class($event->sender) . ' just danced'); // Will log that Dog or Developer danced + Yii::debug(get_class($event->sender) . ' just danced'); // Will log that Dog or Developer danced }); ``` diff --git a/docs/guide-fr/runtime-logging.md b/docs/guide-fr/runtime-logging.md index bb0896a..8cd79ce 100644 --- a/docs/guide-fr/runtime-logging.md +++ b/docs/guide-fr/runtime-logging.md @@ -16,7 +16,7 @@ Dans cette section, nous décrivons principalement les deux premières étapes. Enregistrer des messages est aussi simple que d'appeler une des méthodes suivantes : -* [[Yii::trace()]]: enregistre un message pour garder une trace de comment un morceau de code fonctionne. Cela est utilisé principalement en développement. +* [[Yii::debug()]]: enregistre un message pour garder une trace de comment un morceau de code fonctionne. Cela est utilisé principalement en développement. * [[Yii::info()]]: enregistre un message qui contient quelques informations utiles. * [[Yii::warning()]]: enregistre un message d'avertissement qui indique que quelque chose d'inattendu s'est produit. * [[Yii::error()]]: enregistre une erreur fatale qui doit être analysée dès que possible. @@ -24,7 +24,7 @@ Enregistrer des messages est aussi simple que d'appeler une des méthodes suivan Ces méthodes enregistrent les messages à différents niveaux de sévérité et dans différentes catégories. Elles partagent la même signature `function ($message, $category = 'application')`, où `$message` représente le message à enregistrer, tandis que `$category` est la catégorie de ce message. Le code de l'exemple qui suit enregistre un message de trace dans la catégorie `application`: ```php -Yii::trace('start calculating average revenue'); +Yii::debug('start calculating average revenue'); ``` > Info: les messages enregistrés peuvent être des chaînes de caractères aussi bien que des données complexes telles que des tableaux ou des objets. Il est de la responsabilité des [cibles d'enregistrement](#log-targets) de traiter correctement ces messages. Par défaut, si un message enregistré n'est pas un chaîne de caractères, il est exporté comme une chaîne de caractères en appelant la méthode [[yii\helpers\VarDumper::export()]]. @@ -32,7 +32,7 @@ Yii::trace('start calculating average revenue'); Pour mieux organiser et filtrer les messages enregistrés, il est recommandé que vous spécifiiez une catégorie appropriée pour chacun des messages. Vous pouvez choisir une schéma de nommage hiérarchisé pour les catégories, ce qui facilitera le filtrage des messages par les [cibles d'enregistrement](#log-targets) sur la base de ces catégories. Un schéma de nommage simple et efficace est d'utiliser la constante magique `__METHOD__` de PHP dans les noms de catégorie. Par exemple : ```php -Yii::trace('start calculating average revenue', __METHOD__); +Yii::debug('start calculating average revenue', __METHOD__); ``` La constante magique `__METHOD__` est évaluée comme le nom de la méthode (préfixée par le nom pleinement qualifié de la classe), là où la constante apparaît. Par exemple, elle est égale à `'app\controllers\RevenueController::calculate'` si la ligne suivante est utilisée dans cette méthode. @@ -100,7 +100,7 @@ La propriété [[yii\log\Target::levels|levels]] accepte un tableau constitué d * `error`: correspondant aux messages enregistrés par [[Yii::error()]]. * `warning`: correspondant aux messages enregistrés par [[Yii::warning()]]. * `info`: correspondant aux messages enregistrés par [[Yii::info()]]. -* `trace`: correspondant aux messages enregistrés par [[Yii::trace()]]. +* `trace`: correspondant aux messages enregistrés par [[Yii::debug()]]. * `profile`: correspondant aux messages enregistrés par [[Yii::beginProfile()]] et [[Yii::endProfile()]], et qui sera expliqué en détails dans la sous-section [Profilage de la performance](#performance-profiling). Si vous ne spécifiez pas la propriété [[yii\log\Target::levels|levels]], cela signifie que la cible traitera les messages de *n'importe quel* niveau de sévérité. @@ -222,7 +222,7 @@ Lorsque l'[[yii\log\Logger|objet *logger*]] purge les messages enregistrés vers ] ``` -À cause des niveaux de purge et d'exportation, par défaut, lorsque vous appelez `Yii::trace()` ou toute autre méthode d'enregistrement, vous ne voyez PAS immédiatement le message enregistré dans la cible. Cela peut représenter un problème pour pour certaines applications de console qui durent longtemps. Pour faire en sorte que les messages apparaissent immédiatement dans les cibles d'enregistrement, vous devriez définir les propriétés [[yii\log\Dispatcher::flushInterval|flushInterval]] et [[yii\log\Target::exportInterval|exportInterval]] toutes deux à 1, comme montré ci-après : +À cause des niveaux de purge et d'exportation, par défaut, lorsque vous appelez `Yii::debug()` ou toute autre méthode d'enregistrement, vous ne voyez PAS immédiatement le message enregistré dans la cible. Cela peut représenter un problème pour pour certaines applications de console qui durent longtemps. Pour faire en sorte que les messages apparaissent immédiatement dans les cibles d'enregistrement, vous devriez définir les propriétés [[yii\log\Dispatcher::flushInterval|flushInterval]] et [[yii\log\Target::exportInterval|exportInterval]] toutes deux à 1, comme montré ci-après : ```php return [ diff --git a/docs/guide-fr/start-installation.md b/docs/guide-fr/start-installation.md index 24a1c49..fa36149 100644 --- a/docs/guide-fr/start-installation.md +++ b/docs/guide-fr/start-installation.md @@ -120,7 +120,7 @@ DocumentRoot "path/to/basic/web" ### Configuration Nginx recommandée Pour utiliser Nginx, vous devez avoir installé PHP en utilisant [FPM SAPI](http://php.net/install.fpm). -Utilisez la configuration Nginx suivante, en remplaçant `path/to/basic/web` par le chemin vers le dossier `basic/web` et `mysite.local` par le nom d'hôte de votre serveur. +Utilisez la configuration Nginx suivante, en remplaçant `path/to/basic/web` par le chemin vers le dossier `basic/web` et `mysite.test` par le nom d'hôte de votre serveur. ``` server { @@ -130,7 +130,7 @@ server { listen 80; ## port pour ipv4 #listen [::]:80 default_server ipv6only=on; ## port pour ipv6 - server_name mysite.local; + server_name mysite.test; root /path/to/basic/web; index index.php; diff --git a/docs/guide-fr/structure-filters.md b/docs/guide-fr/structure-filters.md index b6b897d..e198d35 100644 --- a/docs/guide-fr/structure-filters.md +++ b/docs/guide-fr/structure-filters.md @@ -72,7 +72,7 @@ class ActionTimeFilter extends ActionFilter public function afterAction($action, $result) { $time = microtime(true) - $this->_startTime; - Yii::trace("Action '{$action->uniqueId}' spent $time second."); + Yii::debug("Action '{$action->uniqueId}' spent $time second."); return parent::afterAction($action, $result); } } diff --git a/docs/guide-fr/tutorial-i18n.md b/docs/guide-fr/tutorial-i18n.md index 147a93e..6929531 100644 --- a/docs/guide-fr/tutorial-i18n.md +++ b/docs/guide-fr/tutorial-i18n.md @@ -327,7 +327,7 @@ tandis que `one` correspond à `21` ou `101`: ``` Ces noms d'arguments spéciaux tels que `other`, `few`, `many` et autres varient en fonction de la langue. Pour savoir lesquels utiliser pour une locale particulière, reportez-vous aux "Plural Rules, Cardinal" à [http://intl.rmcreative.ru/](http://intl.rmcreative.ru/). -En alternative, vous pouvez vous reporter aux [rules reference at unicode.org](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html). +En alternative, vous pouvez vous reporter aux [rules reference at unicode.org](http://cldr.unicode.org/index/cldr-spec/plural-rules). > Note: le message en russe ci-dessus est principalement utilisé comme message traduit, pas comme message source, sauf si vous définissez la [[yii\base\Application::$sourceLanguage|langue source]] de votre application comme étant `ru-RU` et traduisez à partir du russe. > diff --git a/docs/guide-id/start-installation.md b/docs/guide-id/start-installation.md index 6fce5c4..54fb407 100644 --- a/docs/guide-id/start-installation.md +++ b/docs/guide-id/start-installation.md @@ -189,7 +189,7 @@ DocumentRoot "path/to/basic/web" Untuk menggunakan [Nginx](http://wiki.nginx.org/), Anda harus menginstal PHP sebagai [FPM SAPI](http://php.net/install.fpm). Anda dapat menggunakan konfigurasi Nginx berikut, menggantikan `path/to/basic/web` dengan path yang sebenarnya untuk -`basic/web` dan `mysite.local` dengan hostname yang sebenarnya untuk server. +`basic/web` dan `mysite.test` dengan hostname yang sebenarnya untuk server. ```nginx server { @@ -199,7 +199,7 @@ server { listen 80; ## listen for ipv4 #listen [::]:80 default_server ipv6only=on; ## listen for ipv6 - server_name mysite.local; + server_name mysite.test; root /path/to/basic/web; index index.php; diff --git a/docs/guide-it/start-installation.md b/docs/guide-it/start-installation.md index 1bfb50c..7315f29 100644 --- a/docs/guide-it/start-installation.md +++ b/docs/guide-it/start-installation.md @@ -161,7 +161,7 @@ DocumentRoot "path/to/basic/web" ### Configurazione consigliata di Nginx Devi aver installato PHP con il demone [FPM](http://php.net/install.fpm) per usare [Nginx](http://wiki.nginx.org/). -Usa questa configurazione per Nginx, sostituendo `path/to/basic/web` con il percorso reale di `basic/web` e `mysite.local` con +Usa questa configurazione per Nginx, sostituendo `path/to/basic/web` con il percorso reale di `basic/web` e `mysite.test` con il nome reale del server web. ``` @@ -172,7 +172,7 @@ server { listen 80; ## listen for ipv4 #listen [::]:80 default_server ipv6only=on; ## listen for ipv6 - server_name mysite.local; + server_name mysite.test; root /path/to/basic/web; index index.php; diff --git a/docs/guide-ja/caching-data.md b/docs/guide-ja/caching-data.md index 6149dba..473b468 100644 --- a/docs/guide-ja/caching-data.md +++ b/docs/guide-ja/caching-data.md @@ -111,8 +111,8 @@ Yii はさまざまなキャッシュストレージをサポートしていま 分散型のアプリケーションでキャッシュを扱うときには最速の一つとして考えることができます (例えば、複数台のサーバで、ロードバランサがある、などの場合) 。 * [[yii\redis\Cache]]: [Redis](http://redis.io/) の key-value ストアに基づいてキャッシュコンポーネントを実装しています。(Redis の バージョン 2.6.12 以降が必要です) 。 * [[yii\caching\WinCache]]: PHP の [WinCache](http://iis.net/downloads/microsoft/wincache-extension) ([関連リンク](http://php.net/manual/ja/book.wincache.php)) 拡張モジュールを使用します。 -* [[yii\caching\XCache]]: PHP の [XCache](http://xcache.lighttpd.net/) 拡張モジュールを使用します。 -* [[yii\caching\ZendDataCache]]: キャッシュメディアして [Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm) を使用します。 +* [[yii\caching\XCache]] _(deprecated)_: PHP の [XCache](http://xcache.lighttpd.net/) 拡張モジュールを使用します。 +* [[yii\caching\ZendDataCache]] _(deprecated)_: キャッシュメディアして [Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm) を使用します。 > Tip: 同じアプリケーション内で異なるキャッシュを使用することもできます。一般的なやり方として、小さくとも常に使用されるデータ (例えば、統計データ) を格納する場合はメモリベースのキャッシュストレージを使用し、大きくて使用頻度の低いデータ (例えば、ページコンテント) を格納する場合はファイルベース、またはデータベースのキャッシュストレージを使用します 。 diff --git a/docs/guide-ja/concept-di-container.md b/docs/guide-ja/concept-di-container.md index ea85c0a..6a76670 100644 --- a/docs/guide-ja/concept-di-container.md +++ b/docs/guide-ja/concept-di-container.md @@ -114,7 +114,7 @@ $container->get('Foo', [], [ たとえば ```php -$container->set('Foo', function () { +$container->set('Foo', function ($container, $params, $config) { $foo = new Foo(new Bar); // ... その他の初期化 ... return $foo; @@ -129,7 +129,7 @@ $foo = $container->get('Foo'); ```php class FooBuilder { - public static function build() + public static function build($container, $params, $config) { $foo = new Foo(new Bar); // ... その他の初期化 ... @@ -413,7 +413,7 @@ $container->setDefinitions([ 'class' => 'app\components\Response', 'format' => 'json' ], - 'app\storage\DocumentsReader' => function () { + 'app\storage\DocumentsReader' => function ($container, $params, $config) { $fs = new app\storage\FileStorage('/var/tempfiles'); return new app\storage\DocumentsReader($fs); } diff --git a/docs/guide-ja/concept-events.md b/docs/guide-ja/concept-events.md index 2422d55..1cbe19a 100644 --- a/docs/guide-ja/concept-events.md +++ b/docs/guide-ja/concept-events.md @@ -209,7 +209,7 @@ use yii\base\Event; use yii\db\ActiveRecord; Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) { - Yii::trace(get_class($event->sender) . ' が挿入されました'); + Yii::debug(get_class($event->sender) . ' が挿入されました'); }); ``` @@ -292,7 +292,7 @@ class Developer extends Component implements DanceEventInterface ```php Event::on('app\interfaces\DanceEventInterface', DanceEventInterface::EVENT_DANCE, function ($event) { - Yii::trace(get_class($event->sender) . ' が躍り上がって喜んだ。'); // 犬または開発者が躍り上がって喜んだことをログに記録。 + Yii::debug(get_class($event->sender) . ' が躍り上がって喜んだ。'); // 犬または開発者が躍り上がって喜んだことをログに記録。 }); ``` diff --git a/docs/guide-ja/runtime-logging.md b/docs/guide-ja/runtime-logging.md index f644b63..5a4f308 100644 --- a/docs/guide-ja/runtime-logging.md +++ b/docs/guide-ja/runtime-logging.md @@ -17,7 +17,7 @@ Yii のロギングフレームワークを使うためには、下記のステ ログメッセージを記録することは、次のログ記録メソッドのどれかを呼び出すだけの簡単なことです。 -* [[Yii::trace()]]: コードの断片がどのように走ったかをトレースするメッセージを記録します。主として開発のために使用します。 +* [[Yii::debug()]]: コードの断片がどのように走ったかをトレースするメッセージを記録します。主として開発のために使用します。 * [[Yii::info()]]: 何らかの有用な情報を伝えるメッセージを記録します。 * [[Yii::warning()]]: 何か予期しないことが発生したことを示す警告メッセージを記録します。 * [[Yii::error()]]: 出来るだけ早急に調査すべき致命的なエラーを記録します。 @@ -27,7 +27,7 @@ Yii のロギングフレームワークを使うためには、下記のステ 次のコードサンプルは、トレースメッセージをデフォルトのカテゴリである `application` の下に記録するものです。 ```php -Yii::trace('平均収益の計算を開始'); +Yii::debug('平均収益の計算を開始'); ``` > Info: ログメッセージは文字列でも、配列やオブジェクトのような複雑なデータでも構いません。 @@ -40,7 +40,7 @@ Yii::trace('平均収益の計算を開始'); これは、Yii フレームワークのコアコードでも使われている方法です。例えば、 ```php -Yii::trace('平均収益の計算を開始', __METHOD__); +Yii::debug('平均収益の計算を開始', __METHOD__); ``` `__METHOD__` という定数は、それが出現する場所のメソッド名 (完全修飾のクラス名が前置されます) として評価されます。 @@ -116,7 +116,7 @@ Yii は下記のログターゲットをあらかじめ内蔵しています。 * `error`: [[Yii::error()]] によって記録されたメッセージに対応。 * `warning`: [[Yii::warning()]] によって記録されたメッセージに対応。 * `info`: [[Yii::info()]] によって記録されたメッセージに対応。 -* `trace`: [[Yii::trace()]] によって記録されたメッセージに対応。 +* `trace`: [[Yii::debug()]] によって記録されたメッセージに対応。 * `profile`: [[Yii::beginProfile()]] と [[Yii::endProfile()]] によって記録されたメッセージに対応。 これについては、[プロファイリング](#performance-profiling) の項で詳細に説明します。 @@ -255,7 +255,7 @@ return [ ] ``` -デフォルトの状態では、吐き出しとエクスポートの間隔の設定のために、`Yii::trace()` やその他のログ記録メソッドを呼んでも、ただちには、ログメッセージはログターゲットに出現しません。 +デフォルトの状態では、吐き出しとエクスポートの間隔の設定のために、`Yii::debug()` やその他のログ記録メソッドを呼んでも、ただちには、ログメッセージはログターゲットに出現しません。 このことは、長時間にわたって走るコンソールアプリケーションでは、問題になる場合もあります。 各ログメッセージがただちにログターゲットに出現するようにするためには、下記のように、[[yii\log\Dispatcher::flushInterval|flushInterval]] と [[yii\log\Target::exportInterval|exportInterval]] の両方を 1 に設定しなければなりません。 diff --git a/docs/guide-ja/start-installation.md b/docs/guide-ja/start-installation.md index 917ad5f..f9a07d6 100644 --- a/docs/guide-ja/start-installation.md +++ b/docs/guide-ja/start-installation.md @@ -202,7 +202,7 @@ DocumentRoot "path/to/basic/web" [Nginx](http://wiki.nginx.org/) を使うためには、PHP を [FPM SAPI](http://jp1.php.net/install.fpm) としてインストールしなければなりません。 下記の Nginx の設定を使うことができます。 -`path/to/basic/web` の部分を `basic/web` の実際のパスに置き換え、`mysite.local` を実際のサーバのホスト名に置き換えてください。 +`path/to/basic/web` の部分を `basic/web` の実際のパスに置き換え、`mysite.test` を実際のサーバのホスト名に置き換えてください。 ```nginx server { @@ -212,7 +212,7 @@ server { listen 80; ## listen for ipv4 #listen [::]:80 default_server ipv6only=on; ## listen for ipv6 - server_name mysite.local; + server_name mysite.test; root /path/to/basic/web; index index.php; diff --git a/docs/guide-ja/structure-filters.md b/docs/guide-ja/structure-filters.md index 890b1b2..4b69260 100644 --- a/docs/guide-ja/structure-filters.md +++ b/docs/guide-ja/structure-filters.md @@ -83,7 +83,7 @@ class ActionTimeFilter extends ActionFilter public function afterAction($action, $result) { $time = microtime(true) - $this->_startTime; - Yii::trace("アクション '{$action->uniqueId}' は $time 秒を消費。"); + Yii::debug("アクション '{$action->uniqueId}' は $time 秒を消費。"); return parent::afterAction($action, $result); } } diff --git a/docs/guide-ja/tutorial-i18n.md b/docs/guide-ja/tutorial-i18n.md index 81a1397..809d46f 100644 --- a/docs/guide-ja/tutorial-i18n.md +++ b/docs/guide-ja/tutorial-i18n.md @@ -459,7 +459,7 @@ echo \Yii::t('app', 'There {n,plural,=0{are no cats} =1{is one cat} other{are # これら `other`、`few`、`many` などの特別な引数の名前は言語によって異なります。 特定のロケールに対してどんな引数を指定すべきかを学ぶためには、[http://intl.rmcreative.ru/](http://intl.rmcreative.ru/) の "Plural Rules, Cardinal" を参照してください。 -あるいは、その代りに、[unicode.org の規則のリファレンス](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html) を参照することも出来ます。 +あるいは、その代りに、[unicode.org の規則のリファレンス](http://cldr.unicode.org/index/cldr-spec/plural-rules) を参照することも出来ます。 > Note: 上記のロシア語のメッセージのサンプルは、主として翻訳メッセージとして使用されるものです。 diff --git a/docs/guide-pl/start-installation.md b/docs/guide-pl/start-installation.md index bbb122d..c11aac4 100644 --- a/docs/guide-pl/start-installation.md +++ b/docs/guide-pl/start-installation.md @@ -203,7 +203,7 @@ DocumentRoot "path/to/basic/web" Aby użyć [Nginx](http://wiki.nginx.org/) powinienieś zainstalować PHP jako [FPM SAPI](http://php.net/install.fpm). Możesz użyć przedstawionej poniżej konfiguracji Nginx, zastępując jedynie ścieżkę `path/to/basic/web` aktualną ścieżką do `basic/web` Twojej aplikacji oraz -`mysite.local` aktualną nazwą hosta. +`mysite.test` aktualną nazwą hosta. ```nginx server { @@ -213,7 +213,7 @@ server { listen 80; ## nasłuchuj ipv4 #listen [::]:80 default_server ipv6only=on; ## nasłuchuj ipv6 - server_name mysite.local; + server_name mysite.test; root /path/to/basic/web; index index.php; diff --git a/docs/guide-pt-BR/caching-data.md b/docs/guide-pt-BR/caching-data.md index aec00ba..05c7c60 100644 --- a/docs/guide-pt-BR/caching-data.md +++ b/docs/guide-pt-BR/caching-data.md @@ -96,8 +96,8 @@ Yii suporta uma ampla gama de sistemas de cache. A seguir um resumo: [Redis](http://redis.io/) (requer redis versão 2.6.12 ou mais recente). * [[yii\caching\WinCache]]: usa a extensão PHP [WinCache](http://iis.net/downloads/microsoft/wincache-extension) ([veja também](http://php.net/manual/en/book.wincache.php)). -* [[yii\caching\XCache]]: usa a extensão PHP [XCache](http://xcache.lighttpd.net/). -* [[yii\caching\ZendDataCache]]: usa +* [[yii\caching\XCache]] _(deprecated)_: usa a extensão PHP [XCache](http://xcache.lighttpd.net/). +* [[yii\caching\ZendDataCache]] _(deprecated)_: usa [Cache de Dados Zend](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm) como o meio de cache subjacente. diff --git a/docs/guide-pt-BR/concept-di-container.md b/docs/guide-pt-BR/concept-di-container.md index f0b0739..cb511ae 100644 --- a/docs/guide-pt-BR/concept-di-container.md +++ b/docs/guide-pt-BR/concept-di-container.md @@ -75,7 +75,7 @@ Cada vez que [[yii\di\Container::get()]] for chamado, o callable correspondente O callable é responsável por resolver as dependências e injetá-las de forma adequada para os objetos recém-criados. Por exemplo: ```php -$container->set('Foo', function () { +$container->set('Foo', function ($container, $params, $config) { $foo = new Foo(new Bar); // ... Outras inicializações... return $foo; @@ -89,7 +89,7 @@ Para ocultar a lógica complexa da construção de um novo objeto você pode usa ```php class FooBuilder { - public static function build() + public static function build($container, $params, $config) { return function () { $foo = new Foo(new Bar); diff --git a/docs/guide-pt-BR/concept-events.md b/docs/guide-pt-BR/concept-events.md index a9be2a0..e126c98 100644 --- a/docs/guide-pt-BR/concept-events.md +++ b/docs/guide-pt-BR/concept-events.md @@ -192,7 +192,7 @@ use yii\base\Event; use yii\db\ActiveRecord; Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) { - Yii::trace(get_class($event->sender) . ' is inserted'); + Yii::debug(get_class($event->sender) . ' is inserted'); }); ``` diff --git a/docs/guide-pt-BR/runtime-logging.md b/docs/guide-pt-BR/runtime-logging.md index d487244..555df02 100644 --- a/docs/guide-pt-BR/runtime-logging.md +++ b/docs/guide-pt-BR/runtime-logging.md @@ -16,7 +16,7 @@ Nesta seção, vamos descrever principalmente os dois primeiros passos. Gravar mensagens de log é tão simples como chamar um dos seguintes métodos de registro: -* [[Yii::trace()]]: gravar uma mensagem para rastrear como um determinado trecho de código é executado. Isso é principalmente para o uso de desenvolvimento. +* [[Yii::debug()]]: gravar uma mensagem para rastrear como um determinado trecho de código é executado. Isso é principalmente para o uso de desenvolvimento. * [[Yii::info()]]: gravar uma mensagem que transmite algumas informações úteis. * [[Yii::warning()]]: gravar uma mensagem de aviso que indica que algo inesperado aconteceu. * [[Yii::error()]]: gravar um erro fatal que deve ser investigado o mais rápido possível. @@ -24,7 +24,7 @@ Gravar mensagens de log é tão simples como chamar um dos seguintes métodos de Estes métodos gravam mensagens de log em vários *níveis* e *categorias*. Eles compartilham a mesma assinatura de função `function ($message, $category = 'application')`, onde `$message` significa a mensagem de log a ser gravada, enquanto `$category` é a categoria da mensagem de log. O código no exemplo a seguir registra uma mensagem de rastreamento sob a categoria padrão `application`: ```php -Yii::trace('start calculating average revenue'); +Yii::debug('start calculating average revenue'); ``` > Observação: Mensagens de log podem ser strings, bem como dados complexos, tais como arrays ou objetos. É da responsabilidade dos [destinos de log](#log-targets) lidar adequadamente com as mensagens de log. Por padrão, se uma mensagem de log não for uma string, ela será exportada como uma string chamando [[yii\helpers\VarDumper::export()]]. @@ -32,7 +32,7 @@ Yii::trace('start calculating average revenue'); Para melhor organizar e filtrar as mensagens de log, é recomendável que você especifique uma categoria apropriada para cada mensagem de log. Você pode escolher um esquema de nomenclatura hierárquica para as categorias, o que tornará mais fácil para os [destinos de log](#log-targets) filtrar mensagens com base em suas categorias. Um esquema de nomes simples, mas eficaz é usar a constante mágica PHP `__METHOD__` para os nomes das categorias. Esta é também a abordagem utilizada no código central do framework Yii. Por exemplo, ```php -Yii::trace('start calculating average revenue', __METHOD__); +Yii::debug('start calculating average revenue', __METHOD__); ``` A constante `__METHOD__` corresponde ao nome do método (prefixado com o caminho completo do nome da classe) onde a constante aparece. Por exemplo, é igual a string `'app\controllers\RevenueController::calculate'` se o código acima for chamado dentro deste método. @@ -100,7 +100,7 @@ A propriedade [[yii\log\Target::levels|levels]] é um array que consiste em um o * `error`: corresponde a mensagens logadas por [[Yii::error()]]. * `warning`: corresponde a mensagens logadas por [[Yii::warning()]]. * `info`: corresponde a mensagens logadas por [[Yii::info()]]. -* `trace`: corresponde a mensagens logadas por [[Yii::trace()]]. +* `trace`: corresponde a mensagens logadas por [[Yii::debug()]]. * `profile`: corresponde a mensagens logadas por [[Yii::beginProfile()]] e [[Yii::endProfile()]], que será explicado em mais detalhes na subseção [Perfil de Desempenho](#performance-profiling). Se você não especificar a propriedade [[yii\log\Target::levels|levels]], significa que o alvo de log processará mensagens de *qualquer* nível. @@ -218,7 +218,7 @@ Quando o [[yii\log\Logger|logger object]] libera mensagens de log para os [alvos ] ``` -Devido a configuração de nível, liberação e exportação, por padrão quando você chama `Yii::trace()` ou qualquer outro método de log, você NÃO verá a mensagem de log imediatamente no destino. Isto poderia ser um problema para algumas aplicações console de longa execução. Para fazer cada mensagem de log aparecer imediatamente no destino, você deve configurar ambos [[yii\log\Dispatcher::flushInterval|flushInterval]] e [[yii\log\Target::exportInterval|exportInterval]] para 1, como mostrado a seguir: +Devido a configuração de nível, liberação e exportação, por padrão quando você chama `Yii::debug()` ou qualquer outro método de log, você NÃO verá a mensagem de log imediatamente no destino. Isto poderia ser um problema para algumas aplicações console de longa execução. Para fazer cada mensagem de log aparecer imediatamente no destino, você deve configurar ambos [[yii\log\Dispatcher::flushInterval|flushInterval]] e [[yii\log\Target::exportInterval|exportInterval]] para 1, como mostrado a seguir: ```php return [ diff --git a/docs/guide-pt-BR/start-installation.md b/docs/guide-pt-BR/start-installation.md index 8023e63..e210981 100644 --- a/docs/guide-pt-BR/start-installation.md +++ b/docs/guide-pt-BR/start-installation.md @@ -202,7 +202,7 @@ DocumentRoot "path/to/basic/web" Você deve ter instalado o PHP como um [FPM SAPI](http://php.net/install.fpm) para usar o [Nginx](http://wiki.nginx.org/). Use a seguinte configuração do Nginx, -substituindo `path/to/basic/web` com o caminho real para `basic/web` e `mysite.local` +substituindo `path/to/basic/web` com o caminho real para `basic/web` e `mysite.test` com o nome de host real a servidor. ``` @@ -213,7 +213,7 @@ server { listen 80; ## listen for ipv4 #listen [::]:80 default_server ipv6only=on; ## listen for ipv6 - server_name mysite.local; + server_name mysite.test; root /path/to/basic/web; index index.php; diff --git a/docs/guide-pt-BR/structure-filters.md b/docs/guide-pt-BR/structure-filters.md index 49533a8..409f213 100644 --- a/docs/guide-pt-BR/structure-filters.md +++ b/docs/guide-pt-BR/structure-filters.md @@ -105,7 +105,7 @@ class ActionTimeFilter extends ActionFilter public function afterAction($action, $result) { $time = microtime(true) - $this->_startTime; - Yii::trace("Action '{$action->uniqueId}' spent $time second."); + Yii::debug("Action '{$action->uniqueId}' spent $time second."); return parent::afterAction($action, $result); } } diff --git a/docs/guide-ru/README.md b/docs/guide-ru/README.md index 61c06c8..99d4ff3 100644 --- a/docs/guide-ru/README.md +++ b/docs/guide-ru/README.md @@ -79,7 +79,7 @@ All Rights Reserved. * [Active Record](db-active-record.md) - Получение объектов AR, работа с ними и определение связей. * [Миграции](db-migrations.md) - Контроль версий схемы данных при работе в команде. * [Sphinx](https://github.com/yiisoft/yii2-sphinx/blob/master/docs/guide-ru/README.md) -* [Redis](https://github.com/yiisoft/yii2-redis/blob/master/docs/guide/README.md) +* [Redis](https://github.com/yiisoft/yii2-redis/blob/master/docs/guide-ru/README.md) * [MongoDB](https://github.com/yiisoft/yii2-mongodb/blob/master/docs/guide-ru/README.md) * [ElasticSearch](https://github.com/yiisoft/yii2-elasticsearch/blob/master/docs/guide/README.md) @@ -175,6 +175,7 @@ All Rights Reserved. * [Окружение виртуального хостинга](tutorial-shared-hosting.md) * [Шаблонизаторы](tutorial-template-engines.md) * [Работа со сторонним кодом](tutorial-yii-integration.md) +* [Использование Yii в качестве микро-framework'а](tutorial-yii-as-micro-framework.md) Виджеты diff --git a/docs/guide-ru/caching-data.md b/docs/guide-ru/caching-data.md index f6fb13c..4a65bb1 100644 --- a/docs/guide-ru/caching-data.md +++ b/docs/guide-ru/caching-data.md @@ -102,8 +102,8 @@ Yii поддерживает множество хранилищ кэша: * [[yii\caching\MemCache]]: использует расширения PHP [memcache](http://php.net/manual/en/book.memcache.php) и [memcached](http://php.net/manual/en/book.memcached.php). Этот вариант может рассматриваться как самый быстрый при работе в распределенных приложениях (например, с несколькими серверами, балансировкой нагрузки и так далее); * [[yii\redis\Cache]]: реализует компонент кэша на основе [Redis](http://redis.io/), хранилища ключ-значение (требуется Redis версии 2.6.12 или выше); * [[yii\caching\WinCache]]: использует расширение PHP [WinCache](http://iis.net/downloads/microsoft/wincache-extension) ([смотрите также](http://php.net/manual/en/book.wincache.php)); -* [[yii\caching\XCache]]: использует расширение PHP [XCache](http://xcache.lighttpd.net/); -* [[yii\caching\ZendDataCache]]: использует [Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm). +* [[yii\caching\XCache]] _(deprecated)_: использует расширение PHP [XCache](http://xcache.lighttpd.net/); +* [[yii\caching\ZendDataCache]] _(deprecated)_: использует [Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm). > Tip: Вы можете использовать разные способы хранения кэша в одном приложении. Общая стратегия заключается в использовании памяти под хранение небольших часто используемых данных (например, статистические данные). Для больших и реже используемых данных (например, содержимое страницы) лучше использовать файлы или базу данных. diff --git a/docs/guide-ru/concept-di-container.md b/docs/guide-ru/concept-di-container.md index aaaa3ad..07d083f 100644 --- a/docs/guide-ru/concept-di-container.md +++ b/docs/guide-ru/concept-di-container.md @@ -151,7 +151,7 @@ $container->setDefinitions([ 'class' => 'app\components\Response', 'format' => 'json' ], - 'app\storage\DocumentsReader' => function () { + 'app\storage\DocumentsReader' => function ($container, $params, $config) { $fs = new app\storage\FileStorage('/var/tempfiles'); return new app\storage\DocumentsReader($fs); } @@ -243,7 +243,7 @@ $reader = $container->get('app\storage\DocumentsReader'); Callback отвечает за разрешения зависимостей и внедряет их в соответствии с вновь создаваемыми объектами. Например, ```php -$container->set('Foo', function () { +$container->set('Foo', function ($container, $params, $config) { $foo = new Foo(new Bar); // ... дополнительная инициализация return $foo; @@ -258,7 +258,7 @@ callable: ```php class FooBuilder { - public static function build() + public static function build($container, $params, $config) { $foo = new Foo(new Bar); // ... дополнительная инициализация ... diff --git a/docs/guide-ru/concept-events.md b/docs/guide-ru/concept-events.md index acff9b7..12d01ab 100644 --- a/docs/guide-ru/concept-events.md +++ b/docs/guide-ru/concept-events.md @@ -188,7 +188,7 @@ use yii\base\Event; use yii\db\ActiveRecord; Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) { - Yii::trace(get_class($event->sender) . ' добавлен'); + Yii::debug(get_class($event->sender) . ' добавлен'); }); ``` @@ -266,7 +266,7 @@ class Developer extends Component implements DanceEventInterface ```php Event::on('app\interfaces\DanceEventInterface', DanceEventInterface::EVENT_DANCE, function ($event) { - Yii::trace(get_class($event->sender) . ' just danced'); // Оставит запись в журнале о том, что кто-то танцевал + Yii::debug(get_class($event->sender) . ' just danced'); // Оставит запись в журнале о том, что кто-то танцевал }); ``` diff --git a/docs/guide-ru/db-migrations.md b/docs/guide-ru/db-migrations.md index a55e00c..69ec182 100644 --- a/docs/guide-ru/db-migrations.md +++ b/docs/guide-ru/db-migrations.md @@ -266,7 +266,7 @@ yii migrate/create create_post_table --fields="author_id:integer:notNull:foreign class m160328_040430_create_post_table extends Migration { /** - * @inheritdoc + * {@inheritdoc} */ public function up() { @@ -314,7 +314,7 @@ class m160328_040430_create_post_table extends Migration } /** - * @inheritdoc + * {@inheritdoc} */ public function down() { @@ -465,7 +465,7 @@ yii migrate/create create_junction_table_for_post_and_tag_tables class m160328_041642_create_junction_table_for_post_and_tag_tables extends Migration { /** - * @inheritdoc + * {@inheritdoc} */ public function up() { @@ -512,7 +512,7 @@ class m160328_041642_create_junction_table_for_post_and_tag_tables extends Migra } /** - * @inheritdoc + * {@inheritdoc} */ public function down() { diff --git a/docs/guide-ru/input-validation.md b/docs/guide-ru/input-validation.md index dacd5f9..6e3cca6 100644 --- a/docs/guide-ru/input-validation.md +++ b/docs/guide-ru/input-validation.md @@ -358,8 +358,8 @@ class MyForm extends Model public function validateCountry($attribute, $params) { - if (!in_array($this->$attribute, ['USA', 'Web'])) { - $this->addError($attribute, 'Страна должна быть либо "USA" или "Web".'); + if (!in_array($this->$attribute, ['USA', 'Indonesia'])) { + $this->addError($attribute, 'Страна должна быть либо "USA" или "Indonesia".'); } } } @@ -384,7 +384,9 @@ class MyForm extends Model Вы можете реализовать свою логику проверки путем переопределения метода [[yii\validators\Validator::validateAttribute()]]. Если атрибут не прошел проверку, вызвать [[yii\base\Model::addError()]], -чтобы сохранить сообщение об ошибке в модели, как это делают [встроенные валидаторы](#inline-validators). Например: +чтобы сохранить сообщение об ошибке в модели, как это делают [встроенные валидаторы](#inline-validators). + +Валидация может быть помещена в отдельный класс [[components/validators/CountryValidator]]. В этом случае можно использовать метод [[yii\validators\Validator::addError()]] для того, чтобы добавить своё сообщение об ошибке в модель: ```php namespace app\components; @@ -395,8 +397,8 @@ class CountryValidator extends Validator { public function validateAttribute($model, $attribute) { - if (!in_array($model->$attribute, ['USA', 'Web'])) { - $this->addError($model, $attribute, 'Страна должна быть либо "USA" или "Web".'); + if (!in_array($model->$attribute, ['USA', 'Indonesia'])) { + $this->addError($model, $attribute, 'Страна должна быть либо "{country1}" либо "{country2}".', ['country1' => 'USA', 'country2' => 'Indonesia']); } } } diff --git a/docs/guide-ru/intro-yii.md b/docs/guide-ru/intro-yii.md index 0c2fbdd..867a7a4 100644 --- a/docs/guide-ru/intro-yii.md +++ b/docs/guide-ru/intro-yii.md @@ -1,16 +1,15 @@ Что такое Yii? ============== -Yii – это высокопроизводительный компонентный PHP фреймворк, предназначенный для быстрой разработки современных веб -приложений. Слово Yii (произносится как `Йи` `[ji:]`) в китайском языке означает «простой и эволюционирующий». Также Yii +Yii – это высокопроизводительный компонентный PHP фреймворк, предназначенный для быстрой разработки современных веб-приложений. Слово Yii (произносится как `Йи` `[ji:]`) в китайском языке означает «простой и эволюционирующий». Также Yii может расшифровываться как акроним **Yes It Is**! Для каких задач больше всего подходит Yii? ------------------------------------------ -Yii – это универсальный фреймворк и может быть задействован во всех типах веб приложений. Благодаря его компонентной -структуре и отличной поддержке кэширования, фреймворк особенно подходит для разработки таких крупных проектов как +Yii – это универсальный фреймворк и может быть задействован во всех типах веб-приложений. Благодаря его компонентной +структуре и отличной поддержке кэширования, фреймворк особенно подходит для разработки таких крупных проектов, как порталы, форумы, CMS, магазины или RESTful-приложения. @@ -20,15 +19,15 @@ Yii – это универсальный фреймворк и может бы Если вы уже знакомы с другими фреймворками, вам наверняка будет интересно сравнить их с Yii. - Как и многие другие PHP фреймворки, для организации кода Yii использует архитектурный паттерн MVC (Model-View-Controller). -- Yii придерживается философии простого и элегантного кода не пытаясь усложнять дизайн только ради следования каким-либо +- Yii придерживается философии простого и элегантного кода, не пытаясь усложнять дизайн только ради следования каким-либо шаблонам проектирования. - Yii является full-stack фреймворком и включает в себя проверенные и хорошо зарекомендовавшие себя возможности, такие как ActiveRecord для реляционных и NoSQL баз данных, поддержку REST API, многоуровневое кэширование и другие. -- Yii отлично расширяем. Вы можете настроить или заменить практически любую часть основного кода. Используя архитектуру расширений легко делиться кодом или использовать код сообщества. +- Yii отлично расширяем. Вы можете настроить или заменить практически любую часть основного кода. Используя архитектуру расширений, легко делиться кодом или использовать код сообщества. - Одна из главных целей Yii – производительность. Yii — не проект одного человека. Он поддерживается и развивается [сильной командой](http://www.yiiframework.com/team/) и большим сообществом разработчиков, -которые ей помогают. Авторы фреймворка следят за тенденциями веб разработки и развитием других проектов. Наиболее +которые ей помогают. Авторы фреймворка следят за тенденциями веб-разработки и развитием других проектов. Наиболее подходящие возможности и лучшие практики регулярно внедряются в фреймворк в виде простых и элегантных интерфейсов. Версии Yii diff --git a/docs/guide-ru/output-data-providers.md b/docs/guide-ru/output-data-providers.md index 28239a9..eb311d7 100644 --- a/docs/guide-ru/output-data-providers.md +++ b/docs/guide-ru/output-data-providers.md @@ -258,7 +258,7 @@ class CsvDataProvider extends BaseDataProvider /** - * @inheritdoc + * {@inheritdoc} */ public function init() { @@ -269,7 +269,7 @@ class CsvDataProvider extends BaseDataProvider } /** - * @inheritdoc + * {@inheritdoc} */ protected function prepareModels() { @@ -298,7 +298,7 @@ class CsvDataProvider extends BaseDataProvider } /** - * @inheritdoc + * {@inheritdoc} */ protected function prepareKeys($models) { @@ -320,7 +320,7 @@ class CsvDataProvider extends BaseDataProvider } /** - * @inheritdoc + * {@inheritdoc} */ protected function prepareTotalCount() { diff --git a/docs/guide-ru/output-data-widgets.md b/docs/guide-ru/output-data-widgets.md index 71f173a..61f3916 100644 --- a/docs/guide-ru/output-data-widgets.md +++ b/docs/guide-ru/output-data-widgets.md @@ -222,6 +222,13 @@ echo GridView::widget([ 'attribute' => 'birthday', 'format' => ['date', 'php:Y-m-d'] ], + 'created_at:datetime', // короткий вид записи формата + [ + 'label' => 'Education', + 'attribute' => 'education', + 'filter' => ['0' => 'Elementary', '1' => 'Secondary', '2' => 'Higher'], + 'filterInputOptions' => ['prompt' => 'All educations', 'class' => 'form-control', 'id' => null] + ], ], ]); ``` @@ -235,6 +242,13 @@ echo GridView::widget([ Для конфигурации колонок данных также доступен короткий вид записи, который описан в API документации для [[yii\grid\GridView::columns|колонок]]. +Используйте [[yii\grid\DataColumn::filter|filter]] и [[yii\grid\DataColumn::filterInputOptions|filterInputOptions]] для +настройки HTML кода фильтра. + +По умолчанию заголовки колонок генерируются используя [[yii\data\Sort::link]]. Это можно изменить через свойство +[[yii\grid\Column::header]]. Для изменения заголовка нужно задать [[yii\grid\DataColumn::$label]], как в +примере выше. По умолчанию текст будет взят из модели данных. Подробное описание ищите в [[yii\grid\DataColumn::getHeaderCellLabel]]. + #### ActionColumn [[yii\grid\ActionColumn|ActionColumn]] отображает кнопки действия, такие как изменение или удаление для каждой строки. @@ -619,7 +633,7 @@ class UserView extends ActiveRecord { /** - * @inheritdoc + * {@inheritdoc} */ public static function tableName() { @@ -632,7 +646,7 @@ class UserView extends ActiveRecord } /** - * @inheritdoc + * {@inheritdoc} */ public function rules() { @@ -642,7 +656,7 @@ class UserView extends ActiveRecord } /** - * @inheritdoc + * {@inheritdoc} */ public function attributeLabels() { diff --git a/docs/guide-ru/output-formatting.md b/docs/guide-ru/output-formatting.md index 4afb759..395f06f 100644 --- a/docs/guide-ru/output-formatting.md +++ b/docs/guide-ru/output-formatting.md @@ -36,9 +36,8 @@ Formatter может быть использован двумя различны [[yii\i18n\Formatter::locale|locale]]. Если оно не было настроено, то в качестве локали будет использован [[yii\base\Application::language|язык приложения]]. Подробнее смотрите в разделе «[интернационализация](tutorial-i18n.md)». Компонент форматирования будет выбирать корректный формат для даты и чисел в соответствии с локалью, включая имена -месяцев и дней недели, переведённые на текущий язык. Форматирование дат также зависит от -[[yii\i18n\Formatter::timeZone|часового пояса]], которая -также будет из свойства [[yii\base\Application::timeZone|timeZone]] приложения, если она не была задана явно. +месяцев и дней недели, переведённые на текущий язык. +Форматирование дат также зависит от [[yii\i18n\Formatter::timeZone|часового пояса]], который будет взят из одноимённого свойства [[yii\base\Application::timeZone|timeZone]] приложения, если не был задан явно. В свою очередь [[yii\base\Application::timeZone|timeZone]] устанавливает / читает временную зону PHP. Например, форматирование даты, вызванное с разной локалью, отобразит разные результаты:: @@ -140,16 +139,14 @@ echo Yii::$app->formatter->asTime('2014-10-06 12:41:00'); // 14:41:00 echo Yii::$app->formatter->asTime('2014-10-06 14:41:00 CEST'); // 14:41:00 ``` -Начиная с версии 2.0.1 стало возможно настраивать часовой пояс для предполагаемых timestamp, которые не включают в себя -часовой пояс, как во втором примере в коде выше. Вы можете задать [[yii\i18n\Formatter::defaultTimeZone]] часовым поясом, -который вы используете для хранения данных. - -> Note: Поскольку часовые пояса являются субъектом ответственности правительств по всему миру и могут часто меняться, -> это значит, что вы, вероятно, не имеете самую свежую информацию в базе данных часовых поясов, установленной на вашем сервере. -> Вы можете обратиться к [ICU руководству](http://userguide.icu-project.org/datetime/timezone#TOC-Updating-the-Time-Zone-Data) -> для получения подробностей об обновлении базы данных часовых поясов. -> См. также: [Настройка вашего PHP окружения для интернационализации](tutorial-i18n.md#setup-environment). +Если [[yii\i18n\Formatter::timeZone|часовой пояс форматтера]] не задан явно, используется +[[yii\base\Application::timeZone|часовой пояс приложения]], то есть тот же, что задан в +конфигурации PHP. +> Note: Поскольку правила для часовых поясов принимаются различными правительствами и могут часто меняться, +> вероятно, информация в базе данных часовых поясов на вашем сервере не самая свежая. +> Как обновить базу вы можете узнать из [руководства ICU](http://userguide.icu-project.org/datetime/timezone#TOC-Updating-the-Time-Zone-Data). +> Смотрите также: [Настройка вашего PHP окружения для интернационализации](tutorial-i18n.md#setup-environment). Форматирование чисел ------------------ diff --git a/docs/guide-ru/rest-resources.md b/docs/guide-ru/rest-resources.md index ee148e4..9cc2f76 100644 --- a/docs/guide-ru/rest-resources.md +++ b/docs/guide-ru/rest-resources.md @@ -50,9 +50,9 @@ http://localhost/users?fields=id,email&expand=profile [[yii\db\ActiveRecord::fields()]] возвращает только те атрибуты, которые были объявлены в схеме БД. Вы можете переопределить `fields()` для того, чтобы добавить, удалить, переименовать или переобъявить поля. Значение, -возвращаемое `fields()`, должно быть массивом. Его ключи это имена полей, и значения могут быть либо именами -свойств/атрибутов, либо анонимными функциями, которые возвращают значение соответствующих полей. Если имя атрибута такое же, -как ключ массива вы можете опустить значение: +возвращаемое `fields()`, должно быть массивом. Его ключи — это названия полей. Значения могут быть либо именами +свойств/атрибутов, либо анонимными функциями, которые возвращают значение соответствующих свойств. Когда +название поля совпадает с именем аттрибута вы можете опустить ключ массива: ```php // явное перечисление всех атрибутов лучше всего использовать когда вы хотите быть уверенным что изменение @@ -61,11 +61,11 @@ http://localhost/users?fields=id,email&expand=profile public function fields() { return [ - // название поля совпадает с названием атрибута + // название поля совпадает с именем атрибута 'id', - // имя поля "email", атрибут "email_address" + // название поля "email", атрибут "email_address" 'email' => 'email_address', - // имя поля "name", значение определяется callback-ом PHP + // название поля "name", значение определяется callback-ом PHP 'name' => function () { return $this->first_name . ' ' . $this->last_name; }, @@ -77,7 +77,7 @@ public function fields() { $fields = parent::fields(); - // удаляем не безопасные поля + // удаляем небезопасные поля unset($fields['auth_key'], $fields['password_hash'], $fields['password_reset_token']); return $fields; diff --git a/docs/guide-ru/runtime-logging.md b/docs/guide-ru/runtime-logging.md index d9a4059..84390da 100644 --- a/docs/guide-ru/runtime-logging.md +++ b/docs/guide-ru/runtime-logging.md @@ -14,7 +14,7 @@ Yii предоставляет мощную, гибко настраиваему Запись сообщений лога осуществляется вызовом одного из следующих методов: -* [[Yii::trace()]]: записывает сообщения для отслеживания выполнения кода приложения. Используется, в основном, при разработке. +* [[Yii::debug()]]: записывает сообщения для отслеживания выполнения кода приложения. Используется, в основном, при разработке. * [[Yii::info()]]: записывает сообщение, содержащее какую-либо полезную информацию. * [[Yii::warning()]]: записывает *тревожное* сообщение при возникновении неожиданного события. * [[Yii::error()]]: записывает критическую ошибку, на которую нужно, как можно скорее, обратить внимаение. @@ -22,7 +22,7 @@ Yii предоставляет мощную, гибко настраиваему Эти методы позволяют записывать сообщения разных *уровней важности* и *категорий*. Они имеют одинаковое описание функции `function ($message, $category = 'application')`, где `$message` передает сообщение для записи, а `$category` - категорию сообщения. В следующем примере будет записано *trace* сообщение с категорией по умолчанию `application`: ```php -Yii::trace('start calculating average revenue'); +Yii::debug('start calculating average revenue'); ``` > Note: Сообщение может быть как строкой так и объектом или массивом. За корректную работу с содержимым сообщения отвечают [цели лога](#log-targets). По умолчанию, если сообщение не является строкой, оно будет приведено к строковому типу при помощи [[yii\helpers\VarDumper::export()]]. @@ -30,7 +30,7 @@ Yii::trace('start calculating average revenue'); Для упрощения работы с сообщениями лога и их фильтрации, рекомендуется явно указывать подходящую категорию для каждого сообщения. Возможно использование иерархической системы именования категорий, что значительно упростит [целям лога](#log-targets) фильтрацию сообщений по категориям. Простым и эффективным способом именования категорий является использование магической PHP константы `__METHOD__`. Такой подход используется в ядре фреймворка Yii. Например, ```php -Yii::trace('начало вычисления среднего дохода', __METHOD__); +Yii::debug('начало вычисления среднего дохода', __METHOD__); ``` Константа `__METHOD__` вычисляется как имя метода (включая полное имя класса), в котором она использована. Например, её значение будет вычислено как `'app\controllers\RevenueController::calculate'`, если показанный выше код вызывается в соответствующем методе. @@ -49,7 +49,9 @@ Yii::trace('начало вычисления среднего дохода', __ return [ // Компонент "log" должен быть загружен на этапе предзагрузки 'bootstrap' => ['log'], - + // Компонент "log" обрабатывает сообщения с меткой времени timestamp. + // Задайте временную зону для создания корректных меток времени. + 'timeZone' => 'Europe/Moscow', 'components' => [ 'log' => [ 'targets' => [ @@ -99,7 +101,7 @@ return [ * `error`: соответствует сообщениям, сохраненным методом [[Yii::error()]]. * `warning`: соответствует сообщениям, сохраненным методом [[Yii::warning()]]. * `info`: соответствует сообщениям, сохраненным методом [[Yii::info()]]. -* `trace`: соответствует сообщениям, сохраненным методом [[Yii::trace()]]. +* `trace`: соответствует сообщениям, сохраненным методом [[Yii::debug()]]. * `profile`: соответствует сообщениям, сохраненным методами [[Yii::beginProfile()]] и [[Yii::endProfile()]], подробнее о которых написано в подразделе [Профилирование производительности](#performance-profiling). Если свойство [[yii\log\Target::levels|levels]] не задано, цель логов будет обрабатывать сообщения с *любым* уровнем важности. @@ -220,7 +222,7 @@ return [ ] ``` -Из-за того, что значения максимального количества сообщений для передачи и выгрузки по умолчанию достаточно велико, при вызове метода `Yii::trace()`, или любого другого метода логгирования, сообщение не появится сразу в файле или таблице базы данных. Такое поведение может стать проблемой, например, в консольных приложениях с большим временем исполнения. Для того, чтобы все сообщения логов сразу же попадали в лог, необходимо установить значения свойств [[yii\log\Dispatcher::flushInterval|flushInterval]] и [[yii\log\Target::exportInterval|exportInterval]] равными 1, например так: +Из-за того, что значения максимального количества сообщений для передачи и выгрузки по умолчанию достаточно велико, при вызове метода `Yii::debug()`, или любого другого метода логгирования, сообщение не появится сразу в файле или таблице базы данных. Такое поведение может стать проблемой, например, в консольных приложениях с большим временем исполнения. Для того, чтобы все сообщения логов сразу же попадали в лог, необходимо установить значения свойств [[yii\log\Dispatcher::flushInterval|flushInterval]] и [[yii\log\Target::exportInterval|exportInterval]] равными 1, например так: ```php return [ diff --git a/docs/guide-ru/security-best-practices.md b/docs/guide-ru/security-best-practices.md index 191717f..7a84629 100644 --- a/docs/guide-ru/security-best-practices.md +++ b/docs/guide-ru/security-best-practices.md @@ -162,16 +162,72 @@ CSRF - это аббревиатура для межсайтинговой по Если это так, то нужно запретить доступ ко всему, кроме директории `web`. Если на вашем хостинге такое невозможно, рассмотрите возможность смены хостинга. -Как избежать отладочной информации и утилит в продуктиве --------------------------------------------------------- +Как избежать вывода информации отладки и инструментов в рабочем режиме +---------------------------------------------------------------------- В режиме отладки, Yii отображает довольно подробные ошибки, которые полезны во время разработки. Дело в том, что подробные ошибки удобны для нападающего, так как могут раскрыть структуру базы данных, параметров конфигурации и части -вашего кода. Никогда не запускайте продуктивное приложение с `YII_DEBUG` установленным в `true` в вашем `index.php`. +вашего кода. Никогда не запускайте приложения в рабочем режиме с `YII_DEBUG` установленным в `true` в вашем `index.php`. -Вы никогда не должны включать Gii на продуктиве. Он может быть использован для получения информации о структуре -базы данных, кода и может позволить заменить файлы, генерируемые Gii автоматически. +Вы никогда не должны включать Gii или Debug панель в рабочем режиме. Это может быть использованно для получения информации о структуре базы данных, кода и может позволить заменить файлы, генерируемые Gii автоматически. -Также следует избегать включения на продуктиве панели отладки, если только в этом нет острой необходимости. -Она раскрывает всё приложение и детали конфигурации. Если вам все таки нужно запустить панель отладки на продуктиве, -проверьте дважды что доступ ограничен только вашими IP-адресами. +Следует избегать включения в рабочем режиме панели отладки, если только в этом нет острой необходимости. +Она раскрывает всё приложение и детали конфигурации. Если Вам всё-таки нужно запустить панель отладки в рабочем режиме, +проверьте дважды, что доступ ограничен только вашими IP-адресами. + +Далее по теме читайте: + +- +- + + +Использование безопасного подключения через TLS +----------------------------------------------- + +Yii предоставляет функции, которые зависят от куки-файлов и/или сессий PHP. Они могут быть уязвимыми, если Ваше соединение +скомпрометированно. Риск снижается, если приложение использует безопасное соединение через TLS (часто называемое как [SSL](https://en.wikipedia.org/wiki/Transport_Layer_Security)). + +Инструкции по настройке смотрите в документации к Вашему веб-серверу. Вы также можете проверить примеры конфигураций +предоставленные проектом H5BP: + +- [Nginx](https://github.com/h5bp/server-configs-nginx) +- [Apache](https://github.com/h5bp/server-configs-apache). +- [IIS](https://github.com/h5bp/server-configs-iis). +- [Lighttpd](https://github.com/h5bp/server-configs-lighttpd). + + +Безопасная конфигурация сервера +------------------------------- + +Цель этого раздела - выявить риски, которые необходимо учитывать при создании +конфигурации сервера для обслуживания веб-сайта на основе Yii. Помимо перечисленных здесь пунктов есть и +другие параметры, связанные с безопасностью, которые необходимо учитывать, поэтому не рассматривайте этот раздел как завершенный. + +### Как избежать атаки типа `Host`-header + +Классы типа [[yii\web\UrlManager]] и [[yii\helpers\Url]] могут использовать [[yii\web\Request::getHostInfo()|запрашиваемое имя хоста]]] для генерации ссылок. Если веб-сервер настроен на обслуживание одного и того же сайта независимо от значения заголовка `Host`, эта информация может быть ненадежной и может быть подделана пользователем, отправляющим HTTP-запрос. В таких ситуациях Вы должны либо исправить конфигурацию своего веб-сервера, чтобы обслуживать сайт только для указанных имен узлов, либо явно установить или отфильтровать значение, установив свойство [[yii\web\Request::setHostInfo()|hostInfo]] компонента приложения `request`. + +Дополнительные сведения о конфигурации сервера смотрите в документации Вашего веб-сервера: + +- Apache 2: +- Nginx: + +Если у Вас нет доступа к конфигурации сервера, Вы можете настроить фильтр [[yii\filters\HostControl]] уровня приложения для защиты от такого рода атак: + +```php +// Файл конфигурации веб-приложения +return [ + 'as hostControl' => [ + 'class' => 'yii\filters\HostControl', + 'allowedHosts' => [ + 'example.com', + '*.example.com', + ], + 'fallbackHostInfo' => 'https://example.com', + ], + // ... +]; +``` + +> Note: Вы всегда должны предпочесть конфигурацию веб-сервера для защиты от `атак заголовков узла` вместо использования фильтра. + [[yii\filters\HostControl]] следует использовать, только если настройка конфигурации сервера недоступна. diff --git a/docs/guide-ru/start-installation.md b/docs/guide-ru/start-installation.md index db185b7..d9eccdc 100644 --- a/docs/guide-ru/start-installation.md +++ b/docs/guide-ru/start-installation.md @@ -176,7 +176,7 @@ DocumentRoot "path/to/basic/web" PHP должен быть установлен как [FPM SAPI](http://php.net/manual/ru/install.fpm.php) для [Nginx](http://wiki.nginx.org/). Используйте следующие параметры Nginx и не забудьте заменить `path/to/basic/web` на корректный путь к `basic/web` и -`mysite.local` на ваше имя хоста. +`mysite.test` на ваше имя хоста. ``` server { @@ -186,7 +186,7 @@ server { listen 80; ## listen for ipv4 #listen [::]:80 default_server ipv6only=on; ## слушаем ipv6 - server_name mysite.local; + server_name mysite.test; root /path/to/basic/web; index index.php; diff --git a/docs/guide-ru/structure-filters.md b/docs/guide-ru/structure-filters.md index bcad52d..94d7e21 100644 --- a/docs/guide-ru/structure-filters.md +++ b/docs/guide-ru/structure-filters.md @@ -87,7 +87,7 @@ class ActionTimeFilter extends ActionFilter public function afterAction($action, $result) { $time = microtime(true) - $this->_startTime; - Yii::trace("Action '{$action->uniqueId}' spent $time second."); + Yii::debug("Action '{$action->uniqueId}' spent $time second."); return parent::afterAction($action, $result); } } diff --git a/docs/guide-ru/structure-modules.md b/docs/guide-ru/structure-modules.md index 78d3e67..ebd2a95 100644 --- a/docs/guide-ru/structure-modules.md +++ b/docs/guide-ru/structure-modules.md @@ -171,6 +171,13 @@ yii // из идентификатора модуля, то контроллер и действие определяются исходя из свойства [[yii\base\Module::defaultRoute]], которое по умолчанию равно `default`. Таким образом, маршрут `forum` соответствует контроллеру `default` модуля `forum`. +Добавление маршрутов модуля в URL manager необходимо производить до начала работы [[yii\web\UrlManager::parseRequest()]], что не +позволяет размещать код добавления правил модуля в `init()`, так как инициализация происходит уже после обработки маршрутов. Таким образом, добавление маршрутов необходимо осуществить в [предзагрузке +модуля](structure-extensions.md#bootstrapping-classes). Хорошей практикой, также, будет объединение всех правил модуля +при помощи [[\yii\web\GroupUrlRule]]. + +Если же вы используете модуль для [версионирования API](rest-versioning.md), добавление маршрутов необходимо +производить непосредственно в конфигурации `urlManager` приложения. ### Получение доступа к модулям diff --git a/docs/guide-ru/tutorial-i18n.md b/docs/guide-ru/tutorial-i18n.md index 1a2f187..5d70ee8 100644 --- a/docs/guide-ru/tutorial-i18n.md +++ b/docs/guide-ru/tutorial-i18n.md @@ -269,7 +269,7 @@ for an argument: U_ARGUMENT_TYPE_MISMATCH": ``` Подробная документация о формах склонений для различных языков доступна на сайте -[unicode.org](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html). +[unicode.org](http://cldr.unicode.org/index/cldr-spec/plural-rules). #### Вариации diff --git a/docs/guide-ru/tutorial-yii-as-micro-framework.md b/docs/guide-ru/tutorial-yii-as-micro-framework.md new file mode 100644 index 0000000..193d035 --- /dev/null +++ b/docs/guide-ru/tutorial-yii-as-micro-framework.md @@ -0,0 +1,206 @@ +# Использование Yii в качестве микро-framework'а + +Yii можно легко использовать без функций включенных в базовый и расширенный шаблоны приложений. Другими словами Yii уже является микро-каркасом. Не требуется иметь структуру каталогов предоставляемую этими шаблонами при работе с Yii. + +Это особенно удобно, когда Вам не нужен весь пред-установленный шаблонный код, такой как `Assets` или `Views`. Одним из таких случаев является создание JSON API. В следующих разделах будет показано, как это сделать. + +## Установка Yii + +Создайте каталог для файлов проекта и смените рабочий каталог на этот путь. В примерах используются команды Unix, но аналогичные команды существуют и в Windows. + +```bash +mkdir micro-app +cd micro-app +``` + +> Note: Для продолжения требуется немного знаний о Composer. Если Вы еще не знаете, как использовать Composer, пожалуйста, найдите время, чтобы прочитать [Руководство Composer](https://getcomposer.org/doc/00-intro.md). + +Создайте файл `composer.json` в каталоге `micro-app` с помощью Вашего любимого редактора и добавьте следующее: + +```json +{ + "require": { + "yiisoft/yii2": "~2.0.0" + }, + "repositories": [ + { + "type": "composer", + "url": "https://asset-packagist.org" + } + ] +} +``` + +Сохраните файл и запустите команду `comper install`. Это установит framework со всеми его зависимостями. + +## Создание структуры проекта + +После того как Вы установили фреймворк, пришло время создать [входную точку](structure-entry-scripts.md) приложения. Точка входа - это самый первый файл, который будет выполнен при попытке открыть приложение. По соображениям безопасности рекомендуется поместить файл точки входа в отдельный каталог и сделать каталог корнем веб директории. + +Создайте каталог `web` и поместите в него файл `index.php` со следующим содержимым: + +```php +run(); +``` + +Также создайте файл с именем `config.php`, который будет содержать всю конфигурацию приложения: + +```php + 'micro-app', + // basePath (базовый путь) приложения будет каталог `micro-app` + 'basePath' => __DIR__, + // это пространство имен где приложение будет искать все контроллеры + 'controllerNamespace' => 'micro\controllers', + // установим псевдоним '@micro', чтобы включить автозагрузку классов из пространства имен 'micro' + 'aliases' => [ + '@micro' => __DIR__, + ], +]; +``` + +> Info: Несмотря на то, что конфигурация приложения может находиться в файле `index.php` рекомендуется +> содержать её в отдельном файле. Таким образом её можно также использовать и для консольного приложения, как показано ниже. + +Теперь Ваш проект готов к наполнению кодом. Вам решать какую структуру каталогов проекта Вы выберите, пока Вы сможете видеть пространства имен. + +## Создание первого контроллера + +Создайте каталог `controllers` и добавьте туда файл `SiteController.php` который является контроллером по умолчанию, он будет обрабатывать запрос без пути. + +```php + 'default/index'`. + +На данный момент структура проекта должна выглядеть так: + +``` +micro-app/ +├── composer.json +├── web/ + └── index.php +└── controllers/ + └── SiteController.php +``` + +Если Вы еще не настроили веб-сервер, Вы можете взглянуть на [примеры конфигурационных файлов веб-серверов](start-installation.md#Настройка-веб-сервера-). +Другой возможностью является использование команды `yii serve` которая будет использовать встроенный веб-сервер PHP. Вы можете запустить её из каталога `micro-app/` через: + + vendor/bin/yii serve --docroot=./web + +При открытии URL приложения в браузере, он теперь должен печатать "Hello World!" который был возвращен из `SiteController::actionIndex()`. + +> Info: В нашем примере мы изменили пространство имен по умолчанию приложения с `app` на` micro`, чтобы продемонстрировать +> что Вы не привязаны к этому имени (в случае, если Вы считали, что это так), а затем скорректировали +> [[yii\base\Application::$controllerNamespace|controllers namespace]] и установили правильный псевдоним. + +## Создание REST API + +Чтобы продемонстрировать использование нашей "микроархитектуры" мы создадим простой REST API для сообщений. + +Чтобы этот API обслуживал некоторые данные, нам нужна база данных. Добавим конфигурацию подключения базы данных +к конфигурации приложения: + +```php +'components' => [ + 'db' => [ + 'class' => 'yii\db\Connection', + 'dsn' => 'sqlite:@micro/database.sqlite', + ], +], +``` + +> Info: Для простоты мы используем базу данных sqlite. Дополнительную информацию см. в [Руководство по базам данных](db-dao.md). + +Затем мы создаем [миграции базы данных](db-migrations.md) для создания таблицы сообщений. +Убедитесь, что у Вас есть отдельный файл конфигурации, как описано выше, нам это нужно для того, чтобы запустить консольные команды описанные ниже. +Запуск следующих команд создаст файл миграции базы данных и применит миграцию к базе данных: + + vendor/bin/yii migrate/create --appconfig=config.php create_post_table --fields="title:string,body:text" + vendor/bin/yii migrate/up --appconfig=config.php + +Создайте каталог `models` и файл` Post.php` в этом каталоге. Это код модели: + +```php + Info: Созданная модель представляет собой класс ActiveRecord, который представляет данные из таблицы `posts`. +> Для получения дополнительной информации обратитесь к [active record руководству](db-active-record.md). + +Чтобы обслуживать сообщения в нашем API, добавьте `PostController` в` controllers`: + +```php + Tip: 你可以在同一个应用程序中使用不同的缓存存储器。一个常见的策略是使用基于内存的缓存存储器存储小而常用的数据(例如:统计数据),使用基于文件或数据库的缓存存储器存储大而不太常用的数据(例如:网页内容)。 diff --git a/docs/guide-zh-CN/concept-di-container.md b/docs/guide-zh-CN/concept-di-container.md index c46367a..0943fb4 100644 --- a/docs/guide-zh-CN/concept-di-container.md +++ b/docs/guide-zh-CN/concept-di-container.md @@ -69,7 +69,7 @@ $container->get('Foo', [], [ 这种情况下,容器将使用一个注册过的 PHP 回调创建一个类的新实例。回调负责解决依赖并将其恰当地注入新创建的对象。例如: ```php -$container->set('Foo', function () { +$container->set('Foo', function ($container, $params, $config) { return new Foo(new Bar); }); diff --git a/docs/guide-zh-CN/concept-events.md b/docs/guide-zh-CN/concept-events.md index 7a292f0..bac1529 100644 --- a/docs/guide-zh-CN/concept-events.md +++ b/docs/guide-zh-CN/concept-events.md @@ -182,7 +182,7 @@ use yii\base\Event; use yii\db\ActiveRecord; Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) { - Yii::trace(get_class($event->sender) . ' is inserted'); + Yii::debug(get_class($event->sender) . ' is inserted'); }); ``` diff --git a/docs/guide-zh-CN/start-installation.md b/docs/guide-zh-CN/start-installation.md index d3d366a..9d2044f 100644 --- a/docs/guide-zh-CN/start-installation.md +++ b/docs/guide-zh-CN/start-installation.md @@ -132,7 +132,7 @@ DocumentRoot "path/to/basic/web" ### 推荐使用的 Nginx 配置 -为了使用 [Nginx](http://wiki.nginx.org/),你应该已经将 PHP 安装为 [FPM SAPI](http://php.net/install.fpm) 了。使用如下 Nginx 配置,将 `path/to/basic/web` 替换为实际的 `basic/web` 目录,`mysite.local` 替换为实际的主机名以提供服务。 +为了使用 [Nginx](http://wiki.nginx.org/),你应该已经将 PHP 安装为 [FPM SAPI](http://php.net/install.fpm) 了。使用如下 Nginx 配置,将 `path/to/basic/web` 替换为实际的 `basic/web` 目录,`mysite.test` 替换为实际的主机名以提供服务。 ``` server { @@ -142,7 +142,7 @@ server { listen 80; ## 监听 ipv4 上的 80 端口 #listen [::]:80 default_server ipv6only=on; ## 监听 ipv6 上的 80 端口 - server_name mysite.local; + server_name mysite.test; root /path/to/basic/web; index index.php; diff --git a/docs/guide-zh-CN/structure-filters.md b/docs/guide-zh-CN/structure-filters.md index 91023a0..da18136 100644 --- a/docs/guide-zh-CN/structure-filters.md +++ b/docs/guide-zh-CN/structure-filters.md @@ -84,7 +84,7 @@ class ActionTimeFilter extends ActionFilter public function afterAction($action, $result) { $time = microtime(true) - $this->_startTime; - Yii::trace("Action '{$action->uniqueId}' spent $time second."); + Yii::debug("Action '{$action->uniqueId}' spent $time second."); return parent::afterAction($action, $result); } } diff --git a/docs/guide/README.md b/docs/guide/README.md index 478718b..d032bdb 100644 --- a/docs/guide/README.md +++ b/docs/guide/README.md @@ -18,6 +18,7 @@ Introduction Getting Started --------------- +* [What do you need to know](start-prerequisites.md) * [Installing Yii](start-installation.md) * [Running Applications](start-workflow.md) * [Saying Hello](start-hello.md) diff --git a/docs/guide/caching-data.md b/docs/guide/caching-data.md index e74696a..d964ca2 100644 --- a/docs/guide/caching-data.md +++ b/docs/guide/caching-data.md @@ -125,8 +125,8 @@ Yii supports a wide range of cache storage. The following is a summary: (redis version 2.6.12 or higher is required). * [[yii\caching\WinCache]]: uses PHP [WinCache](http://iis.net/downloads/microsoft/wincache-extension) ([see also](http://php.net/manual/en/book.wincache.php)) extension. -* [[yii\caching\XCache]]: uses PHP [XCache](http://xcache.lighttpd.net/) extension. -* [[yii\caching\ZendDataCache]]: uses +* [[yii\caching\XCache]] _(deprecated)_: uses PHP [XCache](http://xcache.lighttpd.net/) extension. +* [[yii\caching\ZendDataCache]] _(deprecated)_: uses [Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm) as the underlying caching medium. diff --git a/docs/guide/caching-fragment.md b/docs/guide/caching-fragment.md index a9fef47..5a5e9a1 100644 --- a/docs/guide/caching-fragment.md +++ b/docs/guide/caching-fragment.md @@ -174,3 +174,6 @@ if ($this->beginCache($id1)) { The [[yii\base\View::renderDynamic()|renderDynamic()]] method takes a piece of PHP code as its parameter. The return value of the PHP code is treated as the dynamic content. The same PHP code will be executed for every request, no matter the enclosing fragment is being served from cached or not. + +> Note: since version 2.0.14 a dynamic content API is exposed via the [[yii\base\DynamicContentAwareInterface]] interface and its [[yii\base\DynamicContentAwareTrait]] trait. + As an example, you may refer to the [[yii\widgets\FragmentCache]] class. diff --git a/docs/guide/concept-di-container.md b/docs/guide/concept-di-container.md index 67b95f5..665d049 100644 --- a/docs/guide/concept-di-container.md +++ b/docs/guide/concept-di-container.md @@ -117,7 +117,7 @@ The callable is responsible to resolve the dependencies and inject them appropri created objects. For example, ```php -$container->set('Foo', function () { +$container->set('Foo', function ($container, $params, $config) { $foo = new Foo(new Bar); // ... other initializations ... return $foo; @@ -131,7 +131,7 @@ To hide the complex logic for building a new object, you may use a static class ```php class FooBuilder { - public static function build() + public static function build($container, $params, $config) { $foo = new Foo(new Bar); // ... other initializations ... @@ -421,7 +421,7 @@ $container->setDefinitions([ 'class' => 'app\components\Response', 'format' => 'json' ], - 'app\storage\DocumentsReader' => function () { + 'app\storage\DocumentsReader' => function ($container, $params, $config) { $fs = new app\storage\FileStorage('/var/tempfiles'); return new app\storage\DocumentsReader($fs); } diff --git a/docs/guide/concept-events.md b/docs/guide/concept-events.md index 06d11b9..7d0315d 100644 --- a/docs/guide/concept-events.md +++ b/docs/guide/concept-events.md @@ -42,7 +42,7 @@ Attaching Event Handlers You can attach a handler to an event by calling the [[yii\base\Component::on()]] method. For example: ```php -$foo = new Foo; +$foo = new Foo(); // this handler is a global function $foo->on(Foo::EVENT_HELLO, 'function_name'); @@ -212,7 +212,7 @@ use yii\base\Event; use yii\db\ActiveRecord; Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) { - Yii::trace(get_class($event->sender) . ' is inserted'); + Yii::debug(get_class($event->sender) . ' is inserted'); }); ``` @@ -296,7 +296,7 @@ pass the interface class name as the first argument: ```php Event::on('app\interfaces\DanceEventInterface', DanceEventInterface::EVENT_DANCE, function ($event) { - Yii::trace(get_class($event->sender) . ' just danced'); // Will log that Dog or Developer danced + Yii::debug(get_class($event->sender) . ' just danced'); // Will log that Dog or Developer danced }); ``` @@ -355,3 +355,74 @@ done through the Singleton (e.g. the application instance). However, because the namespace of the global events is shared by all parties, you should name the global events wisely, such as introducing some sort of namespace (e.g. "frontend.mail.sent", "backend.mail.sent"). + + +Wildcard Events +--------------- + +Since 2.0.14 you can setup event handler for multiple events matching wildcard pattern. +For example: + +```php +use Yii; + +$foo = new Foo(); + +$foo->on('foo.event.*', function ($event) { + // triggered for any event, which name starts on 'foo.event.' + Yii::debug('trigger event: ' . $event->name); +}); +``` + +Wildcard patterns can be used for class-level events as well. For example: + +```php +use yii\base\Event; +use Yii; + +Event::on('app\models\*', 'before*', function ($event) { + // triggered for any class in namespace 'app\models' for any event, which name starts on 'before' + Yii::debug('trigger event: ' . $event->name . ' for class: ' . get_class($event->sender)); +}); +``` + +This allows you catching all application events by single handler using following code: + +```php +use yii\base\Event; +use Yii; + +Event::on('*', '*', function ($event) { + // triggered for any event at any class + Yii::debug('trigger event: ' . $event->name); +}); +``` + +> Note: usage wildcards for event handlers setup may reduce the application performance. + It is better to be avoided if possible. + +In order to detach event handler specified by wildcard pattern, you should repeat same pattern at +[[yii\base\Component::off()]] or [[yii\base\Event::off()]] invocation. Keep in mind that passing wildcard +during detaching of event handler will detach ony the handler specified for this wildcard, while handlers +attached for regular event names will remain even if they match the pattern. For example: + +```php +use Yii; + +$foo = new Foo(); + +// attach regular handler +$foo->on('event.hello', function ($event) { + echo 'direct-handler' +}); + +// attach wildcard handler +$foo->on('*', function ($event) { + echo 'wildcard-handler' +}); + +// detach wildcard handler only! +$foo->off('*'); + +$foo->trigger('event.hello'); // outputs: 'direct-handler' +``` diff --git a/docs/guide/db-active-record.md b/docs/guide/db-active-record.md index d6a482d..9c4d156 100644 --- a/docs/guide/db-active-record.md +++ b/docs/guide/db-active-record.md @@ -472,7 +472,7 @@ $customer->loadDefaultValues(); ### Attributes Typecasting -Being populated by query results [[yii\db\ActiveRecord]] performs automatic typecast for its attribute values, using +Being populated by query results, [[yii\db\ActiveRecord]] performs automatic typecast for its attribute values, using information from [database table schema](db-dao.md#database-schema). This allows data retrieved from table column declared as integer to be populated in ActiveRecord instance with PHP integer, boolean with boolean and so on. However, typecasting mechanism has several limitations: @@ -490,7 +490,33 @@ converted during saving process. > Tip: you may use [[yii\behaviors\AttributeTypecastBehavior]] to facilitate attribute values typecasting on ActiveRecord validation or saving. + +Since 2.0.14, Yii ActiveRecord supports complex data types, such as JSON or multidimensional arrays. + +#### JSON in MySQL and PostgreSQL + +After data population, the value from JSON column will be automatically decoded from JSON according to standard JSON +decoding rules. + +To save attribute value to a JSON column, ActiveRecord will automatically create a [[yii\db\JsonExpression|JsonExpression]] object +that will be encoded to a JSON string on [QueryBuilder](db-query-builder.md) level. + +#### Arrays in PostgreSQL + +After data population, the value from Array column will be automatically decoded from PgSQL notation to an [[yii\db\ArrayExpression|ArrayExpression]] +object. It implements PHP `ArrayAccess` interface, so you can use it as an array, or call `->getValue()` to get the array itself. + +To save attribute value to an array column, ActiveRecord will automatically create an [[yii\db\ArrayExpression|ArrayExpression]] object +that will be encoded by [QueryBuilder](db-query-builder.md) to an PgSQL string representation of array. + +You can also use conditions for JSON columns: + +```php +$query->andWhere(['=', 'json', new ArrayExpression(['foo' => 'bar']) +``` +To learn more about expressions building system read the [Query Builder – Adding custom Conditions and Expressions](db-query-builder.md#adding-custom-conditions-and-expressions) +article. ### Updating Multiple Rows diff --git a/docs/guide/db-migrations.md b/docs/guide/db-migrations.md index c2e0996..0c536c9 100644 --- a/docs/guide/db-migrations.md +++ b/docs/guide/db-migrations.md @@ -38,6 +38,13 @@ command `yii help migrate`. > Tip: migrations could affect not only database schema but adjust existing data to fit new schema, create RBAC hierarchy or clean up cache. +> Note: When manipulating data using a migration you may find that using your [Active Record](db-active-record.md) classes +> for this might be useful because some of the logic is already implemented there. Keep in mind however, that in contrast +> to code written in the migrations, who's nature is to stay constant forever, application logic is subject to change. +> So when using Active Record in migration code, changes to the logic in the Active Record layer may accidentally break +> existing migrations. For this reason migration code should be kept independent from other application logic such +> as Active Record classes. + ## Creating Migrations @@ -204,7 +211,7 @@ generates class m150811_220037_create_post_table extends Migration { /** - * @inheritdoc + * {@inheritdoc} */ public function up() { @@ -214,7 +221,7 @@ class m150811_220037_create_post_table extends Migration } /** - * @inheritdoc + * {@inheritdoc} */ public function down() { @@ -238,7 +245,7 @@ generates class m150811_220037_create_post_table extends Migration { /** - * @inheritdoc + * {@inheritdoc} */ public function up() { @@ -250,7 +257,7 @@ class m150811_220037_create_post_table extends Migration } /** - * @inheritdoc + * {@inheritdoc} */ public function down() { @@ -275,7 +282,7 @@ generates class m150811_220037_create_post_table extends Migration { /** - * @inheritdoc + * {@inheritdoc} */ public function up() { @@ -287,7 +294,7 @@ class m150811_220037_create_post_table extends Migration } /** - * @inheritdoc + * {@inheritdoc} */ public function down() { @@ -320,7 +327,7 @@ generates class m160328_040430_create_post_table extends Migration { /** - * @inheritdoc + * {@inheritdoc} */ public function up() { @@ -368,7 +375,7 @@ class m160328_040430_create_post_table extends Migration } /** - * @inheritdoc + * {@inheritdoc} */ public function down() { @@ -533,7 +540,7 @@ generates class m160328_041642_create_junction_table_for_post_and_tag_tables extends Migration { /** - * @inheritdoc + * {@inheritdoc} */ public function up() { @@ -580,7 +587,7 @@ class m160328_041642_create_junction_table_for_post_and_tag_tables extends Migra } /** - * @inheritdoc + * {@inheritdoc} */ public function down() { @@ -716,14 +723,6 @@ Below is the list of all these database accessing methods: > ``` -> Note: When manipulating data using a migration you may find that using your [Active Record](db-active-record.md) classes -> for this might be useful because some of the logic is already implemented there. Keep in mind however, that in contrast -> to code written in the migrations, who's nature is to stay constant forever, application logic is subject to change. -> So when using Active Record in migration code, changes to the logic in the Active Record layer may accidentally break -> existing migrations. For this reason migration code should be kept independent from other application logic such -> as Active Record classes. - - ## Applying Migrations To upgrade a database to its latest structure, you should apply all available new migrations using the following command: diff --git a/docs/guide/db-query-builder.md b/docs/guide/db-query-builder.md index b23d1e7..1086f44 100644 --- a/docs/guide/db-query-builder.md +++ b/docs/guide/db-query-builder.md @@ -160,12 +160,12 @@ are in the ["Quoting Tables" section of the "Database Access Objects" guide](gui ### [[yii\db\Query::where()|where()]] The [[yii\db\Query::where()|where()]] method specifies the `WHERE` fragment of a SQL query. You can use one of -the three formats to specify a `WHERE` condition: +the four formats to specify a `WHERE` condition: - string format, e.g., `'status=1'` - hash format, e.g. `['status' => 1, 'type' => 2]` - operator format, e.g. `['like', 'name', 'test']` - +- object format, e.g. `new LikeCondition('name', 'LIKE', 'test')` #### String Format @@ -255,6 +255,9 @@ the operator can be one of the following: - `between`: operand 1 should be the column name, and operand 2 and 3 should be the starting and ending values of the range that the column is in. For example, `['between', 'id', 1, 10]` will generate `id BETWEEN 1 AND 10`. + In case you need to build a condition where value is between two columns (like `11 BETWEEN min_id AND max_id`), + you should use [[yii\db\conditions\BetweenColumnsCondition|BetweenColumnsCondition]]. + See [Conditions – Object Format](#object-format) chapter to learn more about object definition of conditions. - `not between`: similar to `between` except the `BETWEEN` is replaced with `NOT BETWEEN` in the generated condition. @@ -306,6 +309,41 @@ the operator can be one of the following: Using the Operator Format, Yii internally uses parameter binding so in contrast to the [string format](#string-format), here you do not have to add parameters manually. +#### Object Format + +Object Form is available since 2.0.14 and is both most powerful and most complex way to define conditions. +You need to follow it either if you want to build your own abstraction over query builder or if you want to implement +your own complex conditions. + +Instances of condition classes are immutable. Their only purpose is to store condition data and provide getters +for condition builders. Condition builder is a class that holds the logic that transforms data +stored in condition into the SQL expression. + +Internally the formats described above are implicitly converted to object format prior to building raw SQL, +so it is possible to combine formats in a single condition: + +```php +$query->andWhere(new OrCondition([ + new InCondition('type', 'in', $types), + ['like', 'name', '%good%'], + 'disabled=false' +])) +``` + +Conversion from operator format into object format is performed according to +[[yii\db\QueryBuilder::conditionClasses|QueryBuilder::conditionClasses]] property, that maps operators names +to representative class names: + +- `AND`, `OR` -> `yii\db\conditions\ConjunctionCondition` +- `NOT` -> `yii\db\conditions\NotCondition` +- `IN`, `NOT IN` -> `yii\db\conditions\InCondition` +- `BETWEEN`, `NOT BETWEEN` -> `yii\db\conditions\BetweenCondition` + +And so on. + +Using the object format makes it possible to create your own conditions or to change the way default ones are built. +See [Creating Custom Conditions and Expressions](#creating-custom-conditions-and-expressions) chapter to learn more. + #### Appending Conditions @@ -758,3 +796,170 @@ $unbufferedDb->close(); ``` > Note: unbuffered query uses less memory on the PHP-side, but can increase the load on the MySQL server. It is recommended to design your own code with your production practice for extra massive data, [for example, divide the range for integer keys, loop them with Unbuffered Queries](https://github.com/yiisoft/yii2/issues/8420#issuecomment-296109257). + +### Adding custom Conditions and Expressions + +As it was mentioned in [Conditions – Object Format](#object-format) chapter, is is possible to create custom condition +classes. For example, let's create a condition that will check that specific columns are less than some value. +Using the operator format, it would look like the following: + +```php +[ + 'and', + '>', 'posts', $minLimit, + '>', 'comments', $minLimit, + '>', 'reactions', $minLimit, + '>', 'subscriptions', $minLimit +] +``` + +When such condition applied once, it is fine. In case it is used multiple times in a single query it can +be optimized a lot. Let's create a custom condition object to demonstrate it. + +Yii has a [[yii\db\conditions\ConditionInterface|ConditionInterface]], that must be used to mark classes, that represent +a condition. It requires `fromArrayDefinition()` method implementation, in order to make possible to create condition +from array format. In case you don't need it, you can implement this method with exception throwing. + +Since we create our custom condition class, we can build API that suits our task the most. + +```php +namespace app\db\conditions; + +class AllGreaterCondition implements \yii\db\conditions\ConditionInterface +{ + private $columns; + private $value; + + /** + * @param string[] $columns Array of columns that must be greater, than $value + * @param mixed $value the value to compare each $column against. + */ + public function __construct(array $columns, $value) + { + $this->columns = $columns; + $this->value = $value; + } + + public static function fromArrayDefinition($operator, $operands) + { + throw new InvalidArgumentException('Not implemented yet, but we will do it later'); + } + + public function getColumns() { return $this->columns; } + public function getValue() { return $this->vaule; } +} +``` + +So we can create a condition object: + +```php +$conditon = new AllGreaterCondition(['col1', 'col2'], 42); +``` + +But `QueryBuilder` still does not know, to to make an SQL condition out of this object. +Now we need to create a builder for this condition. It must implement [[yii\db\ExpressionBuilderInterface]] +that requires us to implement a `build()` method. + +```php +namespace app\db\conditions; + +class AllGreaterConditionBuilder implements \yii\db\ExpressionBuilderInterface +{ + use \yii\db\Condition\ExpressionBuilderTrait; // Contains constructor and `queryBuilder` property. + + /** + * @param AllGreaterCondition $condition the condition to be built + * @param array $params the binding parameters. + */ + public function build(ConditionInterface $condition, &$params) + { + $value = $condition->getValue(); + + $conditions = []; + foreach ($condition->getColumns() as $column) { + $conditions[] = new SimpleCondition($column, '>', $value); + } + + return $this->queryBuider->buildCondition(new AndCondition($conditions), $params); + } +} +``` + +Then simple let [[yii\db\QueryBuilder|QueryBuilder]] know about our new condition – add a mapping for it to +the `expressionBuilders` array. It could be done right from the application configuration: + +```php +'db' => [ + 'class' => 'yii\db\mysql\Connection', + // ... + 'queryBuilder' => [ + 'expressionBuilders' => [ + 'app\db\conditions\AllGreaterCondition' => 'app\db\conditions\AllGreaterConditionBuilder', + ], + ], +], +``` + +Now we can use our condition in `where()`: + +```php +$query->andWhere(new AllGreaterCondition(['posts', 'comments', 'reactions', 'subscriptions'], $minValue)); +``` + +If we want to make it possible to create our custom condition using operator format, we should declare it in +[[yii\db\QueryBuilder::conditionClasses|QueryBuilder::conditionClasses]]: + +```php +'db' => [ + 'class' => 'yii\db\mysql\Connection', + // ... + 'queryBuilder' => [ + 'expressionBuilders' => [ + 'app\db\conditions\AllGreaterCondition' => 'app\db\conditions\AllGreaterConditionBuilder', + ], + 'conditionClasses' => [ + 'ALL>' => 'app\db\conditions\AllGreaterCondition', + ], + ], +], +``` + +And create a real implementation of `AllGreaterCondition::fromArrayDefinition()` method +in `app\db\conditions\AllGreaterCondition`: + +```php +namespace app\db\conditions; + +class AllGreaterCondition implements \yii\db\conditions\ConditionInterface +{ + // ... see the implementation above + + public static function fromArrayDefinition($operator, $operands) + { + return new static($operands[0], $operands[1]); + } +} +``` + +After that, we can create our custom condition using shorter operator format: + +```php +$query->andWhere(['ALL>', ['posts', 'comments', 'reactions', 'subscriptions'], $minValue]); +``` + +You might notice, that there was two concepts used: Expressions and Conditions. There is a [[yii\db\ExpressionInterface]] +that should be used to mark objects, that require an Expression Builder class, that implements +[[yii\db\ExpressionBuilderInterface]] to be built. Also there is a [[yii\db\condition\ConditionInterface]], that extends +[[yii\db\ExpressionInterface|ExpressionInterface]] and should be used to objects, that can be created from array definition +as it was shown above, but require builder as well. + +To summarise: + +- Expression – is a Data Transfer Object (DTO) for a dataset, that can be somehow compiled to some SQL +statement (an operator, string, array, JSON, etc). +- Condition – is an Expression superset, that aggregates multiple Expressions (or scalar values) that can be compiled +to a single SQL condition. + +You can create your own classes that implement [[yii\db\ExpressionInterface|ExpressionInterface]] to hide the complexity +of transforming data to SQL statements. You will learn more about other examples of Expressions in the +[next article](db-active-record.md); diff --git a/docs/guide/input-validation.md b/docs/guide/input-validation.md index e274616..fc69434 100644 --- a/docs/guide/input-validation.md +++ b/docs/guide/input-validation.md @@ -221,7 +221,7 @@ values are stored in an attribute: ```php ['age', 'trim'], ['age', 'default', 'value' => null], -['age', 'integer', 'integerOnly' => true, 'min' => 0], +['age', 'integer', 'min' => 0], ['age', 'filter', 'filter' => 'intval', 'skipOnEmpty' => true], ``` @@ -387,8 +387,8 @@ class MyForm extends Model public function validateCountry($attribute, $params, $validator) { - if (!in_array($this->$attribute, ['USA', 'Web'])) { - $this->addError($attribute, 'The country must be either "USA" or "Web".'); + if (!in_array($this->$attribute, ['USA', 'Indonesia'])) { + $this->addError($attribute, 'The country must be either "USA" or "Indonesia".'); } } } @@ -422,7 +422,8 @@ fails the validation, call [[yii\base\Model::addError()]] to save the error mess with [inline validators](#inline-validators). -For example the inline validator above could be moved into new [[components/validators/CountryValidator]] class. +For example, the inline validator above could be moved into new [[components/validators/CountryValidator]] class. +In this case we can use [[yii\validators\Validator::addError()]] to set customized message for the model. ```php namespace app\components; @@ -433,8 +434,8 @@ class CountryValidator extends Validator { public function validateAttribute($model, $attribute) { - if (!in_array($model->$attribute, ['USA', 'Web'])) { - $this->addError($model, $attribute, 'The country must be either "USA" or "Web".'); + if (!in_array($model->$attribute, ['USA', 'Indonesia'])) { + $this->addError($model, $attribute, 'The country must be either "{country1}" or "{country2}".', ['country1' => 'USA', 'country2' => 'Indonesia']); } } } diff --git a/docs/guide/output-data-providers.md b/docs/guide/output-data-providers.md index 919ef26..9de89e1 100644 --- a/docs/guide/output-data-providers.md +++ b/docs/guide/output-data-providers.md @@ -262,7 +262,7 @@ class CsvDataProvider extends BaseDataProvider /** - * @inheritdoc + * {@inheritdoc} */ public function init() { @@ -273,7 +273,7 @@ class CsvDataProvider extends BaseDataProvider } /** - * @inheritdoc + * {@inheritdoc} */ protected function prepareModels() { @@ -302,7 +302,7 @@ class CsvDataProvider extends BaseDataProvider } /** - * @inheritdoc + * {@inheritdoc} */ protected function prepareKeys($models) { @@ -324,7 +324,7 @@ class CsvDataProvider extends BaseDataProvider } /** - * @inheritdoc + * {@inheritdoc} */ protected function prepareTotalCount() { diff --git a/docs/guide/output-data-widgets.md b/docs/guide/output-data-widgets.md index eb54081..e009fea 100644 --- a/docs/guide/output-data-widgets.md +++ b/docs/guide/output-data-widgets.md @@ -243,6 +243,13 @@ echo GridView::widget([ 'attribute' => 'birthday', 'format' => ['date', 'php:Y-m-d'] ], + 'created_at:datetime', // shortcut format + [ + 'label' => 'Education', + 'attribute' => 'education', + 'filter' => ['0' => 'Elementary', '1' => 'Secondary', '2' => 'Higher'], + 'filterInputOptions' => ['prompt' => 'All educations', 'class' => 'form-control', 'id' => null] + ], ], ]); ``` @@ -256,6 +263,12 @@ For a list of available formatters see the [section about Data Formatting](outpu For configuring data columns there is also a shortcut format which is described in the API documentation for [[yii\grid\GridView::columns|columns]]. +Use [[yii\grid\DataColumn::filter|filter]] and [[yii\grid\DataColumn::filterInputOptions|filterInputOptions]] to +control HTML for the filter input. + +By default, column headers are rendered by [[yii\data\Sort::link]]. It could be adjusted using [[yii\grid\Column::header]]. +To change header text you should set [[yii\grid\DataColumn::$label]] like in the example above. +By default the label will be populated from data model. For more details see [[yii\grid\DataColumn::getHeaderCellLabel]]. #### Action column @@ -643,7 +656,7 @@ class UserView extends ActiveRecord { /** - * @inheritdoc + * {@inheritdoc} */ public static function tableName() { @@ -656,7 +669,7 @@ class UserView extends ActiveRecord } /** - * @inheritdoc + * {@inheritdoc} */ public function rules() { @@ -666,7 +679,7 @@ class UserView extends ActiveRecord } /** - * @inheritdoc + * {@inheritdoc} */ public function attributeLabels() { diff --git a/docs/guide/output-formatting.md b/docs/guide/output-formatting.md index 58134d6..2d9291a 100644 --- a/docs/guide/output-formatting.md +++ b/docs/guide/output-formatting.md @@ -144,12 +144,15 @@ echo Yii::$app->formatter->asTime('2014-10-06 12:41:00'); // 14:41:00 echo Yii::$app->formatter->asTime('2014-10-06 14:41:00 CEST'); // 14:41:00 ``` +If the [[yii\i18n\Formatter::timeZone|time zone]] is not set explicitly on the formatter component, the +[[yii\base\Application::timeZone|time zone configured in the application]] is used, which is the same time zone +as set in the PHP configuration. + > Note: As time zones are subject to rules made by the governments around the world and may change frequently, it is > likely that you do not have the latest information in the time zone database installed on your system. > You may refer to the [ICU manual](http://userguide.icu-project.org/datetime/timezone#TOC-Updating-the-Time-Zone-Data) > for details on updating the time zone database. Please also read -> [Setting up your PHP environment for internationalization](tutorial-i18n.md#setup-environment). - +> [Setting up your PHP environment for internationalization](tutorial-i18n.md#setup-environment). ## Formatting Numbers diff --git a/docs/guide/runtime-logging.md b/docs/guide/runtime-logging.md index b011bd0..bf226c8 100644 --- a/docs/guide/runtime-logging.md +++ b/docs/guide/runtime-logging.md @@ -18,7 +18,7 @@ In this section, we will mainly describe the first two steps. Recording log messages is as simple as calling one of the following logging methods: -* [[Yii::trace()]]: record a message to trace how a piece of code runs. This is mainly for development use. +* [[Yii::debug()]]: record a message to trace how a piece of code runs. This is mainly for development use. * [[Yii::info()]]: record a message that conveys some useful information. * [[Yii::warning()]]: record a warning message that indicates something unexpected has happened. * [[Yii::error()]]: record a fatal error that should be investigated as soon as possible. @@ -29,7 +29,7 @@ the log message to be recorded, while `$category` is the category of the log mes example records a trace message under the default category `application`: ```php -Yii::trace('start calculating average revenue'); +Yii::debug('start calculating average revenue'); ``` > Info: Log messages can be strings as well as complex data, such as arrays or objects. It is the responsibility @@ -43,7 +43,7 @@ is to use the PHP magic constant `__METHOD__` for the category names. This is al Yii framework code. For example, ```php -Yii::trace('start calculating average revenue', __METHOD__); +Yii::debug('start calculating average revenue', __METHOD__); ``` The `__METHOD__` constant evaluates as the name of the method (prefixed with the fully qualified class name) where @@ -70,7 +70,8 @@ in the application configuration, like the following: return [ // the "log" component must be loaded during bootstrapping time 'bootstrap' => ['log'], - + // the "log" component process messages with timestamp. Set PHP timezone to create correct timestamp + 'timeZone' => 'America/Los_Angeles', 'components' => [ 'log' => [ 'targets' => [ @@ -124,7 +125,7 @@ The [[yii\log\Target::levels|levels]] property takes an array consisting of one * `error`: corresponding to messages logged by [[Yii::error()]]. * `warning`: corresponding to messages logged by [[Yii::warning()]]. * `info`: corresponding to messages logged by [[Yii::info()]]. -* `trace`: corresponding to messages logged by [[Yii::trace()]]. +* `trace`: corresponding to messages logged by [[Yii::debug()]]. * `profile`: corresponding to messages logged by [[Yii::beginProfile()]] and [[Yii::endProfile()]], which will be explained in more details in the [Profiling](#performance-profiling) subsection. @@ -276,7 +277,7 @@ property of individual [log targets](#log-targets), like the following, ] ``` -Because of the flushing and exporting level setting, by default when you call `Yii::trace()` or any other logging +Because of the flushing and exporting level setting, by default when you call `Yii::debug()` or any other logging method, you will NOT see the log message immediately in the log targets. This could be a problem for some long-running console applications. To make each log message appear immediately in the log targets, you should set both [[yii\log\Dispatcher::flushInterval|flushInterval]] and [[yii\log\Target::exportInterval|exportInterval]] to be 1, diff --git a/docs/guide/runtime-requests.md b/docs/guide/runtime-requests.md index c1a137a..ec2703f 100644 --- a/docs/guide/runtime-requests.md +++ b/docs/guide/runtime-requests.md @@ -186,7 +186,7 @@ In case your proxies are using different headers you can use the request configu 'X-Forwarded-Proto', 'X-Proxy-User-Ip', 'Front-End-Https', - ];' + ]; 'ipHeaders' => [ 'X-Proxy-User-Ip', ], diff --git a/docs/guide/security-authorization.md b/docs/guide/security-authorization.md index cb8e06b..95b6f54 100644 --- a/docs/guide/security-authorization.md +++ b/docs/guide/security-authorization.md @@ -225,6 +225,8 @@ return [ 'components' => [ 'authManager' => [ 'class' => 'yii\rbac\DbManager', + // uncomment if you want to cache RBAC items hierarchy + // 'cache' => 'cache', ], // ... ], @@ -264,7 +266,7 @@ Building authorization data is all about the following tasks: Depending on authorization flexibility requirements the tasks above could be done in different ways. If your permissions hierarchy is meant to be changed by developers only, you can use either migrations or a console command. Migration pro is that it could be executed along with other migrations. Console -command pro is that you have a good overview of the hierarchy in the code rathe than it being scattered +command pro is that you have a good overview of the hierarchy in the code rather than it being scattered among multiple migrations. Either way in the end you'll get the following RBAC hierarchy: diff --git a/docs/guide/start-installation.md b/docs/guide/start-installation.md index b079752..f006f88 100644 --- a/docs/guide/start-installation.md +++ b/docs/guide/start-installation.md @@ -111,6 +111,30 @@ But there are other installation options available: you may consider installing the [Advanced Project Template](https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide/README.md). +Installing Assets +----------------- + +Yii relies on [Bower](http://bower.io/) and/or [NPM](https://www.npmjs.org/) packages for the asset (CSS and JavaScript) libraries installation. +It uses Composer to obtain these libraries, allowing PHP and CSS/JavaScript package versions to resolve at the same time. +This can be achieved either by usage of [asset-packagist.org](https://asset-packagist.org) or [composer asset plugin](https://github.com/francoispluchino/composer-asset-plugin/). +Please refer to [Assets documentation](structure-assets.md) for more details. + +You may want to either manage your assets via native Bower/NPM client, use CDN or avoid assets installation entirely. +In order to prevent assets installation via Composer, add the following lines to your 'composer.json': + +```json +"replace": { + "bower-asset/jquery": ">=1.11.0", + "bower-asset/inputmask": ">=3.2.0", + "bower-asset/punycode": ">=1.3.0", + "bower-asset/yii2-pjax": ">=2.0.0" +}, +``` + +> Note: in case of bypassing asset installation via Composer, you are responsible for the assets installation and resolving +> version collisions. Be prepared for possible inconsistencies among asset files from different extensions. + + Verifying the Installation -------------------------- @@ -212,7 +236,7 @@ DocumentRoot "path/to/basic/web" To use [Nginx](http://wiki.nginx.org/), you should install PHP as an [FPM SAPI](http://php.net/install.fpm). You may use the following Nginx configuration, replacing `path/to/basic/web` with the actual path for -`basic/web` and `mysite.local` with the actual hostname to serve. +`basic/web` and `mysite.test` with the actual hostname to serve. ```nginx server { @@ -222,7 +246,7 @@ server { listen 80; ## listen for ipv4 #listen [::]:80 default_server ipv6only=on; ## listen for ipv6 - server_name mysite.local; + server_name mysite.test; root /path/to/basic/web; index index.php; diff --git a/docs/guide/start-prerequisites.md b/docs/guide/start-prerequisites.md new file mode 100644 index 0000000..6956193 --- /dev/null +++ b/docs/guide/start-prerequisites.md @@ -0,0 +1,22 @@ +# What do you need to know + +Yii learning curve is not as steep as other PHP frameworks but still it requires some beforehand knowledge. + +## PHP + +Yii is a PHP framework so make sure you [read and understand language reference](http://php.net/manual/en/langref.php). + +## Object oriented programming + +Basic understanding of object oriented programming is required. If you're not familiar with it, check one of the many +tutorials available such as [the one from tuts+](https://code.tutsplus.com/tutorials/object-oriented-php-for-beginners--net-12762). + +Note that the more complicated your application is the more advanced OOP concepts your should learn in order to successfully +manage that complexity. + +## Command line and composer + +Yii extensively uses de-facto standard PHP package manager, [Composer](https://getcomposer.org/) so make sure you read +and understand its guide. If you are not familiar with using command line it is time to start trying. Once you'll +learn the basics you'll never want to work without it. + diff --git a/docs/guide/structure-assets.md b/docs/guide/structure-assets.md index 5e5979c..46f9313 100644 --- a/docs/guide/structure-assets.md +++ b/docs/guide/structure-assets.md @@ -194,8 +194,8 @@ class FontAwesomeAsset extends AssetBundle ]; public $publishOptions = [ 'only' => [ - 'fonts/', - 'css/', + 'fonts/*', + 'css/*', ] ]; } @@ -250,8 +250,8 @@ Visit [asset-packagist.org](https://asset-packagist.org) to know, how it works. ##### Using fxp/composer-asset-plugin -Comparing to to using asset-packagist, composer-asset-plugin does not require to change application config. Instead, it -requires to install a special Composer plugin globally by running the following command: +Compared to asset-packagist, composer-asset-plugin does not require any changes to application config. Instead, it +requires global installation of a special Composer plugin by running the following command: ```bash composer global require "fxp/composer-asset-plugin:^1.4.1" diff --git a/docs/guide/structure-filters.md b/docs/guide/structure-filters.md index bf03e37..8590c74 100644 --- a/docs/guide/structure-filters.md +++ b/docs/guide/structure-filters.md @@ -90,7 +90,7 @@ class ActionTimeFilter extends ActionFilter public function afterAction($action, $result) { $time = microtime(true) - $this->_startTime; - Yii::trace("Action '{$action->uniqueId}' spent $time second."); + Yii::debug("Action '{$action->uniqueId}' spent $time second."); return parent::afterAction($action, $result); } } diff --git a/docs/guide/structure-modules.md b/docs/guide/structure-modules.md index 255b545..245c90c 100644 --- a/docs/guide/structure-modules.md +++ b/docs/guide/structure-modules.md @@ -176,6 +176,14 @@ only contains the module ID, then the [[yii\base\Module::defaultRoute]] property will determine which controller/action should be used. This means a route `forum` would represent the `default` controller in the `forum` module. +URL manager routes should be added before [[yii\web\UrlManager::parseRequest()]] is fired. That means doing it +in module's `init()` won't work because module will be initialized when routes were already processed. Thus, routes +should be added at [bootstrap stage](structure-extensions.md#bootstrapping-classes). It is a also a good practice +to wrap module's URL rules with [[\yii\web\GroupUrlRule]]. + +In case module is used to [version API](rest-versioning.md), routes should be added directly in `urlManager` +section of the application config. + ### Accessing Modules diff --git a/docs/guide/test-fixtures.md b/docs/guide/test-fixtures.md index 55460be..9000442 100644 --- a/docs/guide/test-fixtures.md +++ b/docs/guide/test-fixtures.md @@ -154,7 +154,10 @@ You may also assign an alias to a fixture. In the above example, the `UserProfil In the test methods, you may then access a fixture object using its alias in `grabFixture()` method. For example, ```php -$profile = $I->grabFixture('profiles', 'user1');` will return the `UserProfileFixture` object. +$profile = $I->grabFixture('profiles', 'user1'); +``` + +will return the `UserProfileFixture` object. Because `UserProfileFixture` extends from `ActiveFixture`, you may further use the following syntax to access the data provided by the fixture: diff --git a/docs/guide/tutorial-i18n.md b/docs/guide/tutorial-i18n.md index 7962e0f..c470cea 100644 --- a/docs/guide/tutorial-i18n.md +++ b/docs/guide/tutorial-i18n.md @@ -416,7 +416,7 @@ while `one` matches `21` or `101`: These `other`, `few`, `many` and other special argument names vary depending on language. To learn which ones you should specify for a particular locale, please refer to "Plural Rules, Cardinal" at [http://intl.rmcreative.ru/](http://intl.rmcreative.ru/). -Alternatively you can refer to [rules reference at unicode.org](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html). +Alternatively you can refer to [rules reference at unicode.org](http://cldr.unicode.org/index/cldr-spec/plural-rules). > Note: The above example Russian message is mainly used as a translated message, not an original message, unless you set > the [[yii\base\Application::$sourceLanguage|source language]] of your application as `ru-RU` and translating from Russian. diff --git a/docs/guide/tutorial-yii-as-micro-framework.md b/docs/guide/tutorial-yii-as-micro-framework.md index 896e593..d0d0277 100644 --- a/docs/guide/tutorial-yii-as-micro-framework.md +++ b/docs/guide/tutorial-yii-as-micro-framework.md @@ -104,6 +104,7 @@ At this point the project structure should look like this: ``` micro-app/ ├── composer.json +├── config.php ├── web/ └── index.php └── controllers/ diff --git a/docs/internals-ru/git-workflow.md b/docs/internals-ru/git-workflow.md index 123dc98..a226549 100644 --- a/docs/internals-ru/git-workflow.md +++ b/docs/internals-ru/git-workflow.md @@ -1,29 +1,29 @@ Рабочий процесс Git для разработчиков Yii 2 =========================================== -Итак, вы хотите разрабатывать Yii? Хорошо! Но для того чтоб увеличить шанс принятия ваших изменений, -пожалуйста следуйте следующим шагам. Если вы новичок в git и github, вы можете сначала проверить -[github help](http://help.github.com/), [try git](https://try.github.com) или прочитать о +Итак, вы хотите разрабатывать Yii? Хорошо! Но для того, чтобы увеличить шанс принятия ваших изменений, +пожалуйста, следуйте следующим шагам. Если вы новичок в git и Github, вы можете сначала проверить +[Github help](http://help.github.com/), [try git](https://try.github.com) или прочитать о [внутренней модели данных git](http://nfarina.com/post/9868516270/git-is-simpler). Подготовка вашего рабочего окружения ------------------------------------ -Следующие шаги будут создавать рабочее окружение для Yii, которое вы можете использовать для работы над основным кодом +Следующие шаги создадут рабочее окружение для Yii, которое вы можете использовать для работы над основным кодом фреймворка. *Эти шаги будут нужны только в первый раз*. -### 1. [Форкаем](http://help.github.com/fork-a-repo/) репозиторий Yii на github и клонируйте ваш форк в ваше рабочее окружение. +### 1. [Сделайте форк](http://help.github.com/fork-a-repo/) репозитория Yii на Github и клонируйте этот форк в ваше рабочее окружение. ``` git clone git@github.com:YOUR-GITHUB-USERNAME/yii2.git ``` -Если у вас есть проблемы с настройкой GIT для работы с GitHub в Linux, или вы получаете ошибку похожую на "Permission Denied -(publickey)", тогда вы должны настроить ваш GIT по [этой инструкции](http://help.github.com/linux-set-up-git/) +Если у вас есть проблемы с настройкой Git для работы с GitHub в Linux, или вы получаете ошибку похожую на "Permission Denied +(publickey)", тогда вы должны настроить ваш Git по [этой инструкции](http://help.github.com/linux-set-up-git/) -### 2. Добавляем главный репозиторий Yii как дополнительный внешний git репозиторий называемый "upstream" +### 2. Добавьте главный репозиторий Yii как дополнительный внешний git репозиторий называемый "upstream" -Перейдите в каталог, куда вы склонировали Yii, как правило "yii2". Затем введите следующую команду: +Перейдите в каталог куда вы склонировали Yii, как правило "yii2". Затем введите следующую команду: ``` git remote add upstream git://github.com/yiisoft/yii2.git @@ -33,11 +33,20 @@ git remote add upstream git://github.com/yiisoft/yii2.git Следующие шаги не обязательны, если вы хотите работать только с переводом или документацией. -- выполните `composer update` для установки зависимостей (если [composer у вас установлен глобально](https://getcomposer.org/doc/00-intro.md#globally)). +- выполните `composer install` для установки зависимостей + (если [composer у вас установлен глобально](https://getcomposer.org/doc/00-intro.md#globally)). -> Note: Если вы видите такие ошибки, как `Problem 1 The requested package bower-asset/jquery could not be found in +> Note: если вы видите такие ошибки, как `Problem 1 The requested package bower-asset/jquery could not be found in > any version, there may be a typo in the package name.`, необходимо запустить `composer global require "fxp/composer-asset-plugin:^1.4.1"` +Если вы планируете работать с Javascript: + +- выполните `npm install` для установки зависимостей и программ тестирования Javascript + (если [Node.js and NPM установлен](https://nodejs.org/en/download/package-manager/)). + +> Note: тесты JavaScript зависят от библиотеки jsdom, которой требуется Node.js 4 или более новый. +> Предпочтительнее использовать Node.js 6 or 7. + - выполните `php build/build dev/app basic` для клонирования базового приложения и установки его зависимостей. Эта команда установит сторонние пакеты composer обычным образом, но создаст ссылку с репозитория yii2 на только что загруженный репозиторий. Таким образом у вас будет только один экземпляр кода. @@ -56,13 +65,16 @@ git remote add upstream git://github.com/yiisoft/yii2.git ### Модульные тесты Вы можете выполнить модульные тесты с помощью команды `phpunit` в корневой директории приложения. Если у вас phpunit -не установлен глобально, вы можете запустить `php vendor/bin/phpunit`. +не установлен глобально, вы можете запустить `php vendor/bin/phpunit` или `vendor/bin/phpunit.bat` в случае +использования OS Windows. Некоторые тесты требуют дополнительно установки и настройки баз данных. Вы можете создать `tests/data/config.local.php` для переопределения настроек, которые определены в `tests/data/config.php`. -Вы можете ограничить тестирование группой тестов, с которой вы сейчас работаете, например запускать только тесты для -валидаторов и redis. Вы можете получить список доступных групп выполнив `phpunit --list-groups`. +Вы можете ограничить тестирование группой тестов, с которой вы сейчас работаете. Например, запускать только тесты для +валидаторов и redis: `phpunit --group=validators,redis`. Вы можете получить список доступных групп выполнив `phpunit --list-groups`. + +Вы можете запустить модульные тесты JavaScript с помощью команды `npm test` в корневой директории приложения. ### Расширения @@ -70,15 +82,16 @@ git remote add upstream git://github.com/yiisoft/yii2.git сделать это: ``` -php build/build dev/ext +php build/build dev/ext ``` -где `` это имя расширения, например `redis`. +где `` это имя расширения, например `redis` и `` это URL вашего форка расширения, например +`git@github.com:my_nickname/yii2-redis.git`. Если вы контрибьютор ядра фреймворка, вы можете не указывать ``. Если вы хотите протестировать расширение в одном из шаблонов приложений, просто добавьте его в `composer.json` приложения, например добавив `"yiisoft/yii2-redis": "~2.0.0"` в секцию `require` базового приложения. Запустите `php build/build dev/app basic` для установки расширения и его зависимостей и создания символической -ссылки на `extensions/redis` так чтоб вы работали не папке вендорных пакетов composer, а напрямую в репозиторий yii2. +ссылки на `extensions/redis` так чтоб вы работали не папке вендорных пакетов composer, а напрямую в репозитории yii2. > Note: по умолчанию URL репозиториев git на GitHub работают через SSH. Чтобы использовать HTTPS, добавьте > флаг `--useHttp` к команде `build`. @@ -94,21 +107,21 @@ php build/build dev/ext Потратьте несколько минут на поиск существующей issue, которая соответствует вашим изменениям. Если вы найдёте её в списке, то пожалуйста оставьте комментарий, что вы начали над ней работать. Если вы не нашли нужной issue пожалуйста [создайте новую issue](report-an-issue.md) или создайте сразу запрос на изменения если это простые изменения. -Это позволит команде проверить ваше предложение, и обеспечивать соответствующую обратную связь. +Это позволит команде проверить ваше предложение, и обеспечить соответствующую обратную связь. > Для небольших изменений или документации, или простых исправлений, вам нет необходимости создавать issue, запрос на изменения в этом случае подходит лучше. -### 2. Вытягивание последнего кода из основного репозитория Yii +### 2. Получите последний код из основного репозитория Yii ``` -git fetch upstream +git pull upstream ``` -Вы должны начинать с этого действия работу над каждым новым предложением, убеждайтесь что вы работаете над самой +Вы должны начинать с этого действия работу над каждым новым предложением. Убедитесь, что вы работаете с самой последней версией кода. -### 3. Создание новой ветки для ваших изменений, основанных на текущем мастере Yii +### 3. Сделайте новую ветку для ваших изменений, основанных на текущей ветке master в Yii > Это очень важно, так как вы не сможете отправлять более одного запроса на изменения из вашего репозитория, если будете использовать ветку master. @@ -123,7 +136,7 @@ git checkout upstream/master git checkout -b 999-name-of-your-branch-goes-here ``` -### 4. Делайте свою магию, пишите ваш код +### 4. Делайте свою магию, пишите свой код Убедитесь, что он работает :) @@ -145,7 +158,7 @@ Enh #999: a description of the enhancement (Your Name) Для очень маленьких исправлений, например опечаток и изменений документации, нет необходимости обновлять CHANGELOG. -### 6. Фиксация ваших изменений +### 6. Зафиксируйте изменения Добавляем файлы/изменения которые вы хотите зафиксировать в [staging area](http://gitref.org/basic/#add) @@ -155,14 +168,14 @@ git add path/to/my/file.php Вы можете использовать опцию `-p` для того, чтоб выбрать, какие изменения вы хотите добавить в коммит. -Фиксируйте ваши изменения с описательным сообщением. Убедитесь что в сообщение есть номер `#XXX`, так github -автоматически свяжет ваш коммит с тикетом: +Фиксируйте ваши изменения с описательным сообщением. Убедитесь, что в сообщении есть номер `#XXX`, так Github +автоматически свяжет ваш коммит с issue: ``` git commit -m "A brief description of this change which fixes #999 goes here" ``` -### 7. Получение последнего кода из апстрима Yii в вашу ветку +### 7. Получите последний код из upstream Yii в вашу ветку ``` git pull upstream master @@ -172,18 +185,18 @@ git pull upstream master какие-либо конфликты слияния, вы должны исправить их и зафиксировать изменения ещё раз. Это гарантирует, что команда Yii сможет слить ваши изменения одним кликом. -### 8. Разрешив зависимости, отправляем код на github +### 8. Разрешив зависимости, отправьте код на Github ``` git push -u origin 999-name-of-your-branch-goes-here ``` -Опция `-u` сохранит указание на ветку в github, чтобы при следующем выполнении `git push`, git знал, куда отправлять +Опция `-u` сохранит указание на ветку в Github, чтобы при следующем выполнении `git push`, git знал, куда отправлять изменения. Это полезно, если вы хотите позже отправлять ещё коммиты в этот запрос на слияние. -### 9. Открываем [запрос на слияние](http://help.github.com/send-pull-requests/) в *upstream*. +### 9. Откройте [запрос на слияние](http://help.github.com/send-pull-requests/) в *upstream*. -Перейдите в репозиторий на github и нажмите "Pull Request", выберите ветку справа и введите больше информации +Перейдите в репозиторий на Github и нажмите "Pull Request", выберите ветку справа и введите больше информации в поле комментариев. Чтобы связать запрос на изменение с issue, добавьте в комментарий `#999` - где 999 это номер issue. > Обратите внимание, что каждый запрос на слияние должен исправлять единственное изменение. Для множества независимых @@ -191,10 +204,10 @@ git push -u origin 999-name-of-your-branch-goes-here ### 10. Проверка вашего кода кем-то -Кто-то будет проверять ваш код, и, возможно, вам будет предложено внести некоторые изменения, если это так, то перейдите +Кто-то будет проверять ваш код, и, возможно, вам будет предложено внести некоторые изменения. Eсли это так, то перейдите к шагу #6 (вам не надо открывать новый запрос на слияние, если текущий ещё открыт). Если код будет принят, он будет -влит в основную ветку и станет частью следующего релиза Yii. Если нет, не унывайте, разным людям необходимы различные -функции и Yii не может реализовывать всё для всех, ваш код будет ещё доступен на github как ссылка для людей кому он +влит в основную ветку и станет частью следующего релиза Yii. Если нет - не унывайте, разным людям необходимы различные +функции и Yii не может реализовывать всё для всех, ваш код будет ещё доступен на Github как ссылка для людей кому он может пригодится. ### 11. Очистка @@ -210,16 +223,16 @@ git push origin --delete 999-name-of-your-branch-goes-here ### Примечание -Для обнаружения регрессии как можно раньше, каждое слияние кодовой базы Yii на github будет подхвачено +Для обнаружения регрессии как можно раньше, каждое слияние кодовой базы Yii на Github будет подхвачено [Travis CI](http://travis-ci.org) для автоматического запуска тестов. Люди из *core team* не хотят нагружать этот сервис, поэтому добавляют текст [`[ci skip]`](http://about.travis-ci.org/docs/user/how-to-skip-a-build/) в описание запроса на слияние, в следующих ситуациях: -* затронуты только javascript, css файлы или файлы изображений, +* затронуты только JavaScript, CSS файлы или файлы изображений, * обновление документации, * изменения затрагивают только строки (например обновление переводов). -Это защитит travis от запуска тестов на изменениях, которые не покрыты тестами. +Это защитит Travis CI от запуска тестов на изменениях, которые не покрыты тестами. ### Обзор команд (для продвинутых участников) diff --git a/docs/internals/README.md b/docs/internals/README.md index e1994a9..d8ac9c1 100644 --- a/docs/internals/README.md +++ b/docs/internals/README.md @@ -42,3 +42,7 @@ Misc ### Exception Hierarchy ![Yii Framework Exception Hierarchy](exception_hierarchy.png) + +### Database testing + +[Here](https://gist.github.com/sergeymakinen/0696a5952f160ea28d7b64c3adfecf6f) is config for test environments for all supported Yii databases. diff --git a/docs/internals/git-workflow.md b/docs/internals/git-workflow.md index bdb09e4..a1dd877 100644 --- a/docs/internals/git-workflow.md +++ b/docs/internals/git-workflow.md @@ -111,10 +111,10 @@ review your suggestion, and provide appropriate feedback along the way. > For small changes or documentation issues or straightforward fixes, you don't need to create an issue, a pull request is enough in this case. -### 2. Fetch the latest code from the main Yii branch +### 2. Pull the latest code from the main Yii branch ``` -git fetch upstream +git pull upstream ``` You should start at this point for every new contribution to make sure you are working on the latest code. diff --git a/docs/internals/release.md b/docs/internals/release.md index 35d092d..c5c0eb7 100644 --- a/docs/internals/release.md +++ b/docs/internals/release.md @@ -53,13 +53,13 @@ You may run it with `--update` to fetch tags for all repos to get the newest inf Making a framework release includes the following commands (apps are always released together with the framework): - ./build release framework - ./build release app-basic - ./build release app-advanced + ./build/build release framework + ./build/build release app-basic + ./build/build release app-advanced Making an extension release includes only one command (e.g. for redis): - ./build release redis + ./build/build release redis The default release command will release a new minor version from the currently checked out branch. To release another version than the default, you have to specify it using the `--version` option, e.g. diff --git a/framework/BaseYii.php b/framework/BaseYii.php index a0b2aef..eb5acd9 100644 --- a/framework/BaseYii.php +++ b/framework/BaseYii.php @@ -7,8 +7,8 @@ namespace yii; +use yii\base\InvalidArgumentException; use yii\base\InvalidConfigException; -use yii\base\InvalidParamException; use yii\base\UnknownClassException; use yii\di\Container; use yii\log\Logger; @@ -125,7 +125,7 @@ class BaseYii * @param bool $throwException whether to throw an exception if the given alias is invalid. * If this is false and an invalid alias is given, false will be returned by this method. * @return string|bool the path corresponding to the alias, false if the root alias is not previously registered. - * @throws InvalidParamException if the alias is invalid while $throwException is true. + * @throws InvalidArgumentException if the alias is invalid while $throwException is true. * @see setAlias() */ public static function getAlias($alias, $throwException = true) @@ -151,7 +151,7 @@ class BaseYii } if ($throwException) { - throw new InvalidParamException("Invalid path alias: $alias"); + throw new InvalidArgumentException("Invalid path alias: $alias"); } return false; @@ -211,7 +211,7 @@ class BaseYii * - a path alias (e.g. `@yii/base`). In this case, the path alias will be converted into the * actual path first by calling [[getAlias()]]. * - * @throws InvalidParamException if $path is an invalid alias. + * @throws InvalidArgumentException if $path is an invalid alias. * @see getAlias() */ public static function setAlias($alias, $path) @@ -380,15 +380,16 @@ class BaseYii } /** - * Logs a trace message. + * Logs a debug message. * Trace messages are logged mainly for development purpose to see * the execution work flow of some code. This method will only log * a message when the application is in debug mode. * @param string|array $message the message to be logged. This can be a simple string or a more * complex data structure, such as array. * @param string $category the category of the message. + * @since 2.0.14 */ - public static function trace($message, $category = 'application') + public static function debug($message, $category = 'application') { if (YII_DEBUG) { static::getLogger()->log($message, Logger::LEVEL_TRACE, $category); @@ -396,6 +397,18 @@ class BaseYii } /** + * Alias of [[debug()]]. + * @param string|array $message the message to be logged. This can be a simple string or a more + * complex data structure, such as array. + * @param string $category the category of the message. + * @deprecated 2.0.14 Use [[debug()]] + */ + public static function trace($message, $category = 'application') + { + static::debug($message, $category); + } + + /** * Logs an error message. * An error message is typically logged when an unrecoverable error occurs * during the execution of an application. @@ -472,6 +485,7 @@ class BaseYii /** * Returns an HTML hyperlink that can be displayed on your Web page showing "Powered by Yii Framework" information. * @return string an HTML hyperlink that can be displayed on your Web page showing "Powered by Yii Framework" information + * @deprecated 2.0.14 */ public static function powered() { diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index eef4a5d..55d1386 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -4,7 +4,130 @@ Yii Framework 2 Change Log 2.0.14 under development ------------------------ -- no changes in this release. +- Bug #15644: Avoid wrong default selection on a dropdown, checkbox list, and radio list, when a option has a key equals to zero (berosoboy) +- Enh #14538: Added `yii\behaviors\AttributeTypecastBehavior::typecastAfterFind` property (littlefuntik, silverfire) +- Enh #14254: add an option to specify whether validator is forced to always use master DB for `yii\validators\UniqueValidator` and `yii\validators\ExistValidator` (rossoneri, samdark) +- Enh #15272: Removed type attribute from script tag (aleksbelic) +- Enh #15120: Refactored dynamic caching introducing `DynamicContentAwareInterface` and `DynamicContentAwareTrait` (sergeymakinen) +- Bug #8983: Only truncate the original log file for rotation (matthewyang, developeruz) +- Bug #11401: Fixed `yii\web\DbSession` concurrency issues when writing and regenerating IDs (samdark, andreasanta, cebe) +- Bug #13034: Fixed `normalizePath` for windows network shares that start with two backslashes (developeruz) +- Bug #14135: Fixed `yii\web\Request::getBodyParam()` crashes on object type body params (klimov-paul) +- Bug #14157: Add support for loading default value `CURRENT_TIMESTAMP` of MySQL `datetime` field (rossoneri) +- Bug #14276: Fixed I18N format with dotted parameters (developeruz) +- Bug #14296: Fixed log targets to throw exception in case log can not be properly exported (bizley) +- Bug #14484: Fixed `yii\validators\UniqueValidator` for target classes with a default scope (laszlovl, developeruz) +- Bug #14604: Fixed `yii\validators\CompareValidator` `compareAttribute` does not work if `compareAttribute` form ID has been changed (mikk150) +- Bug #14711: Fixed `yii\web\ErrorHandler` displaying exception message in non-debug mode (samdark) +- Bug #14811: Fixed `yii\filters\HttpCache` to work with PHP 7.2 (samdark) +- Bug #14859: Fixed OCI DB `defaultSchema` failure when `masterConfig` is used (lovezhl456) +- Bug #14903: Fixed route with extra dashes is executed controller while it should not (developeruz) +- Bug #14916: Fixed `yii\db\Query::each()` iterator key starts from 1 instead of 0 (Vovan-VE) +- Bug #14980: Fix looping in `yii\i18n\MessageFormatter` tokenize pattern if pattern is invalid (uaoleg, developeruz) +- Bug #15031: Fixed incorrect string type length detection for OCI DB schema (Murolike) +- Bug #15046: Throw an `yii\web\HeadersAlreadySentException` if headers were sent before web response (dmirogin) +- Bug #15122: Fixed `yii\db\Command::getRawSql()` to properly replace expressions (hiscaler, samdark) +- Bug #15142: Fixed array params replacing in `yii\helpers\BaseUrl::current()` (IceJOKER) +- Bug #15169: Fixed translating a string when NULL parameter is passed (developeruz) +- Bug #15194: Fixed `yii\db\QueryBuilder::insert()` to preserve passed params when building a `INSERT INTO ... SELECT` query for MSSQL, PostgreSQL and SQLite (sergeymakinen) +- Bug #15229: Fixed `yii\console\widgets\Table` default value for `getScreenWidth()`, when `Console::getScreenSize()` can't determine screen size (webleaf) +- Bug #15234: Fixed `\yii\widgets\LinkPager` removed `tag` from `disabledListItemSubTagOptions` (SDKiller) +- Bug #15249: Controllers in subdirectories were not visible in commands list (IceJOKER) +- Bug #15270: Resolved potential race conditions when writing generated php-files (kalessil) +- Bug #15300: Fixed "Cannot read property 'style' of undefined" error at the error screen (vitorarantes) +- Bug #15301: Fixed `ArrayHelper::filter()` to work properly with `0` in values (hhniao) +- Bug #15302: Fixed `yii\caching\DbCache` so that `getValues` now behaves the same as `getValue` with regards to streams (edwards-sj) +- Bug #15317: Regenerate CSRF token if an empty value is given (sammousa) +- Bug #15320: Fixed special role checks in `yii\filters\AccessRule::matchRole()` (Izumi-kun) +- Bug #15322: Fixed PHP 7.2 compatibility of `FileHelper::getExtensionsByMimeType()` (samdark) +- Bug #15353: Remove side effect of ActiveQuery::getTablesUsedInFrom() introduced in 2.0.13 (terales) +- Bug #15355: Fixed `yii\db\Query::from()` does not work with `yii\db\Expression` (vladis84, silverfire, samdark) +- Bug #15356: Fixed multiple bugs in `yii\db\Query::getTablesUsedInFrom()` (vladis84, samdark) +- Bug #15380: `FormatConverter::convertDateIcuToPhp()` now converts `a` ICU symbols to `A` (brandonkelly) +- Bug #15407: Fixed rendering rows with associative arrays in `yii\console\widgets\Table` (dmrogin) +- Bug #15432: Fixed wrong value being set in `yii\filters\RateLimiter::checkRateLimit()` resulting in wrong `X-Rate-Limit-Reset` header value (bizley) +- Bug #15440: Fixed `yii\behaviors\AttributeTypecastBehavior::$attributeTypes` auto-detection fails for rule, which specify attribute with '!' prefix (klimov-paul) +- Bug #15462: Fixed `accessChecker` configuration error (developeruz) +- Bug #15494: Fixed missing `WWW-Authenticate` header (developeruz) +- Bug #15522: Fixed `yii\db\ActiveRecord::refresh()` method does not use an alias in the condition (vladis84) +- Bug #15523: `yii\web\Session` settings could now be configured after session is started (StalkAlex, rob006, daniel1302, samdark) +- Bug #15536: Fixed `yii\widgets\ActiveForm::init()` for call `parent::init()` (panchenkodv) +- Bug #15540: Fixed `yii\db\ActiveRecord::with()` unable to use relation defined via attached behavior in case `asArray` is enabled (klimov-paul) +- Bug #15553: Fixed `yii\validators\NumberValidator` incorrectly validate resource (developeruz) +- Bug #15621: Fixed `yii\web\User::getIdentity()` returning `null` if an exception had been thrown when it was called previously (brandonkelly) +- Enh #3087: Added `yii\helpers\BaseHtml::error()` "errorSource" option to be able to customize errors display (yanggs07, developeruz, silverfire) +- Enh #3250: Added support for events partial wildcard matching (klimov-paul) +- Enh #5515: Added default value for `yii\behaviors\BlameableBehavior` for cases when the user is guest (dmirogin) +- Enh #6844: `yii\base\ArrayableTrait::toArray()` now allows recursive `$fields` and `$expand` (bboure) +- Enh #7988: Added `\yii\helpers\Console::errorSummary()` and `\yii\helpers\Json::errorSummary()` (developeruz) +- Enh #7996: Short syntax for verb in GroupUrlRule (schojniak, developeruz) +- Enh #8092: ExistValidator for relations (developeruz) +- Enh #8527: Added `yii\i18n\Locale` component having `getCurrencySymbol()` method (amarox, samdark) +- Enh #8752: Allow specify `$attributeNames` as a string for `yii\base\Model` `validate()` method (developeruz) +- Enh #9137: Added `Access-Control-Allow-Method` header for the OPTIONS request (developeruz) +- Enh #9253: Allow `variations` to be a string for `yii\filters\PageCache` and `yii\widgets\FragmentCache` (schojniak, developeruz) +- Enh #9771: Assign hidden input with its own set of HTML options via `$hiddenOptions` in activeFileInput `$options` (HanafiAhmat) +- Enh #10186: Use native `hash_equals` in `yii\base\Security::compareString()` if available, throw exception if non-strings are compared (aotd1, samdark) +- Enh #11611: Added `BetweenColumnsCondition` to build SQL condition like `value BETWEEN col1 and col2` (silverfire) +- Enh #12623: Added `yii\helpers\StringHelper::matchWildcard()` replacing usage of `fnmatch()`, which may be unreliable (klimov-paul) +- Enh #13019: Support JSON in SchemaBuilderTrait (zhukovra, undefinedor) +- Enh #13465: Added `yii\helpers\FileHelper::findDirectory()` method (ArsSirek, developeruz) +- Enh #13618: Active record now resets related models after corresponding attributes updates (Kolyunya, rob006) +- Enh #13679: Added `yii\behaviors\CacheableWidgetBehavior` (Kolyunya) +- Enh #13814: MySQL unique index names can now contain spaces (df2) +- Enh #13879: Added upsert support for `yii\db\QueryBuilder` and `yii\db\Command` (sergeymakinen) +- Enh #13919: Added option to add comment for created table to migration console command (mixartemev, developeruz) +- Enh #13996: Added `yii\web\View::registerJsVar()` method that allows registering JavaScript variables (Eseperio, samdark) +- Enh #14043: Added `yii\helpers\IpHelper` (silverfire, cebe) +- Enh #14355: Added ability to pass an empty array as a parameter in console command (developeruz) +- Enh #14488: Added support for X-Forwarded-Host to `yii\web\Request`, fixed `getServerPort()` usage (si294r, samdark) +- Enh #14546: Added `dataDirectory` property into `BaseActiveFixture` (leandrogehlen) +- Enh #14568: Refactored migration templates to use `safeUp()` and `safeDown()` methods (Kolyunya) +- Enh #14638: Added `yii\db\SchemaBuilderTrait::tinyInteger()` (rob006) +- Enh #14643: Added `yii\web\ErrorAction::$layout` property to conveniently set layout from error action config (swods, cebe, samdark) +- Enh #14662: Added support for custom `Content-Type` specification to `yii\web\JsonResponseFormatter` (Kolyunya) +- Enh #14732, #11218, #14810, #10855: It is now possible to pass `yii\db\Query` anywhere, where `yii\db\Expression` was supported (silverfire) +- Enh #14806: Added $placeFooterAfterBody option for GridView (terehru) +- Enh #15024: `yii\web\Pjax` widget does not prevent CSS files from sending anymore because they are handled by client-side plugin correctly (onmotion) +- Enh #15047: `yii\db\Query::select()` and `yii\db\Query::addSelect()` now check for duplicate column names (wapmorgan) +- Enh #15135: Automatic completion for help in bash and zsh (Valkeru) +- Enh #15216: Added `yii\web\ErrorHandler::$traceLine` to allow opening file at line clicked in IDE (vladis84) +- Enh #15219: Added `yii\filters\auth\HttpHeaderAuth` (bboure) +- Enh #15221: Added support for specifying `--camelCase` console options in `--kebab-case` (brandonkelly) +- Enh #15221: Added support for the `--