Commit f6c6fe27 by Alexander Makarov

Merge branch 'master'

Conflicts: framework/CHANGELOG.md
parents 8bdc437b c442bf63
......@@ -23,6 +23,7 @@
"yiisoft/yii2-codeception": "*",
"codeception/codeception": "*",
"codeception/specify": "*",
"codeception/verify": "*",
"yiisoft/yii2-debug": "*",
"yiisoft/yii2-gii": "*"
},
......
......@@ -39,15 +39,16 @@ class ContactFormTest extends TestCase
$model->contact('admin@example.com');
$this->specify('email should be send', function () {
$this->assertFileExists($this->getMessageFile(), 'email file should exist');
expect('email file should exist', file_exists($this->getMessageFile()))->true();
});
$this->specify('message should contain correct data', function () use($model) {
$emailMessage = file_get_contents($this->getMessageFile());
$this->assertContains($model->name, $emailMessage, 'email should contain user name');
$this->assertContains($model->email, $emailMessage, 'email should contain sender email');
$this->assertContains($model->subject, $emailMessage, 'email should contain subject');
$this->assertContains($model->body, $emailMessage, 'email should contain body');
expect('email should contain user name', $emailMessage)->contains($model->name);
expect('email should contain sender email', $emailMessage)->contains($model->email);
expect('email should contain subject', $emailMessage)->contains($model->subject);
expect('email should contain body', $emailMessage)->contains($model->body);
});
}
......
......@@ -19,8 +19,8 @@ class LoginFormTest extends TestCase
$model->password = 'some_password';
$this->specify('user should not be able to login, when there is no identity' , function () use ($model) {
$this->assertFalse($model->login());
$this->assertTrue(Yii::$app->user->isGuest,'user should not be logged in');
expect('model should not login user', $model->login())->false();
expect('user should not be logged in', Yii::$app->user->isGuest)->true();
});
}
......@@ -32,9 +32,9 @@ class LoginFormTest extends TestCase
$model->password = 'wrong-password';
$this->specify('user should not be able to login with wrong password', function () use ($model) {
$this->assertFalse($model->login());
$this->assertArrayHasKey('password', $model->errors);
$this->assertTrue(Yii::$app->user->isGuest, 'user should not be logged in');
expect('model should not login user', $model->login())->false();
expect('error message should be set', $model->errors)->hasKey('password');
expect('user should not be logged in', Yii::$app->user->isGuest)->true();
});
}
......@@ -46,9 +46,9 @@ class LoginFormTest extends TestCase
$model->password = 'demo';
$this->specify('user should be able to login with correct credentials', function() use ($model) {
$this->assertTrue($model->login());
$this->assertArrayNotHasKey('password', $model->errors);
$this->assertFalse(Yii::$app->user->isGuest,'user should be logged in');
expect('model should login user', $model->login())->true();
expect('error message should not be set', $model->errors)->hasntKey('password');
expect('user should be logged in', Yii::$app->user->isGuest)->false();
});
}
......
......@@ -248,7 +248,7 @@ public function editArticle($id)
throw new NotFoundHttpException;
}
if (!\Yii::$app->user->checkAccess('edit_article', ['article' => $article])) {
throw new AccessDeniedHttpException;
throw new ForbiddenHttpException;
}
// ...
}
......
......@@ -88,7 +88,7 @@ class UserProfileFixture extends ActiveFixture
public $modelClass = 'app\models\UserProfile';
public $depends = ['app\tests\fixtures\UserFixture'];
}
```
In the above, we have shown how to define a fixture about a DB table. To define a fixture not related with DB
(e.g. a fixture about certain files and directories), you may extend from the more general base class
......
......@@ -12,18 +12,20 @@ defined('YII_DEBUG') or define('YII_DEBUG', false);
$composerAutoload = [
__DIR__ . '/vendor/autoload.php', // standalone with "composer install" run
__DIR__ . '/../autoload.php', // script is installed as a composer binary
__DIR__ . '/../../autoload.php', // script is installed as a composer binary
];
$vendorPath = null;
foreach($composerAutoload as $autoload) {
if (file_exists($autoload)) {
require($autoload);
$vendorPath = dirname($autoload);
break;
}
}
$yiiDirs = [
__DIR__ . '/../../framework', // in yii2-dev repo
__DIR__ . '/vendor/yiisoft/yii2', // standalone with "composer install" run
__DIR__ . '/../yiisoft/yii2', // script is installed as a composer binary
__DIR__ . '/../../yiisoft/yii2', // script is installed as a composer binary
];
foreach($yiiDirs as $dir) {
if (file_exists($dir . '/Yii.php')) {
......@@ -45,5 +47,8 @@ $application = new yii\console\Application([
'controllerNamespace' => 'yii\\apidoc\\commands',
'controllerPath' => '@yii/apidoc/commands',
]);
if ($vendorPath !== null) {
$application->setVendorPath($vendorPath);
}
$exitCode = $application->run();
exit($exitCode);
......@@ -20,6 +20,7 @@
"minimum-stability": "dev",
"require": {
"yiisoft/yii2": "*",
"yiisoft/yii2-bootstrap": "*",
"phpdocumentor/reflection": "dev-master | >1.0.2"
},
"autoload": {
......
......@@ -154,7 +154,7 @@ class TypeDoc extends BaseDoc
{
parent::__construct($reflector, $config);
$this->namespace = StringHelper::basename($this->name);
$this->namespace = StringHelper::dirname($this->name);
if ($reflector === null) {
return;
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\apidoc\templates\bootstrap;
use yii\apidoc\models\Context;
use yii\console\Controller;
use Yii;
use yii\helpers\Console;
use yii\helpers\FileHelper;
/**
*
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
class Renderer extends \yii\apidoc\templates\html\Renderer
{
public $layout = '@yii/apidoc/templates/bootstrap/views/bootstrap.php';
public $indexView = '@yii/apidoc/templates/bootstrap/views/index.php';
public $pageTitle = 'Yii Framework 2.0 API Documentation';
}
\ No newline at end of file
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\apidoc\templates\bootstrap;
use Yii;
use yii\base\InvalidConfigException;
use yii\bootstrap\BootstrapAsset;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
/**
* Nav renders a nav HTML component.
*
* For example:
*
* ```php
* echo Nav::widget([
* 'items' => [
* [
* 'label' => 'Home',
* 'url' => ['site/index'],
* 'linkOptions' => [...],
* ],
* [
* 'label' => 'Dropdown',
* 'items' => [
* ['label' => 'Level 1 - Dropdown A', 'url' => '#'],
* '<li class="divider"></li>',
* '<li class="dropdown-header">Dropdown Header</li>',
* ['label' => 'Level 1 - Dropdown B', 'url' => '#'],
* ],
* ],
* ],
* ]);
* ```
*
* Note: Multilevel dropdowns beyond Level 1 are not supported in Bootstrap 3.
*
* @see http://getbootstrap.com/components.html#dropdowns
* @see http://getbootstrap.com/components/#nav
*
* @author Antonio Ramirez <amigo.cobos@gmail.com>
* @since 2.0
*/
class SideNavWidget extends \yii\bootstrap\Widget
{
/**
* @var array list of items in the nav widget. Each array element represents a single
* menu item which can be either a string or an array with the following structure:
*
* - label: string, required, the nav item label.
* - url: optional, the item's URL. Defaults to "#".
* - visible: boolean, optional, whether this menu item is visible. Defaults to true.
* - linkOptions: array, optional, the HTML attributes of the item's link.
* - options: array, optional, the HTML attributes of the item container (LI).
* - active: boolean, optional, whether the item should be on active state or not.
* - items: array|string, optional, the configuration array for creating a [[Dropdown]] widget,
* or a string representing the dropdown menu. Note that Bootstrap does not support sub-dropdown menus.
*
* If a menu item is a string, it will be rendered directly without HTML encoding.
*/
public $items = [];
/**
* @var boolean whether the nav items labels should be HTML-encoded.
*/
public $encodeLabels = true;
/**
* @var string the route used to determine if a menu item is active or not.
* If not set, it will use the route of the current request.
* @see params
* @see isItemActive
*/
public $activeUrl;
/**
* Initializes the widget.
*/
public function init()
{
parent::init();
if (!isset($this->options['class'])) {
Html::addCssClass($this->options, 'list-group');
}
}
/**
* Renders the widget.
*/
public function run()
{
echo $this->renderItems();
BootstrapAsset::register($this->getView());
}
/**
* Renders widget items.
*/
public function renderItems()
{
$items = [];
foreach ($this->items as $i => $item) {
if (isset($item['visible']) && !$item['visible']) {
unset($items[$i]);
continue;
}
$items[] = $this->renderItem($item);
}
return Html::tag('div', implode("\n", $items), $this->options);
}
/**
* Renders a widget's item.
* @param string|array $item the item to render.
* @return string the rendering result.
* @throws InvalidConfigException
*/
public function renderItem($item)
{
if (is_string($item)) {
return $item;
}
if (!isset($item['label'])) {
throw new InvalidConfigException("The 'label' option is required.");
}
$label = $this->encodeLabels ? Html::encode($item['label']) : $item['label'];
// $options = ArrayHelper::getValue($item, 'options', []);
$items = ArrayHelper::getValue($item, 'items');
$url = Html::url(ArrayHelper::getValue($item, 'url', '#'));
$linkOptions = ArrayHelper::getValue($item, 'linkOptions', []);
Html::addCssClass($linkOptions, 'list-group-item');
if (isset($item['active'])) {
$active = ArrayHelper::remove($item, 'active', false);
} else {
$active = ($url == $this->activeUrl);
}
if ($items !== null) {
$linkOptions['data-toggle'] = 'collapse';
$linkOptions['data-parent'] = '#' . $this->id;
$id = $this->id . '-' . static::$counter++;
$url = '#' . $id;
$label .= ' ' . Html::tag('b', '', ['class' => 'caret']);
if (is_array($items)) {
if ($active === false) {
foreach($items as $subItem) {
if (isset($subItem['active']) && $subItem['active']) {
$active = true;
}
}
}
$items = static::widget([
'id' => $id,
'items' => $items,
'encodeLabels' => $this->encodeLabels,
'view' => $this->getView(),
'options' => [
'class' => "submenu panel-collapse collapse" . ($active ? ' in' : '')
]
]);
}
}
if ($active) {
Html::addCssClass($linkOptions, 'active');
}
return Html::a($label, $url, $linkOptions) . $items;
}
}
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\apidoc\templates\bootstrap\assets;
use yii\web\JqueryAsset;
use yii\web\View;
/**
* The asset bundle for the offline template.
*
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
class AssetBundle extends \yii\web\AssetBundle
{
public $sourcePath = '@yii/apidoc/templates/bootstrap/assets/css';
public $css = [
// 'api.css',
'style.css',
];
public $depends = [
'yii\web\JqueryAsset',
'yii\bootstrap\BootstrapAsset',
'yii\bootstrap\BootstrapPluginAsset',
];
public $jsOptions = [
'position' => View::POS_HEAD,
];
}
pre {
color: #000000;
background-color: #FFF5E6;
font-family: "courier new", "times new roman", monospace;
line-height: 1.3em;
/* Put a nice border around it. */
padding: 1px;
width: 90%;
/* Don't wrap its contents, and show scrollbars. */
/* white-space: nowrap;*/
overflow: auto;
/* Stop after about 24 lines, and just show a scrollbar. */
/* max-height: 24em; */
margin: 5px;
padding-left: 20px;
border: 1px solid #FFE6BF;
border-left: 6px solid #FFE6BF;
}
code {
color: #000000;
background-color: #FFF5E6;
padding: 1px;
}
div.code {
display: none;
color: #000000;
background-color: #FFF5E6;
font-family: "courier new", "times new roman", monospace;
line-height: 1.3em;
/* Put a nice border around it. */
padding: 1px;
width: 90%;
/* Don't wrap its contents, and show scrollbars. */
/* white-space: nowrap;*/
overflow: auto;
/* Stop after about 24 lines, and just show a scrollbar. */
/* max-height: 24em; */
margin: 5px;
padding-left: 20px;
border-left: 6px solid #FFE6BF;
}
table.summaryTable {
background: #E6ECFF;
border-collapse: collapse;
width: 100%;
}
table.summaryTable th, table.summaryTable td {
border: 1px #BFCFFF solid;
padding: 0.2em;
}
table.summaryTable th {
background: #CCD9FF;
text-align: left;
}
#nav {
padding: 3px;
margin: 0 0 10px 0;
border-top: 1px #BFCFFF solid;
}
#classDescription {
padding: 5px;
margin: 10px 0 20px 0;
border-bottom: 1px solid #BFCFFF;
}
.detailHeader {
font-weight: bold;
font-size: 12pt;
margin: 30px 0 5px 0;
border-bottom: 1px solid #BFCFFF;
}
.detailHeaderTag {
font-weight: normal;
font-size: 10pt;
}
.paramNameCol {
width: 12%;
font-weight: bold;
}
.paramTypeCol {
width: 12%;
}
.sourceCode {
margin: 5px 0;
padding:5px;
background:#FFF5E6;
}
\ No newline at end of file
html,
body {
height: 100%;
}
.wrap {
min-height: 100%;
height: auto;
width: auto;
margin: 60px 30px 0 30px;
padding: 0;
}
.footer {
height: 60px;
background-color: #f5f5f5;
border-top: 1px solid #ddd;
padding: 20px 30px;
}
#navigation {
margin-top: 20px;
}
.submenu a {
background: #f5f5f5;
border-radius: 0;
}
.submenu a:hover, .submenu a:active,
.submenu a.active, .submenu a.active:hover, .submenu a.active:active {
background: #44b5f6;
border-color: #44b5f6;
border-radius: 0;
color: #fff;
}
.signature, .signature2 {
padding: 3px;
color: #000000;
font-family: "courier new", "times new roman", monospace;
line-height: 1.3em;
white-space: pre-line;
word-wrap: break-word;
word-break: break-all;
}
.signature {
margin: 10px 0 10px 0;
background: #E6ECFF;
border: 1px #BFCFFF solid;
}
<?php
use yii\apidoc\templates\bootstrap\SideNavWidget;
use yii\bootstrap\Nav;
use yii\bootstrap\NavBar;
use yii\helpers\Html;
use yii\helpers\StringHelper;
use yii\widgets\Menu;
/**
* @var yii\web\View $this
*/
\yii\apidoc\templates\bootstrap\assets\AssetBundle::register($this);
$this->beginPage();
?>
<!DOCTYPE html>
<html lang="<?= Yii::$app->language ?>">
<head>
<meta charset="<?= Yii::$app->charset ?>"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="language" content="en" />
<?php $this->head() ?>
<title><?= Html::encode($this->context->pageTitle) ?></title>
</head>
<body>
<?php $this->beginBody() ?>
<div class="wrap">
<?php
NavBar::begin([
'brandLabel' => $this->context->pageTitle,
'brandUrl' => './index.html',
'options' => [
'class' => 'navbar-inverse navbar-fixed-top',
],
'padded' => false,
'view' => $this,
]);
echo Nav::widget([
'options' => ['class' => 'navbar-nav'],
'items' => [
['label' => 'Class reference', 'url' => './index.html'],
// ['label' => 'Application API', 'url' => '/site/about'],
// ['label' => 'Guide', 'url' => './guide_index.html'],
],
'view' => $this,
]);
NavBar::end();
?>
<!-- <div class="container">-->
<div class="row">
<div class="col-md-2">
<?php
ksort($types);
$nav = [];
foreach($types as $i=>$class) {
$namespace = $class->namespace;
if (empty($namespace)) {
$namespace = 'Not namespaced classes';
}
if (!isset($nav[$namespace])) {
$nav[$namespace] = [
'label' => $namespace,
'url' => '#',
'items' => [],
];
}
$nav[$namespace]['items'][] = [
'label' => StringHelper::basename($class->name),
'url' => './' . $this->context->generateUrl($class->name),
'active' => isset($type) && ($class->name == $type->name),
];
} ?>
<?= SideNavWidget::widget([
'id' => 'navigation',
'items' => $nav,
// 'route' => 'wtf',
'view' => $this,
])?>
</div>
<div class="col-md-9" role="main">
<?= $content ?>
</div>
</div>
<!-- </div>-->
</div>
<footer class="footer">
<?php /* <p class="pull-left">&copy; My Company <?= date('Y') ?></p> */ ?>
<p class="pull-right"><?= Yii::powered() ?></p>
</footer>
<script type="text/javascript">
/*<![CDATA[*/
$("a.toggle").on('click', function() {
var $this = $(this);
if ($this.hasClass('properties-hidden')) {
$this.text($this.text().replace(/Show/,'Hide'));
$this.parents(".summary").find(".inherited").show();
$this.removeClass('properties-hidden');
} else {
$this.text($this.text().replace(/Hide/,'Show'));
$this.parents(".summary").find(".inherited").hide();
$this.addClass('properties-hidden');
}
return false;
});
/*
$(".sourceCode a.show").toggle(function(){
$(this).text($(this).text().replace(/show/,'hide'));
$(this).parents(".sourceCode").find("div.code").show();
},function(){
$(this).text($(this).text().replace(/hide/,'show'));
$(this).parents(".sourceCode").find("div.code").hide();
});
$("a.sourceLink").click(function(){
$(this).attr('target','_blank');
});
*/
/*]]>*/
</script>
<?php $this->endBody() ?>
</body>
</html>
<?php $this->endPage() ?>
\ No newline at end of file
<?php
use yii\apidoc\models\ClassDoc;
use yii\apidoc\models\InterfaceDoc;
use yii\apidoc\models\TraitDoc;
/**
* @var ClassDoc[]|InterfaceDoc[]|TraitDoc[] $types
* @var yii\web\View $this
*/
?><h1>Class Reference</h1>
<table class="summaryTable docIndex table table-bordered table-striped table-hover">
<colgroup>
<col class="col-package" />
<col class="col-class" />
<col class="col-description" />
</colgroup>
<tr>
<th>Class</th>
<th>Description</th>
</tr>
<?php
ksort($types);
foreach($types as $i=>$class):
?>
<tr>
<td><?= $this->context->typeLink($class, $class->name) ?></td>
<td><?= \yii\apidoc\helpers\Markdown::process($class->shortDescription, $class) ?></td>
</tr>
<?php endforeach; ?>
</table>
......@@ -96,7 +96,7 @@ abstract class Renderer extends BaseRenderer implements ViewContextInterface
$this->context = $context;
$dir = Yii::getAlias($this->targetDir);
if (!is_dir($dir)) {
mkdir($dir);
mkdir($dir, 0777, true);
}
$types = array_merge($context->classes, $context->interfaces, $context->traits);
......@@ -107,6 +107,7 @@ abstract class Renderer extends BaseRenderer implements ViewContextInterface
$fileContent = $this->renderWithLayout($this->typeView, [
'type' => $type,
'docContext' => $context,
'types' => $types,
]);
file_put_contents($dir . '/' . $this->generateFileName($type->name), $fileContent);
Console::updateProgress(++$done, $typeCount);
......@@ -166,7 +167,7 @@ abstract class Renderer extends BaseRenderer implements ViewContextInterface
$links[] = Html::a(
$type->name,
null,
['href' => $this->generateFileName($type->name)]
['href' => $this->generateUrl($type->name)]
) . $postfix;
}
}
......@@ -191,7 +192,7 @@ abstract class Renderer extends BaseRenderer implements ViewContextInterface
if (($type = $this->context->getType($subject->definedBy)) === null) {
return $subject->name;
} else {
$link = $this->generateFileName($type->name);
$link = $this->generateUrl($type->name);
if ($subject instanceof MethodDoc) {
$link .= '#' . $subject->name . '()';
} else {
......@@ -336,6 +337,11 @@ abstract class Renderer extends BaseRenderer implements ViewContextInterface
. ' )';
}
public function generateUrl($typeName)
{
return $this->generateFileName($typeName);
}
protected function generateFileName($typeName)
{
return strtolower(str_replace('\\', '_', $typeName)) . '.html';
......
......@@ -15,7 +15,7 @@ if (empty($type->constants)) {
<p><a href="#" class="toggle">Hide inherited constants</a></p>
<table class="summaryTable">
<table class="summaryTable table table-striped table-bordered table-hover">
<colgroup>
<col class="col-const" />
<col class="col-description" />
......
......@@ -13,9 +13,9 @@ if (empty($events)) {
} ?>
<h2>Event Details</h2>
<?php foreach($events as $event): ?>
<div class="detailHeader" id="<?= $event->name.'-detail' ?>">
<div class="detailHeader h3" id="<?= $event->name.'-detail' ?>">
<?php echo $event->name; ?>
<span class="detailHeaderTag">
<span class="detailHeaderTag small">
event
<?php if(!empty($event->since)): ?>
(available since version <?= $event->since ?>)
......
......@@ -15,7 +15,7 @@ if (empty($type->events)) {
<p><a href="#" class="toggle">Hide inherited events</a></p>
<table class="summaryTable">
<table class="summaryTable table table-striped table-bordered table-hover">
<colgroup>
<col class="col-event" />
<col class="col-description" />
......
......@@ -16,9 +16,9 @@ if (empty($methods)) {
<?php foreach($methods as $method): ?>
<div class="detailHeader" id="<?= $method->name . '()-detail' ?>">
<div class="detailHeader h3" id="<?= $method->name . '()-detail' ?>">
<?= $method->name ?>()
<span class="detailHeaderTag">
<span class="detailHeaderTag small">
method
<?php if (!empty($method->since)): ?>
(available since version <?php echo $method->since; ?>)
......@@ -26,11 +26,9 @@ if (empty($methods)) {
</span>
</div>
<table class="summaryTable">
<table class="summaryTable table table-striped table-bordered table-hover">
<tr><td colspan="3">
<div class="signature2">
<?= $this->context->renderMethodSignature($method) ?>
</div>
<div class="signature2"><?= $this->context->renderMethodSignature($method) ?></div>
</td></tr>
<?php if(!empty($method->params) || !empty($method->return) || !empty($method->exceptions)): ?>
<?php foreach($method->params as $param): ?>
......
......@@ -19,7 +19,7 @@ if ($protected && count($type->getProtectedMethods()) == 0 || !$protected && cou
<p><a href="#" class="toggle">Hide inherited methods</a></p>
<table class="summaryTable">
<table class="summaryTable table table-striped table-bordered table-hover">
<colgroup>
<col class="col-method" />
<col class="col-description" />
......
......@@ -16,9 +16,9 @@ if (empty($properties)) {
<?php foreach($properties as $property): ?>
<div class="detailHeader" id="<?= $property->name.'-detail' ?>">
<div class="detailHeader h3" id="<?= $property->name.'-detail' ?>">
<?php echo $property->name; ?>
<span class="detailHeaderTag">
<span class="detailHeaderTag small">
property
<?php if($property->getIsReadOnly()) echo ' <em>read-only</em> '; ?>
<?php if($property->getIsWriteOnly()) echo ' <em>write-only</em> '; ?>
......@@ -28,9 +28,7 @@ if (empty($properties)) {
</span>
</div>
<div class="signature">
<?php echo $this->context->renderPropertySignature($property); ?>
</div>
<div class="signature"><?php echo $this->context->renderPropertySignature($property); ?></div>
<p><?= Markdown::process($property->description, $type) ?></p>
......
......@@ -18,7 +18,7 @@ if ($protected && count($type->getProtectedProperties()) == 0 || !$protected &&
<p><a href="#" class="toggle">Hide inherited properties</a></p>
<table class="summaryTable">
<table class="summaryTable table table-striped table-bordered table-hover">
<colgroup>
<col class="col-property" />
<col class="col-type" />
......
......@@ -44,7 +44,7 @@ $renderer = $this->context;
<?php endif; ?>
</div>
<table class="summaryTable docClass">
<table class="summaryTable docClass table table-bordered">
<colgroup>
<col class="col-name" />
<col class="col-value" />
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\apidoc\templates\online;
use yii\apidoc\models\Context;
use yii\apidoc\models\TypeDoc;
use yii\console\Controller;
use Yii;
use yii\helpers\Console;
use yii\helpers\FileHelper;
use yii\helpers\StringHelper;
/**
*
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
class Renderer extends \yii\apidoc\templates\html\Renderer
{
public $layout = false;
public $indexView = '@yii/apidoc/templates/online/views/index.php';
public $pageTitle = 'Yii Framework 2.0 API Documentation';
/**
* Renders a given [[Context]].
*
* @param Context $context the api documentation context to render.
* @param Controller $controller the apidoc controller instance. Can be used to control output.
*/
public function render($context, $controller)
{
parent::render($context, $controller);
$dir = Yii::getAlias($this->targetDir);
$controller->stdout("writing packages file...");
$packages = [];
$notNamespaced = [];
foreach(array_merge($context->classes, $context->interfaces, $context->traits) as $type) {
/** @var TypeDoc $type */
if (empty($type->namespace)) {
$notNamespaced[] = str_replace('\\', '-', $type->name);
} else {
$packages[$type->namespace][] = str_replace('\\', '-', $type->name);
}
}
ksort($packages);
$packages = array_merge(['Not namespaced' => $notNamespaced], $packages);
foreach($packages as $name => $classes) {
sort($packages[$name]);
}
file_put_contents($dir . '/packages.txt', serialize($packages));
$controller->stdout('done.' . PHP_EOL, Console::FG_GREEN);
}
protected function generateUrl($typeName)
{
return strtolower(str_replace('\\', '-', $typeName));
}
protected function generateFileName($typeName)
{
return $this->generateUrl($typeName) . '.html';
}
}
\ No newline at end of file
<?php
use yii\apidoc\models\ClassDoc;
use yii\apidoc\models\InterfaceDoc;
use yii\apidoc\models\TraitDoc;
/**
* @var ClassDoc[]|InterfaceDoc[]|TraitDoc[] $types
* @var yii\web\View $this
*/
?><h1>Class Reference</h1>
<table class="summaryTable docIndex">
<colgroup>
<col class="col-package" />
<col class="col-class" />
<col class="col-description" />
</colgroup>
<tr>
<th>Class</th>
<th>Description</th>
</tr>
<?php
ksort($types);
foreach($types as $i=>$class):
?>
<tr>
<td><?= $this->context->typeLink($class, $class->name) ?></td>
<td><?= \yii\apidoc\helpers\Markdown::process($class->shortDescription, $class) ?></td>
</tr>
<?php endforeach; ?>
</table>
......@@ -87,6 +87,7 @@ class ButtonDropdown extends Widget
'label' => '<span class="caret"></span>',
'encodeLabel' => false,
'options' => $this->options,
'view' => $this->getView(),
]);
} else {
$label .= ' <span class="caret"></span>';
......@@ -103,6 +104,7 @@ class ButtonDropdown extends Widget
'label' => $label,
'options' => $options,
'encodeLabel' => false,
'view' => $this->getView(),
]) . "\n" . $splitButton;
}
......@@ -114,6 +116,7 @@ class ButtonDropdown extends Widget
{
$config = $this->dropdown;
$config['clientOptions'] = false;
$config['view'] = $this->getView();
return Dropdown::widget($config);
}
}
......@@ -86,7 +86,8 @@ class ButtonGroup extends Widget
$buttons[] = Button::widget([
'label' => $label,
'options' => $options,
'encodeLabel' => $this->encodeLabels
'encodeLabel' => $this->encodeLabels,
'view' => $this->getView()
]);
} else {
$buttons[] = $button;
......
......@@ -171,6 +171,7 @@ class Nav extends Widget
'items' => $items,
'encodeLabels' => $this->encodeLabels,
'clientOptions' => false,
'view' => $this->getView(),
]);
}
}
......@@ -202,7 +203,7 @@ class Nav extends Widget
unset($item['url']['#']);
if (count($item['url']) > 1) {
foreach (array_splice($item['url'], 1) as $name => $value) {
if (!isset($this->params[$name]) || $this->params[$name] != $value) {
if ($value !== null && (!isset($this->params[$name]) || $this->params[$name] != $value)) {
return false;
}
}
......
......@@ -134,7 +134,7 @@ class Tabs extends Widget
}
$header = Html::a($label, "#", ['class' => 'dropdown-toggle', 'data-toggle' => 'dropdown']) . "\n"
. Dropdown::widget(['items' => $item['items'], 'clientOptions' => false]);
. Dropdown::widget(['items' => $item['items'], 'clientOptions' => false, 'view' => $this->getView()]);
} elseif (isset($item['content'])) {
$options = array_merge($this->itemOptions, ArrayHelper::getValue($item, 'options', []));
$options['id'] = ArrayHelper::getValue($options, 'id', $this->options['id'] . '-tab' . $n);
......
......@@ -10,7 +10,7 @@ namespace yii\debug;
use Yii;
use yii\base\Application;
use yii\web\View;
use yii\web\AccessDeniedHttpException;
use yii\web\ForbiddenHttpException;
/**
* The Yii Debug Module provides the debug toolbar and debugger
......@@ -80,7 +80,7 @@ class Module extends \yii\base\Module
} elseif ($action->id === 'toolbar') {
return false;
} else {
throw new AccessDeniedHttpException('You are not allowed to access this page.');
throw new ForbiddenHttpException('You are not allowed to access this page.');
}
}
......
......@@ -36,13 +36,15 @@ class RequestPanel extends Panel
public function save()
{
if (function_exists('apache_request_headers')) {
$requestHeaders = apache_request_headers();
} elseif (function_exists('http_get_request_headers')) {
$requestHeaders = http_get_request_headers();
} else {
$requestHeaders = [];
$headers = Yii::$app->getRequest()->getHeaders();
foreach ($headers as $name => $value) {
if (is_array($value) && count($value) == 1) {
$requestHeaders[$name] = current($value);
} else {
$requestHeaders[$name] = $value;
}
}
$responseHeaders = [];
foreach (headers_list() as $header) {
if (($pos = strpos($header, ':')) !== false) {
......
......@@ -8,7 +8,7 @@
namespace yii\gii;
use Yii;
use yii\web\AccessDeniedHttpException;
use yii\web\ForbiddenHttpException;
/**
* This is the main module class for the Gii module.
......@@ -110,7 +110,7 @@ class Module extends \yii\base\Module
if ($this->checkAccess()) {
return parent::beforeAction($action);
} else {
throw new AccessDeniedHttpException('You are not allowed to access this page.');
throw new ForbiddenHttpException('You are not allowed to access this page.');
}
}
......
......@@ -80,11 +80,13 @@ Yii Framework 2 Change Log
- Enh #2008: `yii message/extract` is now able to save translation strings to database (kate-kate, samdark)
- Enh #2043: Added support for custom request body parsers (danschmidt5189, cebe)
- Enh #2051: Do not save null data into database when using RBAC (qiangxue)
- Enh #2101: Gii is now using model labels when generating search (thiagotalma)
- Enh #2079:
- i18n now falls back to `en` from `en-US` if message translation isn't found (samdark)
- View now falls back to `en` from `en-US` if file not found (samdark)
- Default `sourceLanguage` and `language` are now `en` (samdark)
- Enh #2101: Gii is now using model labels when generating search (thiagotalma)
- Enh #2103: Renamed AccessDeniedHttpException to ForbiddenHttpException, added new commonly used HTTP exception classes (danschmidt5189)
- Enh #2124: Added support for UNION ALL queries (Ivan Pomortsev, iworker)
- Enh: Added `favicon.ico` and `robots.txt` to default application templates (samdark)
- Enh: Added `Widget::autoIdPrefix` to support prefixing automatically generated widget IDs (qiangxue)
- Enh: Support for file aliases in console command 'message' (omnilight)
......@@ -97,6 +99,8 @@ Yii Framework 2 Change Log
- Enh #1839: Added support for getting file extension and basename from uploaded file (anfrantic)
- Enh: yii\codeception\TestCase now supports loading and using fixtures via Yii fixture framework (qiangxue)
- Enh: Added support to parse json request data to Request::getRestParams() (cebe)
- Enh: Added ability to get incoming headers (dizews)
- Enh: Added `beforeRun()` and `afterRun()` to `yii\base\Action` (qiangxue)
- Chg #1519: `yii\web\User::loginRequired()` now returns the `Response` object instead of exiting the application (qiangxue)
- Chg #1586: `QueryBuilder::buildLikeCondition()` will now escape special characters and use percentage characters by default (qiangxue)
- Chg #1610: `Html::activeCheckboxList()` and `Html::activeRadioList()` will submit an empty string if no checkbox/radio is selected (qiangxue)
......@@ -106,6 +110,7 @@ Yii Framework 2 Change Log
- Chg #1821: Changed default values for yii\db\Connection username and password to null (cebe)
- Chg #1844: `Response::sendFile()` and other file sending methods will not send the response (qiangxue)
- Chg #1852: DbConnection::tablePrefix default value now 'tbl_' (creocoder)
- Chg #1958: `beforeSubmit` in `yii.activeform` is now executed after validation and before form submission (6pblcb)
- Chg #2025: Removed ability to declare scopes in ActiveRecord (samdark)
- Chg #2057: AutoTimestamp attributes defaults changed from `create_time` and `update_time` to `created_at` and `updated_at` (creocoder)
- Chg #2063: Removed `yii\web\Request::acceptTypes` and renamed `yii\web\Request::acceptedContentTypes` to `acceptableContentTypes` (qiangxue)
......
......@@ -127,6 +127,13 @@
var $form = $(this),
data = $form.data('yiiActiveForm');
if (data.validated) {
if (data.settings.beforeSubmit !== undefined) {
if (data.settings.beforeSubmit($form) == false) {
data.validated = false;
data.submitting = false;
return false;
}
}
// continue submitting the form since validation passes
return true;
}
......@@ -135,40 +142,36 @@
clearTimeout(data.settings.timer);
}
data.submitting = true;
if (!data.settings.beforeSubmit || data.settings.beforeSubmit($form)) {
validate($form, function (messages) {
var errors = [];
$.each(data.attributes, function () {
if (updateInput($form, this, messages)) {
errors.push(this.input);
}
});
updateSummary($form, messages);
if (errors.length) {
var top = $form.find(errors.join(',')).first().offset().top;
var wtop = $(window).scrollTop();
if (top < wtop || top > wtop + $(window).height) {
$(window).scrollTop(top);
}
} else {
data.validated = true;
var $button = data.submitObject || $form.find(':submit:first');
// TODO: if the submission is caused by "change" event, it will not work
if ($button.length) {
$button.click();
} else {
// no submit button in the form
$form.submit();
}
return;
validate($form, function (messages) {
var errors = [];
$.each(data.attributes, function () {
if (updateInput($form, this, messages)) {
errors.push(this.input);
}
data.submitting = false;
}, function () {
data.submitting = false;
});
} else {
updateSummary($form, messages);
if (errors.length) {
var top = $form.find(errors.join(',')).first().offset().top;
var wtop = $(window).scrollTop();
if (top < wtop || top > wtop + $(window).height) {
$(window).scrollTop(top);
}
} else {
data.validated = true;
var $button = data.submitObject || $form.find(':submit:first');
// TODO: if the submission is caused by "change" event, it will not work
if ($button.length) {
$button.click();
} else {
// no submit button in the form
$form.submit();
}
return;
}
data.submitting = false;
}
}, function () {
data.submitting = false;
});
return false;
},
......
......@@ -86,4 +86,23 @@ class Action extends Component
}
return call_user_func_array([$this, 'run'], $args);
}
/**
* This method is called right before `run()` is executed.
* You may override this method to do preparation work for the action run.
* If the method returns false, it will cancel the action.
* @return boolean whether to run the action.
*/
protected function beforeRun()
{
return true;
}
/**
* This method is called right after `run()` is executed.
* You may override this method to do post-processing work for the action run.
*/
protected function afterRun()
{
}
}
......@@ -11,7 +11,7 @@ namespace yii\base;
* ActionFilter provides a base implementation for action filters that can be added to a controller
* to handle the `beforeAction` event.
*
* Check implementation of [[AccessControl]], [[PageCache]] and [[HttpCache]] as examples on how to use it.
* Check implementation of [[\yii\web\AccessControl]], [[\yii\web\PageCache]] and [[\yii\web\HttpCache]] as examples on how to use it.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
......
......@@ -196,7 +196,7 @@ return [
'yii\validators\ValidationAsset' => YII_PATH . '/validators/ValidationAsset.php',
'yii\validators\Validator' => YII_PATH . '/validators/Validator.php',
'yii\web\AccessControl' => YII_PATH . '/web/AccessControl.php',
'yii\web\AccessDeniedHttpException' => YII_PATH . '/web/AccessDeniedHttpException.php',
'yii\web\ForbiddenHttpException' => YII_PATH . '/web/ForbiddenHttpException.php',
'yii\web\AccessRule' => YII_PATH . '/web/AccessRule.php',
'yii\web\Application' => YII_PATH . '/web/Application.php',
'yii\web\AssetBundle' => YII_PATH . '/web/AssetBundle.php',
......
......@@ -15,7 +15,7 @@ use yii\base\InvalidRouteException;
/**
* Application represents a console application.
*
* Application extends from [[yii\base\Application]] by providing functionalities that are
* Application extends from [[\yii\base\Application]] by providing functionalities that are
* specific to console requests. In particular, it deals with console requests
* through a command-based approach:
*
......
......@@ -635,11 +635,12 @@ class Query extends Component implements QueryInterface
/**
* Appends a SQL statement using UNION operator.
* @param string|Query $sql the SQL statement to be appended using UNION
* @param bool $all TRUE if using UNION ALL and FALSE if using UNION
* @return static the query object itself
*/
public function union($sql)
public function union($sql, $all = false)
{
$this->union[] = $sql;
$this->union[] = [ 'query' => $sql, 'all' => $all ];
return $this;
}
......
......@@ -739,16 +739,23 @@ class QueryBuilder extends \yii\base\Object
if (empty($unions)) {
return '';
}
$result = '';
foreach ($unions as $i => $union) {
if ($union instanceof Query) {
$query = $union['query'];
if ($query instanceof Query) {
// save the original parameters so that we can restore them later to prevent from modifying the query object
$originalParams = $union->params;
$union->addParams($params);
list ($unions[$i], $params) = $this->build($union);
$union->params = $originalParams;
$originalParams = $query->params;
$query->addParams($params);
list ($unions[$i]['query'], $params) = $this->build($query);
$query->params = $originalParams;
}
$result .= 'UNION ' . ($union['all'] ? 'ALL ' : '') . '( ' . $unions[$i]['query'] . ' ) ';
}
return "UNION (\n" . implode("\n) UNION (\n", $unions) . "\n)";
return trim($result);
}
/**
......
......@@ -85,7 +85,7 @@ class BaseStringHelper
if ($pos !== false) {
return mb_substr($path, 0, $pos);
} else {
return $path;
return '';
}
}
......
......@@ -7,7 +7,7 @@ return [
'messagePath' => __DIR__,
// array, required, list of language codes that the extracted messages
// should be translated to. For example, ['zh-CN', 'de'].
'languages' => ['ar', 'da', 'de', 'es', 'fa-IR', 'fr', 'it', 'ja', 'pl', 'pt-BR', 'pt-PT', 'ro', 'ru', 'sk', 'sr', 'sr-Latn', 'uk', 'zh-CN'],
'languages' => ['ar', 'da', 'de', 'el', 'es', 'fa-IR', 'fr', 'it', 'ja', 'pl', 'pt-BR', 'pt-PT', 'ro', 'ru', 'sk', 'sr', 'sr-Latn', 'uk', 'zh-CN'],
// string, the name of the function for translating messages.
// Defaults to 'Yii::t'. This is used as a mark to find the messages to be
// translated. You may use a string for single function name or an array for
......
<?php
/**
* Message translations.
*
* This file is automatically generated by 'yii message' command.
* It contains the localizable messages extracted from source code.
* You may modify this file by translating the extracted messages.
*
* Each array element represents the translation (value) of a message (key).
* If the value is empty, the message is considered as not translated.
* Messages that no longer need translation will have their translations
* enclosed between a pair of '@@' marks.
*
* Message string can be used with plural forms format. Check i18n section
* of the guide for details.
*
* NOTE: this file must be saved in UTF-8 encoding.
*/
return array (
'Home' => 'Αρχική',
'Invalid data received for parameter "{param}".' => 'Μη έγκυρα δεδομένα για την παράμετρο "{param}".',
'Login Required' => 'Απαιτείται είσοδος',
'Missing required arguments: {params}' => 'Απουσιάζουν απαραίτητες επιλογές: {params}',
'Missing required parameters: {params}' => 'Απουσιάζουν απαραίτητες παράμετροι: {params}',
'No help for unknown command "{command}".' => 'Δεν υπάρχει τεκμηρίωση για την εντολή "{command}".',
'No help for unknown sub-command "{command}".' => 'Δεν υπάρχει τεκμηρίωση για την υπό-εντολή "{command}".',
'Showing <b>{begin, number}-{end, number}</b> of <b>{totalCount, number}</b> {totalCount, plural, one{item} other{items}}.' => 'Παρουσιάζονται <b>{begin, number}-{end, number}</b> από <b>{totalCount, number}</b>.',
'Total <b>{count, number}</b> {count, plural, one{item} other{items}}.' => 'Συνολικά <b>{count, number}</b> {count, plural, one{αντικείμενο} few{αντικείμενα} many{αντικείμενα} other{αντικείμενα}}.',
'Unable to verify your data submission.' => 'Δεν ήταν δυνατή η επαλήθευση των απεσταλμένων δεδομένων.',
'Unknown command "{command}".' => 'Άγνωστη εντολή "{command}".',
'Unknown option: --{name}' => 'Άγνωστη επιλογή : --{name}',
'View' => 'Προβολή',
'the input value' => 'η τιμή εισόδου',
'(not set)' => '(μη ορισμένο)',
'An internal server error occurred.' => 'Σφάλμα διακομιστή.',
'Are you sure to delete this item?' => 'Είστε σίγουρος για τη διαγραφή;',
'Delete' => 'Διαγραφή',
'Error' => 'Σφάλμα',
'File upload failed.' => 'Η μεταφόρτωση απέτυχε.',
'Invalid Configuration' => 'Invalid Configuration',
'No' => 'Όχι',
'No results found.' => 'Δεν βρέθηκαν αποτελέσματα.',
'Not Supported' => 'Δεν υποστηρίζεται',
'Only files with these extensions are allowed: {extensions}.' => 'Επιτρέπονται αρχεία μόνο με καταλήξεις: {extensions}.',
'Only files with these mimeTypes are allowed: {mimeTypes}.' => 'Επιτρέπονται αρχεία μόνο με MIME τύπο: {mimeTypes}.',
'Page not found.' => 'Η σελίδα δεν βρέθηκε.',
'Please fix the following errors:' => 'Παρακαλώ διορθώστε τα παρακάτω σφάλματα:',
'Please upload a file.' => 'Παρακαλώ μεταφορτώστε ένα αρχείο.',
'The file "{file}" is not an image.' => 'Το αρχείο «{file}» δεν είναι εικόνα.',
'The file "{file}" is too big. Its size cannot exceed {limit, number} {limit, plural, one{byte} other{bytes}}.' => 'Το αρχείο «{file}» είναι πολύ μεγάλο . Το μέγεθος του δεν μπορεί να είναι πάνω από {limit, number} {limit, plural, one{byte} other{bytes}}.',
'The image "{file}" is too large. The height cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Το αρχείο «{file}» είναι πολύ μεγάλο. Το ύψος δεν μπορεί να είναι μεγαλύτερο από {limit, number} {limit, plural, one{pixel} few{pixels} many{pixels} other{pixels}}.',
'The image "{file}" is too large. The width cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Το αρχείο «{file}» είναι πολύ μεγάλο. Το πλάτος δεν μπορεί να είναι μεγαλύτερο από {limit, number} {limit, plural, one{pixel} few{pixels} many{pixels} other{pixels}}.',
'The file "{file}" is too small. Its size cannot be smaller than {limit, number} {limit, plural, one{byte} other{bytes}}.' => 'Το αρχείο «{file}» είναι πολύ μικρό. Το μέγεθος του δεν μπορεί να είναι μικρότερο από {limit, number} {limit, plural, one{byte} few{bytes} many{bytes} other{bytes}}.',
'The image "{file}" is too small. The height cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Το αρχείο «{file}» είναι πολύ μικρό. To ύψος δεν μπορεί να είναι μικρότερο από {limit, number} {limit, plural, one{pixel} few{pixels} many{pixels} other{pixels}}.',
'The image "{file}" is too small. The width cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Το αρχείο «{file}» είναι πολύ μικρό. Το πλάτος του δεν μπορεί να είναι μικρότερο από {limit, number} {limit, plural, one{pixel} few{pixels} many{pixels} other{pixels}}.',
'The format of {attribute} is invalid.' => 'Ο τύπος του «{attribute}» δεν είναι έγκυρος.',
'The verification code is incorrect.' => 'Ο κωδικός επαλήθευσης είναι εσφαλμένος.',
'Update' => 'Ενημέρωση',
'User Error' => 'Σφάλμα χρήστη',
'User Warning' => 'Προειδοποίηση χρήστη',
'Warning' => 'Προειδοποίηση',
'Yes' => 'Ναι',
'You are not allowed to perform this action.' => 'Δεν επιτρέπεται να εκτελέσετε αυτή τη δράση.',
'You can upload at most {limit, number} {limit, plural, one{file} other{files}}.' => 'Μπορείτε να μεταφορτώσετε το πολύ {limit, number} {limit, plural, one{αρχείο} few{αρχεία} many{αρχεία} other{αρχεία}}.',
'{attribute} "{value}" has already been taken.' => '{attribute} «{value}» έχει ήδη καταχωρηθεί.',
'{attribute} cannot be blank.' => 'Το «{attribute}» δεν μπορεί να είναι κενό.',
'{attribute} is invalid.' => 'Το «{attribute}» δεν είναι έγκυρο.',
'{attribute} is not a valid URL.' => 'Το «{attribute}» δεν είναι έγκυρο URL.',
'{attribute} is not a valid email address.' => 'Η διεύθυνση email «{attribute}» δεν είναι έγκυρη .',
'{attribute} must be "{requiredValue}".' => 'Το «{attribute}» πρέπει να είναι «{requiredValue}».',
'{attribute} must be a number.' => 'Το «{attribute}» πρέπει να είναι αριθμός.',
'{attribute} must be a string.' => 'Το «{attribute}» πρέπει να είναι συμβολοσειρά.',
'{attribute} must be an integer.' => 'Το «{attribute}» πρέπει να είναι ακέραιος.',
'{attribute} must be either "{true}" or "{false}".' => 'Το «{attribute}» πρέπει να είναι «{true}» ή «{false}».',
'{attribute} must be greater than "{compareValue}".' => 'Το «{attribute}» πρέπει να είναι μεγαλύτερο από «{compareValue}».',
'{attribute} must be greater than or equal to "{compareValue}".' => 'Το «{attribute}» πρέπει να είναι μεγαλύτερο ή ίσο με «{compareValue}».',
'{attribute} must be less than "{compareValue}".' => 'Το «{attribute}» πρέπει να είναι μικρότερο από «{compareValue}».',
'{attribute} must be less than or equal to "{compareValue}".' => 'Το «{attribute}» πρέπει να είναι μικρότερο ή ίσο με «{compareValue}».',
'{attribute} must be no greater than {max}.' => 'Το «{attribute}» πρέπει να μην ξεπερνά το {max}.',
'{attribute} must be no less than {min}.' => 'Το «{attribute}» πρέπει να μην είναι λιγότερο από {min}.',
'{attribute} must be repeated exactly.' => 'Το «{attribute}» πρέπει να επαναληφθεί ακριβώς.',
'{attribute} must not be equal to "{compareValue}".' => 'Το «{attribute}» πρέπει να μην είναι ίσο με «{compareValue}».',
'{attribute} should contain at least {min, number} {min, plural, one{character} other{characters}}.' => 'Το «{attribute}» πρέπει να περιέχει το λιγότερο {min, number} {min, plural, one{χαρακτήρα} few{χαρακτήρες} many{χαρακτήρες} other{χαρακτήρες}}.',
'{attribute} should contain at most {max, number} {max, plural, one{character} other{characters}}.' => 'Το «{attribute}» πρέπει να περιέχει το πολύ {max, number} {max, plural, one{χαρακτήρα} few{χαρακτήρες} many{χαρακτήρες} other{χαρακτήρες}}.',
'{attribute} should contain {length, number} {length, plural, one{character} other{characters}}.' => 'Το «{attribute}» πρέπει να περιέχει {length, number} {length, plural, one{χαρακτήρα} few{χαρακτήρες} many{χαρακτήρες} other{χαρακτήρες}}.',
);
......@@ -17,12 +17,11 @@
* NOTE: this file must be saved in UTF-8 encoding.
*/
return array (
'View' => '',
'(not set)' => '(não definido)',
'An internal server error occurred.' => 'Ocorreu um erro interno do servidor.',
'Are you sure to delete this item?' => 'Tem certeza de que deseja excluir este item?',
'Delete' => 'Excluir',
'Error' => 'Error',
'Error' => 'Erro',
'File upload failed.' => 'O upload do arquivo falhou.',
'Home' => 'Página Inicial',
'Invalid data received for parameter "{param}".' => 'Dados inválidos recebidos para o parâmetro “{param}”.',
......@@ -33,29 +32,30 @@ return array (
'No help for unknown command "{command}".' => 'Não há ajuda para o comando desconhecido “{command}”.',
'No help for unknown sub-command "{command}".' => 'Não há ajuda para o sub-comando desconhecido “{command}”.',
'No results found.' => 'Nenhum resultado foi encontrado.',
'Only files with these extensions are allowed: {extensions}.' => 'Só são permitidos arquivos com as seguintes extensões: {extensions}.',
'Only files with these mimeTypes are allowed: {mimeTypes}.' => 'Só são permitidos arquivos com os seguintes mimeTypes: {mimeTypes}.',
'Only files with these extensions are allowed: {extensions}.' => 'São permitidos somente arquivos com as seguintes extensões: {extensions}.',
'Only files with these mimeTypes are allowed: {mimeTypes}.' => 'São permitidos somente arquivos com os seguintes mimeTypes: {mimeTypes}.',
'Page not found.' => 'Página não encontrada.',
'Please fix the following errors:' => 'Por favor, corrija os seguintes erros:',
'Please upload a file.' => 'Por favor suba um arquivo.',
'Please upload a file.' => 'Por favor, faça upload de um arquivo.',
'Showing <b>{begin, number}-{end, number}</b> of <b>{totalCount, number}</b> {totalCount, plural, one{item} other{items}}.' => 'Exibindo <b>{begin, number}-{end, number}</b> de <b>{totalCount, number}</b> {totalCount, plural, one{item} other{itens}}.',
'The file "{file}" is not an image.' => 'O arquivo “{file}” não é uma imagem.',
'The file "{file}" is too big. Its size cannot exceed {limit, number} {limit, plural, one{byte} other{bytes}}.' => 'O arquivo “{file}” é grande demais. Seu tamanho não pode exceder {limit, number} {limit, plural, one{byte} other{bytes}}.',
'The file "{file}" is too small. Its size cannot be smaller than {limit, number} {limit, plural, one{byte} other{bytes}}.' => 'O arquivo “{file}” é pequeno demais. Seu tamanho não pode ser menor do que {limit, number} {limit, plural, one{byte} other{bytes}}.',
'The file "{file}" is too small. Its size cannot be smaller than {limit, number} {limit, plural, one{byte} other{bytes}}.' => 'O arquivo “{file}” é pequeno demais. Seu tamanho não pode ser menor que {limit, number} {limit, plural, one{byte} other{bytes}}.',
'The format of {attribute} is invalid.' => 'O formato de “{attribute}” é inválido.',
'The image "{file}" is too large. The height cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'O arquivo “{file}” é grande demais. A altura não pode ser maior do que {limit, number} {limit, plural, one{pixel} other{pixels}}.',
'The image "{file}" is too large. The width cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'O arquivo “{file}” é grande demais. A largura não pode ser maior do que {limit, number} {limit, plural, one{pixel} other{pixels}}.',
'The image "{file}" is too small. The height cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'O arquivo “{file}” é pequeno demais. A altura não pode ser menor do que {limit, number} {limit, plural, one{pixel} other{pixels}}.',
'The image "{file}" is too small. The width cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'O arquivo “{file}” é pequeno demais. A largura não pode ser menor do que {limit, number} {limit, plural, one{pixel} other{pixels}}.',
'The image "{file}" is too large. The height cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'O arquivo “{file}” é grande demais. A altura não pode ser maior que {limit, number} {limit, plural, one{pixel} other{pixels}}.',
'The image "{file}" is too large. The width cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'O arquivo “{file}” é grande demais. A largura não pode ser maior que {limit, number} {limit, plural, one{pixel} other{pixels}}.',
'The image "{file}" is too small. The height cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'O arquivo “{file}” é pequeno demais. A altura não pode ser menor que {limit, number} {limit, plural, one{pixel} other{pixels}}.',
'The image "{file}" is too small. The width cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'O arquivo “{file}” é pequeno demais. A largura não pode ser menor que {limit, number} {limit, plural, one{pixel} other{pixels}}.',
'The verification code is incorrect.' => 'O código de verificação está incorreto.',
'Total <b>{count, number}</b> {count, plural, one{item} other{items}}.' => 'Total <b>{count, number}</b> {count, plural, one{item} other{itens}}.',
'Unable to verify your data submission.' => 'Não foi possível verificar a sua submissão de dados.',
'Unable to verify your data submission.' => 'Não foi possível verificar o seu envio de dados.',
'Unknown command "{command}".' => 'Comando desconhecido “{command}”.',
'Unknown option: --{name}' => 'Opção desconhecida : --{name}',
'Update' => 'Atualizar',
'Update' => 'Alterar',
'View' => 'Exibir',
'Yes' => 'Sim',
'You are not allowed to perform this action.' => 'Você não está autorizado a realizar essa ação.',
'You can upload at most {limit, number} {limit, plural, one{file} other{files}}.' => 'Você pode fazer o upload de no máximo {limit, number} {limit, plural, one{arquivo} other{arquivos}}.',
'You can upload at most {limit, number} {limit, plural, one{file} other{files}}.' => 'Você pode fazer o upload de, no máximo, {limit, number} {limit, plural, one{arquivo} other{arquivos}}.',
'the input value' => 'o valor de entrada',
'{attribute} "{value}" has already been taken.' => '{attribute} “{value}” já foi utilizado.',
'{attribute} cannot be blank.' => '“{attribute}” não pode ficar em branco.',
......@@ -64,15 +64,15 @@ return array (
'{attribute} is not a valid email address.' => '“{attribute}” não é um endereço de e-mail válido.',
'{attribute} must be "{requiredValue}".' => '“{attribute}” deve ser “{requiredValue}”.',
'{attribute} must be a number.' => '“{attribute}” deve ser um número.',
'{attribute} must be a string.' => '“{attribute}” deve ser uma string.',
'{attribute} must be a string.' => '“{attribute}” deve ser um texto.',
'{attribute} must be an integer.' => '“{attribute}” deve ser um número inteiro.',
'{attribute} must be either "{true}" or "{false}".' => '“{attribute}” deve ser “{true}” ou “{false}”.',
'{attribute} must be greater than "{compareValue}".' => '“{attribute}” deve ser maior do que “{compareValue}”.',
'{attribute} must be greater than "{compareValue}".' => '“{attribute}” deve ser maior que “{compareValue}”.',
'{attribute} must be greater than or equal to "{compareValue}".' => '“{attribute}” deve ser maior ou igual a “{compareValue}”.',
'{attribute} must be less than "{compareValue}".' => '“{attribute}” deve ser menor do que “{compareValue}”.',
'{attribute} must be less than "{compareValue}".' => '“{attribute}” deve ser menor que “{compareValue}”.',
'{attribute} must be less than or equal to "{compareValue}".' => '“{attribute}” deve ser menor ou igual a “{compareValue}”.',
'{attribute} must be no greater than {max}.' => '“{attribute}” não pode ser maior do que {max}.',
'{attribute} must be no less than {min}.' => '“{attribute}” não pode ser menor do que {min}.',
'{attribute} must be no greater than {max}.' => '“{attribute}” não pode ser maior que {max}.',
'{attribute} must be no less than {min}.' => '“{attribute}” não pode ser menor que {min}.',
'{attribute} must be repeated exactly.' => '“{attribute}” deve ser repetido exatamente.',
'{attribute} must not be equal to "{compareValue}".' => '“{attribute}” não deve ser igual a “{compareValue}”.',
'{attribute} should contain at least {min, number} {min, plural, one{character} other{characters}}.' => '“{attribute}” deve conter pelo menos {min, number} {min, plural, one{caractere} other{caracteres}}.',
......
......@@ -130,14 +130,14 @@ class AccessControl extends ActionFilter
* The default implementation will redirect the user to the login page if he is a guest;
* if the user is already logged, a 403 HTTP exception will be thrown.
* @param User $user the current user
* @throws AccessDeniedHttpException if the user is already logged in.
* @throws ForbiddenHttpException if the user is already logged in.
*/
protected function denyAccess($user)
{
if ($user->getIsGuest()) {
$user->loginRequired();
} else {
throw new AccessDeniedHttpException(Yii::t('yii', 'You are not allowed to perform this action.'));
throw new ForbiddenHttpException(Yii::t('yii', 'You are not allowed to perform this action.'));
}
}
}
......@@ -10,6 +10,12 @@ namespace yii\web;
/**
* BadRequestHttpException represents a "Bad Request" HTTP exception with status code 400.
*
* Use this exception to represent a generic client error. In many cases, there
* may be an HTTP exception that more precisely describes the error. In that
* case, consider using the more precise exception to provide the user with
* additional information.
*
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
......
......@@ -8,12 +8,13 @@
namespace yii\web;
/**
* AccessDeniedHttpException represents an "Access Denied" HTTP exception with status code 403.
* ConflictHttpException represents a "Conflict" HTTP exception with status code 409
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.10
* @author Dan Schmidt <danschmidt5189@gmail.com>
* @since 2.0
*/
class AccessDeniedHttpException extends HttpException
class ConflictHttpException extends HttpException
{
/**
* Constructor.
......@@ -23,6 +24,6 @@ class AccessDeniedHttpException extends HttpException
*/
public function __construct($message = null, $code = 0, \Exception $previous = null)
{
parent::__construct(403, $message, $code, $previous);
parent::__construct(409, $message, $code, $previous);
}
}
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\web;
/**
* ForbiddenHttpException represents a "Forbidden" HTTP exception with status code 403.
*
* Use this exception when a user has been authenticated but is not allowed to
* perform the requested action. If the user is not authenticated, consider
* using a 401 [[UnauthorizedHttpException]]. If you do not want to
* expose authorization information to the user, it is valid to respond with a
* 404 [[NotFoundHttpException]].
*
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4
* @author Dan Schmidt <danschmidt5189@gmail.com>
* @since 2.0
*/
class ForbiddenHttpException extends HttpException
{
/**
* Constructor.
* @param string $message error message
* @param integer $code error code
* @param \Exception $previous The previous exception used for the exception chaining.
*/
public function __construct($message = null, $code = 0, \Exception $previous = null)
{
parent::__construct(403, $message, $code, $previous);
}
}
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\web;
/**
* GoneHttpException represents a "Gone" HTTP exception with status code 410
*
* Throw a GoneHttpException when a user requests a resource that no longer exists
* at the requested url. For example, after a record is deleted, future requests
* for that record should return a 410 GoneHttpException instead of a 404
* [[NotFoundHttpException]].
*
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.11
* @author Dan Schmidt <danschmidt5189@gmail.com>
* @since 2.0
*/
class GoneHttpException extends HttpException
{
/**
* Constructor.
* @param string $message error message
* @param integer $code error code
* @param \Exception $previous The previous exception used for the exception chaining.
*/
public function __construct($message = null, $code = 0, \Exception $previous = null)
{
parent::__construct(410, $message, $code, $previous);
}
}
......@@ -11,7 +11,7 @@ use yii\base\InvalidParamException;
use yii\helpers\Json;
/**
* Parses a raw HTTP request using [[yii\helpers\Json::decode()]]
* Parses a raw HTTP request using [[\yii\helpers\Json::decode()]]
*
* @author Dan Schmidt <danschmidt5189@gmail.com>
* @since 2.0
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\web;
/**
* NotAcceptableHttpException represents a "Not Acceptable" HTTP exception with status code 406
*
* Use this exception when the client requests a Content-Type that your
* application cannot return. Note that, according to the HTTP 1.1 specification,
* you are not required to respond with this status code in this situation.
*
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.7
* @author Dan Schmidt <danschmidt5189@gmail.com>
* @since 2.0
*/
class NotAcceptableHttpException extends HttpException
{
/**
* Constructor.
* @param string $message error message
* @param integer $code error code
* @param \Exception $previous The previous exception used for the exception chaining.
*/
public function __construct($message = null, $code = 0, \Exception $previous = null)
{
parent::__construct(406, $message, $code, $previous);
}
}
......@@ -151,6 +151,10 @@ class Request extends \yii\base\Request
private $_cookies;
/**
* @var array the headers in this collection (indexed by the header names)
*/
private $_headers;
/**
* Resolves the current request into a route and the associated parameters.
......@@ -170,6 +174,37 @@ class Request extends \yii\base\Request
}
/**
* Returns the header collection.
* The header collection contains incoming HTTP headers.
* @return HeaderCollection the header collection
*/
public function getHeaders()
{
if ($this->_headers === null) {
$this->_headers = new HeaderCollection;
$headers = [];
if (function_exists('getallheaders')) {
$headers = getallheaders();
} elseif (function_exists('http_get_request_headers')) {
$headers = http_get_request_headers();
} else {
foreach ($_SERVER as $name => $value) {
if (substr($name, 0, 5) == 'HTTP_') {
$name = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))));
$this->_headers->add($name, $value);
}
}
return $this->_headers;
}
foreach ($headers as $name => $value) {
$this->_headers->add($name, $value);
}
}
return $this->_headers;
}
/**
* Returns the method of the current request (e.g. GET, POST, HEAD, PUT, PATCH, DELETE).
* @return string request method, such as GET, POST, HEAD, PUT, PATCH, DELETE.
* The value returned is turned into upper case.
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\web;
/**
* TooManyRequestsHttpException represents a "Too Many Requests" HTTP exception with status code 429
*
* Use this exception to indicate that a client has made too many requests in a
* given period of time. For example, you would throw this exception when
* 'throttling' an API user.
*
* @link http://tools.ietf.org/search/rfc6585#section-4
* @author Dan Schmidt <danschmidt5189@gmail.com>
* @since 2.0
*/
class TooManyRequestsHttpException extends HttpException
{
/**
* Constructor.
* @param string $message error message
* @param integer $code error code
* @param \Exception $previous The previous exception used for the exception chaining.
*/
public function __construct($message = null, $code = 0, \Exception $previous = null)
{
parent::__construct(429, $message, $code, $previous);
}
}
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\web;
/**
* UnauthorizedHttpException represents an "Unauthorized" HTTP exception with status code 401
*
* Use this exception to indicate that a client needs to authenticate or login
* to perform the requested action. If the client is already authenticated and
* is simply not allowed to perform the action, consider using a 403
* [[ForbiddenHttpException]] or 404 [[NotFoundHttpException]] instead.
*
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2
* @author Dan Schmidt <danschmidt5189@gmail.com>
* @since 2.0
*/
class UnauthorizedHttpException extends HttpException
{
/**
* Constructor.
* @param string $message error message
* @param integer $code error code
* @param \Exception $previous The previous exception used for the exception chaining.
*/
public function __construct($message = null, $code = 0, \Exception $previous = null)
{
parent::__construct(401, $message, $code, $previous);
}
}
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\web;
/**
* UnsupportedMediaTypeHttpException represents an "Unsupported Media Type" HTTP exception with status code 415
*
* Use this exception when the client sends data in a format that your
* application does not understand. For example, you would throw this exception
* if the client POSTs XML data to an action or controller that only accepts
* JSON.
*
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.16
* @author Dan Schmidt <danschmidt5189@gmail.com>
* @since 2.0
*/
class UnsupportedMediaTypeHttpException extends HttpException
{
/**
* Constructor.
* @param string $message error message
* @param integer $code error code
* @param \Exception $previous The previous exception used for the exception chaining.
*/
public function __construct($message = null, $code = 0, \Exception $previous = null)
{
parent::__construct(415, $message, $code, $previous);
}
}
......@@ -323,7 +323,7 @@ class User extends Component
* Note that when [[loginUrl]] is set, calling this method will NOT terminate the application execution.
*
* @return Response the redirection response if [[loginUrl]] is set
* @throws AccessDeniedHttpException the "Access Denied" HTTP exception if [[loginUrl]] is not set
* @throws ForbiddenHttpException the "Access Denied" HTTP exception if [[loginUrl]] is not set
*/
public function loginRequired()
{
......@@ -334,7 +334,7 @@ class User extends Component
if ($this->loginUrl !== null) {
return Yii::$app->getResponse()->redirect($this->loginUrl);
} else {
throw new AccessDeniedHttpException(Yii::t('yii', 'Login Required'));
throw new ForbiddenHttpException(Yii::t('yii', 'Login Required'));
}
}
......
......@@ -193,8 +193,10 @@ abstract class BaseListView extends Widget
}
/** @var LinkPager $class */
$class = ArrayHelper::remove($this->pager, 'class', LinkPager::className());
$this->pager['pagination'] = $pagination;
return $class::widget($this->pager);
$pager = $this->pager;
$pager['pagination'] = $pagination;
$pager['view'] = $this->getView();
return $class::widget($pager);
}
/**
......@@ -209,7 +211,9 @@ abstract class BaseListView extends Widget
}
/** @var LinkSorter $class */
$class = ArrayHelper::remove($this->sorter, 'class', LinkSorter::className());
$this->sorter['sort'] = $sort;
return $class::widget($this->sorter);
$sorter = $this->sorter;
$sorter['sort'] = $sort;
$sorter['view'] = $this->getView();
return $class::widget($sorter);
}
}
......@@ -295,7 +295,7 @@ class Menu extends Widget
unset($item['url']['#']);
if (count($item['url']) > 1) {
foreach (array_splice($item['url'], 1) as $name => $value) {
if (!isset($this->params[$name]) || $this->params[$name] != $value) {
if ($value !== null && (!isset($this->params[$name]) || $this->params[$name] != $value)) {
return false;
}
}
......
......@@ -215,4 +215,30 @@ class QueryBuilderTest extends DatabaseTestCase
$this->assertEquals($expectedQueryParams, $queryParams);
}
*/
/*
This test contains three select queries connected with UNION and UNION ALL constructions.
It could be useful to use "phpunit --group=db --filter testBuildUnion" command for run it.
public function testBuildUnion()
{
$expectedQuerySql = "SELECT `id` FROM `TotalExample` `t1` WHERE (w > 0) AND (x < 2) UNION ( SELECT `id` FROM `TotalTotalExample` `t2` WHERE w > 5 ) UNION ALL ( SELECT `id` FROM `TotalTotalExample` `t3` WHERE w = 3 )";
$query = new Query();
$secondQuery = new Query();
$secondQuery->select('id')
->from('TotalTotalExample t2')
->where('w > 5');
$thirdQuery = new Query();
$thirdQuery->select('id')
->from('TotalTotalExample t3')
->where('w = 3');
$query->select('id')
->from('TotalExample t1')
->where(['and', 'w > 0', 'x < 2'])
->union($secondQuery)
->union($thirdQuery, TRUE);
list($actualQuerySql, $queryParams) = $this->getQueryBuilder()->build($query);
$this->assertEquals($expectedQuerySql, $actualQuerySql);
}*/
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment