├── .gitignore
├── tests
├── assets
│ └── .gitignore
└── src
│ ├── BaseBootstrap4BlockTestCase.php
│ ├── BaseBootstrap4WidgetTestCase.php
│ ├── tags
│ └── TooltipTagTest.php
│ ├── widgets
│ ├── BreadcrumbsTest.php
│ └── LinkPagerTest.php
│ ├── blocks
│ ├── ImageBlockTest.php
│ └── CarouselBlockTest.php
│ └── ActiveFormTest.php
├── src
├── blockgroups
│ └── BootstrapGroup.php
├── BaseBootstrap4Block.php
├── Bootstrap4Asset.php
├── Module.php
├── grid
│ ├── GridView.php
│ └── ActionColumn.php
├── ActiveField.php
├── tags
│ └── TooltipTag.php
├── widgets
│ ├── Breadcrumbs.php
│ └── LinkPager.php
├── views
│ └── blocks
│ │ ├── ImageBlock.php
│ │ └── CarouselBlock.php
├── ActiveForm.php
├── blocks
│ ├── ImageBlock.php
│ └── CarouselBlock.php
└── messages
│ ├── pl
│ └── bootstrap4.php
│ ├── en
│ └── bootstrap4.php
│ ├── ru
│ └── bootstrap4.php
│ ├── de
│ └── bootstrap4.php
│ ├── id
│ └── bootstrap4.php
│ ├── pt
│ └── bootstrap4.php
│ └── fr
│ └── bootstrap4.php
├── actions.phpunit.xml
├── LICENSE.md
├── composer.json
├── .github
└── workflows
│ └── tests.yml
├── README.md
└── CHANGELOG.md
/.gitignore:
--------------------------------------------------------------------------------
1 | /.settings/
2 | /.buildpath
3 | /.project
4 | /.idea
5 | /vendor/
6 | /luya
7 | composer.lock
--------------------------------------------------------------------------------
/tests/assets/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Ignore everything in this directory
3 | *
4 | # Except this file
5 | !.gitignore
--------------------------------------------------------------------------------
/src/blockgroups/BootstrapGroup.php:
--------------------------------------------------------------------------------
1 |
9 | * @since 1.0.0
10 | */
11 | class BootstrapGroup extends \luya\cms\base\BlockGroup
12 | {
13 | public function identifier()
14 | {
15 | return 'bootstrap4';
16 | }
17 |
18 | public function label()
19 | {
20 | return 'Bootstrap 4';
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/BaseBootstrap4Block.php:
--------------------------------------------------------------------------------
1 |
13 | * @since 1.0.0
14 | */
15 | abstract class BaseBootstrap4Block extends PhpBlock
16 | {
17 | /**
18 | * @inheritdoc
19 | */
20 | public function getViewPath()
21 | {
22 | return dirname(__DIR__) . '/src/views/blocks';
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Bootstrap4Asset.php:
--------------------------------------------------------------------------------
1 |
9 | * @since 1.0.0
10 | */
11 | class Bootstrap4Asset extends \yii\web\AssetBundle
12 | {
13 | public $js = [
14 | ['//stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.bundle.min.js', 'integrity' => 'sha384-6khuMg9gaYr5AxOqhkVIODVIvm9ynTT5J4V1cfthmT+emCG6yVmEZsRHdxlotUnm', 'crossorigin' => 'anonymous'],
15 | ];
16 |
17 | public $css = [
18 | ['//stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css', 'integrity' => 'sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh', 'crossorigin' => 'anonymous'],
19 | ];
20 |
21 |
22 | public $depends = [
23 | 'yii\web\JqueryAsset',
24 | ];
25 | }
26 |
--------------------------------------------------------------------------------
/actions.phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 | ./tests
14 |
15 |
16 |
17 |
18 | ./vendor
19 | ./tests
20 |
21 |
22 | ./src
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/Module.php:
--------------------------------------------------------------------------------
1 |
14 | */
15 | class Module extends \luya\base\Module
16 | {
17 | /**
18 | * @inheritdoc
19 | */
20 | public static function onLoad()
21 | {
22 | Yii::setAlias('@bootstrap4', static::staticBasePath());
23 |
24 | self::registerTranslation('bootstrap4*', static::staticBasePath() . '/messages', [
25 | 'bootstrap4' => 'bootstrap4.php',
26 | ]);
27 | }
28 |
29 | /**
30 | * Translations
31 | *
32 | * @param string $message
33 | * @param array $params
34 | * @return string
35 | */
36 | public static function t($message, array $params = [])
37 | {
38 | return parent::baseT('bootstrap4', $message, $params);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/tests/src/BaseBootstrap4BlockTestCase.php:
--------------------------------------------------------------------------------
1 | 'bootstrap4test',
13 | 'basePath' => dirname(__DIR__) . '/../',
14 | 'aliases' => [
15 | '@app' => 'app_path',
16 | ],
17 | 'components' => [
18 | 'assetManager' => [
19 | 'basePath' => dirname(__DIR__) . '/assets',
20 | 'bundles' => [
21 | 'yii\web\JqueryAsset' => false,
22 | 'luya\bootstrap4\Bootstrap4Asset' => false,
23 | ],
24 | ],
25 | 'storage' => [
26 | 'class' => 'luya\admin\filesystem\DummyFileSystem',
27 | 'filesArray' => [],
28 | 'imagesArray' => [],
29 | ],
30 | ]
31 | ];
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/grid/GridView.php:
--------------------------------------------------------------------------------
1 |
11 | * @since 1.0.0
12 | */
13 | class GridView extends \yii\grid\GridView
14 | {
15 | /**
16 | * Apply class `table-responsive` if enabled.
17 | */
18 | public $responsive = false;
19 |
20 | /**
21 | * @var array the HTML attributes for the grid table element.
22 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
23 | */
24 | public $tableOptions = ['class' => 'table table-striped table-bordered'];
25 |
26 | /**
27 | * @inheritdoc
28 | */
29 | public $pager = ['class' => LinkPager::class];
30 |
31 | /**
32 | * @inheritdoc
33 | */
34 | public function init()
35 | {
36 | parent::init();
37 |
38 | if ($this->responsive) {
39 | $this->tableOptions['class'] = $this->tableOptions['class'] . ' table-responsive';
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/tests/src/BaseBootstrap4WidgetTestCase.php:
--------------------------------------------------------------------------------
1 | 'bs4app',
15 | 'basePath' => dirname(__DIR__) . '/../',
16 | 'components' => [
17 | 'assetManager' => [
18 | 'basePath' => dirname(__DIR__) . '/assets',
19 | 'bundles' => [
20 | 'yii\web\JqueryAsset' => false,
21 | 'luya\bootstrap4\Bootstrap4Asset' => false,
22 | ],
23 | ],
24 | 'storage' => [
25 | 'class' => 'luya\admin\filesystem\DummyFileSystem',
26 | 'filesArray' => [],
27 | 'imagesArray' => [],
28 | ],
29 | 'composition' => null
30 | ]
31 | ];
32 | }
33 | }
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2014-2021 Zephir Software Design AG. https://luya.io
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/ActiveField.php:
--------------------------------------------------------------------------------
1 |
11 | * @since 1.0.0
12 | */
13 | class ActiveField extends \yii\widgets\ActiveField
14 | {
15 | /**
16 | * @inheritdoc
17 | */
18 | public $hintOptions = ['class' => 'form-text text-muted', 'tag' => 'small'];
19 |
20 | /**
21 | * @inheritdoc
22 | */
23 | public $errorOptions = ['class' => 'invalid-feedback'];
24 |
25 | /**
26 | * Checkbox rendered as switch
27 | *
28 | * @param array $options
29 | * @return self
30 | * @see https://getbootstrap.com/docs/4.2/components/forms/#switches
31 | * @since 1.0.4
32 | */
33 | public function checkboxSwitch($options = [])
34 | {
35 | $this->label(false);
36 | $this->parts['{input}'] = '
37 | '.Html::activeCheckbox($this->model, $this->attribute, array_merge(['label' => null, 'class' => 'custom-control-input'], $options)).'
38 | '.Html::activeLabel($this->model, $this->attribute, $options).'
39 |
';
40 |
41 | return $this;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/tests/src/tags/TooltipTagTest.php:
--------------------------------------------------------------------------------
1 | 'mytestapp',
14 | 'basePath' => dirname(__DIR__),
15 | 'aliases' => [
16 | '@app' => 'app_path',
17 | ],
18 | 'components' => [
19 | 'assetManager' => [
20 | 'basePath' => dirname(__DIR__) . '/../assets',
21 | 'bundles' => [
22 | 'yii\web\JqueryAsset' => false,
23 | 'luya\bootstrap4\Bootstrap4Asset' => false,
24 | ],
25 | ],
26 | 'storage' => [
27 | 'class' => 'luya\admin\filesystem\DummyFileSystem',
28 | 'filesArray' => [],
29 | 'imagesArray' => [],
30 | ],
31 | ]
32 | ];
33 | }
34 |
35 | public function testTag()
36 | {
37 | $tag = new TooltipTag();
38 | $this->assertSame('link ', $tag->parse('link', 'text'));
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/grid/ActionColumn.php:
--------------------------------------------------------------------------------
1 |
12 | * @since 1.0.0
13 | */
14 | class ActionColumn extends \yii\grid\ActionColumn
15 | {
16 | public function init()
17 | {
18 | // do not call parent is then the glyphicons button would be added
19 | $this->initBs4Icons('view', 'fa-search-plus');
20 | $this->initBs4Icons('update', 'fa-edit');
21 | $this->initBs4Icons('delete', 'fa-trash', [
22 | 'data-confirm' => Yii::t('yii', 'Are you sure you want to delete this item?'),
23 | 'data-method' => 'post',
24 | ]);
25 | }
26 |
27 | protected function initBs4Icons($name, $iconName, $options = [])
28 | {
29 | if (!isset($this->buttons[$name]) && strpos($this->template, '{' . $name . '}') !== false) {
30 | $this->buttons[$name] = function ($url, $model, $key) use ($name, $iconName, $options) {
31 | $title = Yii::t('yii', ucfirst($name));
32 | $options = array_merge([
33 | 'title' => $title,
34 | 'aria-label' => $title,
35 | 'data-pjax' => '0',
36 | ], $options, $this->buttonOptions);
37 | $icon = Html::tag('i', '', ['class' => "fa $iconName", 'aria-hidden' => true]);
38 | return Html::a($icon, $url, $options);
39 | };
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "luyadev/luya-bootstrap4",
3 | "description": "Bootstrap4 Assets and Helper classes like ActiveForm for LUYA and Yii2.",
4 | "type": "luya-extension",
5 | "keywords": [
6 | "php",
7 | "luya",
8 | "module",
9 | "cms",
10 | "yii2",
11 | "bootstrap",
12 | "bootstrap4",
13 | "twbs4",
14 | "luya-module",
15 | "bootstrap4",
16 | "bootstrap",
17 | "assets"
18 | ],
19 | "license": "MIT",
20 | "homepage": "https://luya.io",
21 | "authors": [
22 | {
23 | "name": "Basil",
24 | "email": "git@nadar.io",
25 | "homepage": "https://github.com/nadar"
26 | }
27 | ],
28 | "support": {
29 | "issues": "https://github.com/luyadev/luya-bootstrap4/issues"
30 | },
31 | "require": {
32 | "luyadev/luya-core": ">=1.6"
33 | },
34 | "require-dev": {
35 | "luyadev/luya-testsuite": "^3.0",
36 | "luyadev/luya-module-cms": "^4.0",
37 | "luyadev/luya-module-admin": "^4.0"
38 | },
39 | "autoload": {
40 | "psr-4": {
41 | "luya\\bootstrap4\\": "src/"
42 | }
43 | },
44 | "autoload-dev": {
45 | "psr-4": {
46 | "luya\\bootstrap4\\tests\\": "tests/"
47 | }
48 | },
49 | "extra": {
50 | "luya": {
51 | "blocks": [
52 | "src{{DS}}blocks"
53 | ]
54 | }
55 | },
56 | "config": {
57 | "fxp-asset": {
58 | "enabled": false
59 | },
60 | "allow-plugins": {
61 | "yiisoft/yii2-composer": true,
62 | "luyadev/luya-composer": true
63 | }
64 | },
65 | "repositories": [
66 | {
67 | "type": "composer",
68 | "url": "https://asset-packagist.org"
69 | }
70 | ]
71 | }
72 |
--------------------------------------------------------------------------------
/src/tags/TooltipTag.php:
--------------------------------------------------------------------------------
1 | [
16 | * 'tooltip' => ['class' => 'luya\bootstrap4\tags\TooltipTag'],
17 | * ],
18 | * ```
19 | *
20 | * @author Basil Suter
21 | * @since 1.0.0
22 | */
23 | class TooltipTag extends BaseTag
24 | {
25 | /**
26 | * @var string Whether it should possition: top, bottom, left, right. You can configure this while setup the tag.
27 | */
28 | public $position = 'top';
29 |
30 | /**
31 | * @inheritDoc
32 | */
33 | public function init()
34 | {
35 | parent::init();
36 | $this->view->registerJs('$(\'[data-toggle="tooltip"]\').tooltip()', View::POS_READY);
37 | }
38 |
39 | /**
40 | * @inheritDoc
41 | */
42 | public function example()
43 | {
44 | return 'tooltip[Tooltip on Top](This is the tooltip text!)';
45 | }
46 |
47 | /**
48 | * @inheritDoc
49 | */
50 | public function readme()
51 | {
52 | return 'Generate a Tooltip element over a text (span) Element.';
53 | }
54 |
55 | /**
56 | * @inheritDoc
57 | */
58 | public function parse($value, $sub)
59 | {
60 | return Html::tag('span', $value, [
61 | 'data-toggle' => 'tooltip',
62 | 'title' => $sub,
63 | 'data-placement' => $this->position,
64 | 'class' => 'tooltip-info-span',
65 | ]);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/widgets/Breadcrumbs.php:
--------------------------------------------------------------------------------
1 |
12 | * Home
13 | *
14 | *
15 | * Home
16 | * Library
17 | *
18 | *
19 | * Home
20 | * Library
21 | * Data
22 | *
23 | * ```
24 | *
25 | * @author Basil Suter
26 | * @since 1.0.0
27 | */
28 | class Breadcrumbs extends \yii\widgets\Breadcrumbs
29 | {
30 | /**
31 | * @var string the name of the breadcrumb container tag.
32 | */
33 | public $tag = 'ol';
34 |
35 | /**
36 | * @var array the HTML attributes for the breadcrumb container tag.
37 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
38 | */
39 | public $options = ['class' => 'breadcrumb'];
40 |
41 | /**
42 | * @var string the template used to render each inactive item in the breadcrumbs. The token `{link}`
43 | * will be replaced with the actual HTML link for each inactive item.
44 | */
45 | public $itemTemplate = "{link} \n";
46 |
47 | /**
48 | * @var string the template used to render each active item in the breadcrumbs. The token `{link}`
49 | * will be replaced with the actual HTML link for each active item.
50 | */
51 | public $activeItemTemplate = "{link} \n";
52 | }
53 |
--------------------------------------------------------------------------------
/.github/workflows/tests.yml:
--------------------------------------------------------------------------------
1 | name: Tests
2 | on: [push, pull_request]
3 | env:
4 | DEFAULT_COMPOSER_FLAGS: "--prefer-dist --no-interaction"
5 | CC_TEST_REPORTER_ID: e5b2383e4b8cb691696f61c6de9d18afcb7fc53d36949295b35da1fb384d8632
6 | jobs:
7 | phpunit:
8 | name: PHP ${{ matrix.php }} on ${{ matrix.os }}
9 | runs-on: ${{ matrix.os }}
10 | strategy:
11 | fail-fast: false
12 | matrix:
13 | os: [ubuntu-latest]
14 | php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1']
15 |
16 | steps:
17 | ## checkout the repoistory
18 | - name: Checkout Repo
19 | uses: actions/checkout@v2
20 |
21 | ## Install(?) php
22 | - name: Install PHP
23 | uses: shivammathur/setup-php@v2
24 | with:
25 | php-version: ${{ matrix.php }}
26 | extensions: curl, dom, imagick, intl, mbstring, mcrypt, mysql, pdo, pdo_mysql, pdo_pgsql, pdo_sqlite, pgsql, sqlite
27 | ini-values: date.timezone='UTC'
28 |
29 | ## install composer
30 | - name: Install dependencies
31 | run: composer install $DEFAULT_COMPOSER_FLAGS
32 |
33 | ## run unit tests
34 | - name: PHP Unit tests for PHP
35 | run: vendor/bin/phpunit --verbose --configuration actions.phpunit.xml
36 | if: matrix.php == '8.1' || matrix.php == '8.0' || matrix.php == '7.4' || matrix.php == '7.3' || matrix.php == '7.2' || matrix.php == '7.0'
37 |
38 | ## unit test with coverage
39 | - name: PHP Unit tests for PHP 7.1
40 | run: vendor/bin/phpunit --verbose --coverage-clover=clover.xml --configuration actions.phpunit.xml
41 | if: matrix.php == '7.1'
42 |
43 | ## coverage
44 | - name: Code coverage
45 | run: |
46 | curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
47 | chmod +x ./cc-test-reporter
48 | ./cc-test-reporter after-build -t clover
49 | if: matrix.php == '7.1'
50 | continue-on-error: true # if is fork
--------------------------------------------------------------------------------
/src/views/blocks/ImageBlock.php:
--------------------------------------------------------------------------------
1 | extraValue('image');
8 | * @param $this->varValue('align');
9 | * @param $this->varValue('showCaption');
10 | * @param $this->varValue('image');
11 | * @param $this->cfgValue('lazyload');
12 | *
13 | * @var $this \luya\cms\base\PhpBlockView
14 | */
15 | use luya\lazyload\LazyLoad;
16 |
17 | $align = $this->varValue('align', 'left');
18 | ?>
19 |
20 | extraValue('image', false)): ?>
21 |
22 |
23 | caption)) {
25 | $caption = $image->caption;
26 | } else {
27 | $caption = '';
28 | }
29 | if ($this->cfgValue('lazyload', false)):
30 | $options['src'] = 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==';
31 | if (!empty($caption)) {
32 | $options['alt'] = $caption;
33 | $options['title'] = $caption;
34 | }
35 | echo LazyLoad::widget([
36 | 'src' => $image->source,
37 | 'extraClass' => 'figure-img img-fluid',
38 | 'width' => $image->itemArray['resolution_width'],
39 | 'height' => $image->itemArray['resolution_height'],
40 | 'options' => $options
41 | ]);
42 | else: ?>
43 | alt="= $caption ?>">
44 |
45 | varValue('showCaption', false) && !empty($caption)): ?>
46 | = $caption ?>
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/ActiveForm.php:
--------------------------------------------------------------------------------
1 |
14 | * @since 1.0.0
15 | */
16 | class ActiveForm extends \yii\widgets\ActiveForm
17 | {
18 | /**
19 | * @var string Using different style themes:
20 | *
21 | * + default: Default layout with labels at the top of the fields.
22 | * + horizontal: Horizontal layout set the labels left to the fields.
23 | */
24 | public $layout = 'default';
25 |
26 | /**
27 | * @var string Change the validation state to the input field.
28 | */
29 | public $validationStateOn = self::VALIDATION_STATE_ON_INPUT;
30 |
31 | /**
32 | * @var string The error Summary alert class
33 | */
34 | public $errorSummaryCssClass = 'error-summary alert alert-danger';
35 |
36 | /**
37 | * @inheritdoc
38 | */
39 | public $fieldClass = 'luya\bootstrap4\ActiveField';
40 |
41 | /**
42 | * @inheritdoc
43 | */
44 | public $errorCssClass = 'is-invalid';
45 |
46 | /**
47 | * @inheritdoc
48 | */
49 | public $successCssClass = 'is-valid';
50 |
51 | /**
52 | * @inheritdoc
53 | */
54 | public function init()
55 | {
56 | if ($this->layout == 'horizontal') {
57 | $this->provideHorizontalLayout();
58 | }
59 |
60 | parent::init();
61 | }
62 |
63 | /**
64 | * Change the configuration of the active field and form based on the horizontal inputs.
65 | *
66 | * Bootstrap 4 Example Output:
67 | *
68 | * ```php
69 | *
75 | * ```
76 | */
77 | protected function provideHorizontalLayout()
78 | {
79 | $this->options = ['class' => 'form-group row'];
80 | $this->fieldConfig = [
81 | 'options' => [
82 | 'class' => 'form-group row',
83 | ],
84 | 'labelOptions' => [
85 | 'class' => 'col-sm-2 col-form-label',
86 | ],
87 | 'template' => "{label}\n{input}\n{hint}\n{error}
",
88 | ];
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/tests/src/widgets/BreadcrumbsTest.php:
--------------------------------------------------------------------------------
1 | assertContainsTrimmed('', ob_get_clean());
17 | }
18 |
19 | public function testWidgetOutputWithoutLink()
20 | {
21 | $links = [];
22 |
23 | ob_start();
24 | ob_implicit_flush(false);
25 | echo Breadcrumbs::widget(['links' => $links]);
26 |
27 | $this->assertContainsTrimmed('', ob_get_clean());
28 | }
29 |
30 | public function testWidgetOutputWithOneLink()
31 | {
32 | $links = [
33 | [
34 | 'label' => 'Label 1',
35 | 'url' => 'link1'
36 | ]
37 | ];
38 |
39 | ob_start();
40 | ob_implicit_flush(false);
41 | echo Breadcrumbs::widget(['links' => $links]);
42 |
43 | $this->assertContainsTrimmed('
44 | Home
45 | Label 1
46 | ', ob_get_clean());
47 | }
48 |
49 | public function testWidgetOutputWithMultipleLinks()
50 | {
51 | $links = [
52 | [
53 | 'label' => 'Label 1',
54 | 'url' => 'link1'
55 | ],
56 | [
57 | 'label' => 'Label 2',
58 | 'url' => 'link2'
59 | ],
60 | ];
61 |
62 | ob_start();
63 | ob_implicit_flush(false);
64 | echo Breadcrumbs::widget(['links' => $links]);
65 |
66 | $this->assertContainsTrimmed('
67 | Home
68 | Label 1
69 | Label 2
70 | ', ob_get_clean());
71 | }
72 |
73 | public function testWidgetOutputWithoutHomeLink()
74 | {
75 | $links = [
76 | [
77 | 'label' => 'Label 1',
78 | 'url' => 'link1'
79 | ],
80 | [
81 | 'label' => 'Label 2',
82 | 'url' => 'link2'
83 | ],
84 | ];
85 |
86 | ob_start();
87 | ob_implicit_flush(false);
88 | echo Breadcrumbs::widget(['links' => $links, 'homeLink' => false]);
89 |
90 | $this->assertContainsTrimmed('
91 | Label 1
92 | Label 2
93 | ', ob_get_clean());
94 | }
95 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | # Bootstrap 4
6 |
7 | [](https://luya.io)
8 | 
9 | [](https://codeclimate.com/github/luyadev/luya-bootstrap4/test_coverage)
10 | [](https://packagist.org/packages/luyadev/luya-bootstrap4)
11 | [](https://packagist.org/packages/luyadev/luya-bootstrap4)
12 | [](https://forum.luya.io/)
13 |
14 | Wrapper classes for new [Bootstrap 4](https://getbootstrap.com/) CSS Framework for [Yii](https://yiiframework.com) and/or [LUYA](https://luya.io).
15 |
16 | > As of Bootstrap 4, the grid is completely written in FLEX. Check the [Browser Support](https://caniuse.com/#search=flex) to decide if you want to use Bootstrap 4 for your project.
17 |
18 | This package contains the following components:
19 |
20 | + Widgets
21 | + ActiveForm Widget (Yii ActiveForm Widget matching the Bootstrap 4 form styles)
22 | + Breadcrumbs
23 | + LinkPager
24 | + ActiveField Widget
25 | + Grid View / Action Column
26 | + Tags
27 | + Tooltips
28 | + CMS Blocks
29 | + Image
30 | + Carousel
31 | + Asset File (contains precompiled bootstrap4 css and js files via cdn)
32 |
33 | ## Installation
34 |
35 | Add the package to your project via composer
36 |
37 | ```sh
38 | composer require luyadev/luya-bootstrap4:^1.0
39 | ```
40 |
41 | ## Assets Bundle
42 |
43 | To use the css and js files of bootstrap just register the `Bootstrap4Asset` into your layout file with the following code of your layout.php file:
44 |
45 | ```php
46 | luya\bootstrap4\Bootstrap4Asset::register($this)
47 | ```
48 |
49 | At the top section of your layout file. This will include all required css and js files to use bootstrap 4 and set the right depenecy with jquery.
50 |
51 | ## Active Form
52 |
53 | A common way to build forms is the use thy Yii ActiveForm widget, to match all bootstrap4 components use it like following:
54 |
55 | ```php
56 |
63 | Bootstrap 4 ActiveForm
64 |
65 | = $form->field($model, 'username') ?>
66 | = $form->field($model, 'password')->passwordInput() ?>
67 | = Html::submitButton('Login', ['class' => 'btn btn-primary-outline']) ?>
68 |
69 | ```
70 |
71 | Tip: In order to style required fields with asterisks, you can use the following CSS:
72 |
73 | ```css
74 | div.required label.control-label:after {
75 | content: " *";
76 | color: red;
77 | }
78 | ```
79 |
--------------------------------------------------------------------------------
/src/widgets/LinkPager.php:
--------------------------------------------------------------------------------
1 |
9 | * @since 1.0.0
10 | */
11 | class LinkPager extends \yii\widgets\LinkPager
12 | {
13 | /**
14 | * @var array HTML attributes for the pager container tag.
15 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
16 | */
17 | public $options = ['class' => 'pagination'];
18 |
19 | /**
20 | * @var array HTML attributes for the link in a pager container tag.
21 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
22 | */
23 | public $linkOptions = ['class' => 'page-link'];
24 | /**
25 | * @var string the CSS class for the each page button.
26 | * @since 2.0.7
27 | */
28 | public $pageCssClass = 'page-item';
29 | /**
30 | * @var string the CSS class for the "first" page button.
31 | */
32 | public $firstPageCssClass = '';
33 | /**
34 | * @var string the CSS class for the "last" page button.
35 | */
36 | public $lastPageCssClass = '';
37 | /**
38 | * @var string the CSS class for the "previous" page button.
39 | */
40 | public $prevPageCssClass = 'page-item';
41 | /**
42 | * @var string the CSS class for the "next" page button.
43 | */
44 | public $nextPageCssClass = 'page-item';
45 | /**
46 | * @var string the CSS class for the active (currently selected) page button.
47 | */
48 | public $activePageCssClass = 'active';
49 | /**
50 | * @var string the CSS class for the disabled page buttons.
51 | */
52 | public $disabledPageCssClass = 'disabled';
53 |
54 | /**
55 | * @inheritdoc
56 | */
57 | public $disabledListItemSubTagOptions = ['class' => 'page-link', 'tag' => 'a'];
58 |
59 | /**
60 | * @var int maximum number of page buttons that can be displayed. Defaults to 10.
61 | */
62 | public $maxButtonCount = 10;
63 | /**
64 | * @var string|bool the label for the "next" page button. Note that this will NOT be HTML-encoded.
65 | * If this property is false, the "next" page button will not be displayed.
66 | */
67 | public $nextPageLabel = '»';
68 | /**
69 | * @var string|bool the text label for the previous page button. Note that this will NOT be HTML-encoded.
70 | * If this property is false, the "previous" page button will not be displayed.
71 | */
72 | public $prevPageLabel = '«';
73 | /**
74 | * @var string|bool the text label for the "first" page button. Note that this will NOT be HTML-encoded.
75 | * If it's specified as true, page number will be used as label.
76 | * Default is false that means the "first" page button will not be displayed.
77 | */
78 | public $firstPageLabel = false;
79 | /**
80 | * @var string|bool the text label for the "last" page button. Note that this will NOT be HTML-encoded.
81 | * If it's specified as true, page number will be used as label.
82 | * Default is false that means the "last" page button will not be displayed.
83 | */
84 | public $lastPageLabel = false;
85 | }
86 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # LUYA BOOTSTRAP 4 CHANGELOG
2 |
3 | All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/).
4 | In order to read more about upgrading and BC breaks have a look at the [UPGRADE Document](UPGRADE.md).
5 |
6 | ## 1.1.2 (9. December 2021)
7 |
8 | + Small changes in docs, translations, composer dependencies
9 |
10 | ## 1.1.1 (27. July 2021)
11 |
12 | + Allow LUYA Core Version 2.0
13 |
14 | ## 1.1.0 (28. July 2020)
15 |
16 | + [#30](https://github.com/luyadev/luya-bootstrap4/pull/30) Added widget tests
17 | + [#29](https://github.com/luyadev/luya-bootstrap4/pull/29) CarouselBlock: Added config variable to use LazyLoad; adjusted CarouselBlock tests
18 | + [#28](https://github.com/luyadev/luya-bootstrap4/issues/28) Image block: Added config variable to use LazyLoad; added `alt` and `title` attribute.
19 | + Adjust library requirements to `luyadev/luya-core >= 1.6` in composer dependencies.
20 | + Remove Travis and replaced by GitHub Actions
21 |
22 | ## 1.0.4 (6. May 2020)
23 |
24 | + Update CDN links from 4.3.1 to 4.4.1.
25 | + Added new `checkboxSwitch()` option for ActiveField in Bootstrap 4 Form Widget.
26 | + Added PHP 7.4 tests to Travis.
27 |
28 | ## 1.0.3 (22. October 2019)
29 |
30 | + [#25](https://github.com/luyadev/luya-bootstrap4/pull/26) Fixed bug with none unique accordion ids.
31 | + New PT translations.
32 |
33 | ## 1.0.2.2 (23. September 2019)
34 |
35 | + Fixed bug with Carousel block when multiple blocks are on the same Page.
36 |
37 | ## 1.0.2.1 (31. July 2019)
38 |
39 | + Fixed bug in carousel block when using indicators.
40 |
41 | ## 1.0.2 (6. June 2019)
42 |
43 | + Update to latest bootstrap 4.3.1 version.
44 | + Added field help info for carousel block.
45 | + Use {{DS}} separator for block paths.
46 | + [#22](https://github.com/luyadev/luya-bootstrap4/issues/22) Added the link (around the image). Changed the caption property away from image to slide. Added caption CSS class posibility.
47 |
48 | ## 1.0.1.1 (1. January 2019)
49 |
50 | + [#24](https://github.com/luyadev/luya-bootstrap4/issues/24) Fixed tooltip tag and added test.
51 |
52 | ## 1.0.1 (3. December 2018)
53 |
54 | + [#20](https://github.com/luyadev/luya-bootstrap4/pull/20) Russian translations.
55 | + [#19](https://github.com/luyadev/luya-bootstrap4/pull/19) Polish translations.
56 | + [#18](https://github.com/luyadev/luya-bootstrap4/issues/18) Update to Bootstrap version 4.1.3, use js bundle file.
57 |
58 | ## 1.0.0 (18. July 2018)
59 |
60 | + [#10](https://github.com/luyadev/luya-bootstrap4/issues/10) Update to Bootstrap 4.1
61 | + [#3](https://github.com/luyadev/luya-bootstrap4/issues/3) Use new Bootstrap 4 form validation classes.
62 | + [#7](https://github.com/luyadev/luya-bootstrap4/issues/7) Added Image block.
63 | + [#5](https://github.com/luyadev/luya-bootstrap4/issues/5) Add carousel block.
64 | + [#4](https://github.com/luyadev/luya-bootstrap4/issues/4) Move old blocks into luya legacy repo.
65 |
66 | ## 1.0.0-RC7 (28. January 2018)
67 |
68 | + Bootstrap 4 stable resources
69 |
70 | ## 1.0.0-RC6 (4. January 2018)
71 |
72 | + Bootstrap 4 beta 3 resources
73 |
74 | ## 1.0.0-RC5 (4. January 2018)
75 |
76 | + Bootstrap 4 beta 2 resources
77 | + Added block icons.
78 | + [#2](https://github.com/luyadev/luya-bootstrap4/issues/2) Fixed issue when using block without enable the module in the config, therefore the bootstrap4 alias is missing for the block view files.
79 |
80 | ## 1.0.0-RC4 (9. September 2017)
81 |
82 | + Fixed general issues for new LUYA RC4 release.
83 |
--------------------------------------------------------------------------------
/src/blocks/ImageBlock.php:
--------------------------------------------------------------------------------
1 |
16 | * @since 1.0.0
17 | */
18 | class ImageBlock extends PhpBlock
19 | {
20 | /**
21 | * @var string The module where this block belongs to in order to find the view files.
22 | */
23 | public $module = 'bootstrap4';
24 |
25 | /**
26 | * @var bool Choose whether a block can be cached trough the caching component. Be carefull with caching container blocks.
27 | */
28 | public $cacheEnabled = true;
29 |
30 | /**
31 | * @var int The cache lifetime for this block in seconds (3600 = 1 hour), only affects when cacheEnabled is true
32 | */
33 | public $cacheExpiration = 3600;
34 |
35 | /**
36 | * @inheritDoc
37 | */
38 | public function blockGroup()
39 | {
40 | return MediaGroup::class;
41 | }
42 |
43 | /**
44 | * @inheritDoc
45 | */
46 | public function name()
47 | {
48 | return Module::t('block_image.block_name');
49 | }
50 |
51 | /**
52 | * @inheritDoc
53 | */
54 | public function icon()
55 | {
56 | return 'image'; // see the list of icons on: https://material.io/icons/
57 | }
58 |
59 | /**
60 | * @inheritDoc
61 | */
62 | public function config()
63 | {
64 | return [
65 | 'vars' => [
66 | ['var' => 'image', 'label' => Module::t('block_image.image'), 'type' => self::TYPE_IMAGEUPLOAD, 'options' => ['no_filter' => false]],
67 | ['var' => 'align', 'label' => Module::t('block_image.align'), 'type' => self::TYPE_SELECT, 'options' => BlockHelper::selectArrayOption(['left' => Module::t('block_image.align_left'), 'center' => Module::t('block_image.align_center'), 'right' => Module::t('block_image.align_right')])],
68 | ['var' => 'showCaption', 'label' => Module::t('block_image.show_caption'), 'type' => self::TYPE_CHECKBOX],
69 | ],
70 | 'cfgs' => [
71 | ['var' => 'lazyload', 'label' => Module::t('block_image.lazyload'), 'type' => self::TYPE_CHECKBOX]
72 | ]
73 | ];
74 | }
75 |
76 | /**
77 | * @inheritDoc
78 | */
79 | public function extraVars()
80 | {
81 | return [
82 | 'image' => BlockHelper::imageUpload($this->getVarValue('image'), false, true),
83 | ];
84 | }
85 |
86 | /**
87 | * {@inheritDoc}
88 | *
89 | * @param {{extras.image}}
90 | * @param {{vars.align}}
91 | * @param {{vars.showCaption}}
92 | * @param {{vars.image}}
93 | */
94 | public function admin()
95 | {
96 | return '
97 |
98 |
99 |
100 |
101 | {% if vars.showCaption and extras.image.caption %}
102 |
{{extras.image.caption}}
103 | {% endif %}
104 |
105 |
';
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/messages/pl/bootstrap4.php:
--------------------------------------------------------------------------------
1 | 'Lista plików',
7 | 'block_file_list.files_label' => 'Pliki',
8 | 'block_file_list.show_type_label' => 'Wyświetl typ pliku',
9 | 'block_file_list.show_type_icon' => 'Wyświetl ikonę typu pliku',
10 | 'block_file_list.show_file_size' => 'Wyświetlaj rozmiar pliku',
11 |
12 | 'block_image.block_name' => 'Obraz',
13 | 'block_image.image' => 'Obraz',
14 | 'block_image.align' => 'Pozycja obrazu',
15 | 'block_image.align_left' => 'W lewo',
16 | 'block_image.align_right' => 'Prawo',
17 | 'block_image.align_center' => 'Center',
18 | 'block_image.show_caption' => 'Pokaż podpis',
19 |
20 | 'block_layout.block_name' => 'Układ: wiersz',
21 | 'block_layout.content' => 'Treść wiersza',
22 |
23 | 'block_layout_column.block_name' => 'Układ: Kolumna',
24 | 'block_layout_column.column_count' => 'Rozmiar XS w górę',
25 | 'block_layout_column.column_count_sm' => 'Rozmiar SM up',
26 | 'block_layout_column.column_count_md' => 'Rozmiar MD w górę',
27 | 'block_layout_column.column_count_lg' => 'Rozmiar LG w górę',
28 | 'block_layout_column.column_count_xl' => 'Rozmiar XL w górę',
29 | 'block_layout_column.content' => 'Zawartość kolumny',
30 |
31 | 'block_carousel.items' => 'Slajdy',
32 | 'block_carousel.block_name' => 'Karuzela',
33 | 'block_carousel.title' => 'Tytuł',
34 | 'block_carousel.caption' => 'Podpis pod obrazem',
35 | 'block_carousel.image' => 'Obraz',
36 | 'block_carousel.image_link' => 'Link',
37 |
38 | 'block_image_text.block_name' => 'Obraz z tekstem',
39 | 'block_image_text.image_position' => 'Pozycja obrazu',
40 | 'block_image_text.left' => 'W lewo',
41 | 'block_image_text.right' => 'Right',
42 | 'block_image_text.center' => 'Wyśrodkowany',
43 | 'block_image_text.image_shape' => 'Kształt obrazu',
44 | 'block_image_text.no_shape' => 'Brak kształtu',
45 | 'block_image_text.rounded_corners' => 'Zaokrąglone rogi',
46 | 'block_image_text.thumbnail' => 'Miniatura z ramką',
47 | 'block_image_text.circle' => 'Circle',
48 | 'block_image_text.image' => 'Obraz',
49 | 'block_image_text.image.width' => 'Szerokość obrazu',
50 | 'block_image_text.image.caption' => 'Podpis obrazu',
51 | 'block_image_text.image.caption.visibility' => 'Pokaż podpis obrazu',
52 | 'block_image_text.help' => 'Dodaj obrazy i tekst do opakowania dynamicznego',
53 | 'block_image_text.no_text' => 'Żaden tekst nie został jeszcze dodany.',
54 | 'block_image_text.no_image' => 'Nie dodano jeszcze obrazu.',
55 | 'block_image_text.link' => 'Link do obrazu',
56 | 'block_image_text.file' => 'Załącz plik',
57 | 'block_image_text.file_download' => 'Pobierz plik za pomocą obrazu',
58 |
59 | 'block_inlinetext.name' => 'Blok tekstu śródliniowego',
60 | 'block_inlinetext.empty' => 'Żaden tekst nie został jeszcze dodany.',
61 | 'block_inlinetext.size-sm' => 'Rozmiar mobilny',
62 | 'block_inlinetext.size-md' => 'Rozmiar tabletu',
63 | 'block_inlinetext.size-lg' => 'Rozmiar pulpitu',
64 | 'block_inlinetext.size-full' => 'Pełna szerokość',
65 | 'block_inlinetext.size' => 'szerokość',
66 |
67 | 'block_inline_wrapper.label' => 'Umieść tu bloki wbudowane ...',
68 | 'block_inline_wrapper.name' => 'Blokada kontenera śródliniowego',
69 |
70 | 'block_carousel.config_controls' => 'Sterowanie',
71 | 'block_carousel.config_indicators' => 'Wskaźniki',
72 | 'block_carousel.config_crossfade' => 'Crossfade',
73 | 'block_carousel.config_interval' => 'Interval',
74 | 'block_carousel.config_keyboard' => 'Klawiatura',
75 | 'block_carousel.config_pause' => 'Pauza',
76 | 'block_carousel.config_ride' => 'Ride',
77 | 'block_carousel.config_wrap' => 'Zawijaj',
78 | 'block_carousel.config_row' => 'Wiersz',
79 | ];
80 |
--------------------------------------------------------------------------------
/src/messages/en/bootstrap4.php:
--------------------------------------------------------------------------------
1 | 'Files List',
7 | 'block_file_list.files_label' => 'Files',
8 | 'block_file_list.show_type_label' => 'Display file type',
9 | 'block_file_list.show_type_icon' => 'Display file type icon',
10 | 'block_file_list.show_file_size' => 'Display file size',
11 |
12 | 'block_image.block_name' => 'Image',
13 | 'block_image.image' => 'Image',
14 | 'block_image.align' => 'Image position',
15 | 'block_image.align_left' => 'Left',
16 | 'block_image.align_right' => 'Right',
17 | 'block_image.align_center' => 'Center',
18 | 'block_image.show_caption' => 'Show caption',
19 | 'block_image.lazyload' => 'LazyLoad',
20 |
21 | 'block_layout.block_name' => 'Layout: Row',
22 | 'block_layout.content' => 'Row content',
23 |
24 | 'block_layout_column.block_name' => 'Layout: Column',
25 | 'block_layout_column.column_count' => 'Size XS up',
26 | 'block_layout_column.column_count_sm' => 'Size SM up',
27 | 'block_layout_column.column_count_md' => 'Size MD up',
28 | 'block_layout_column.column_count_lg' => 'Size LG up',
29 | 'block_layout_column.column_count_xl' => 'Size XL up',
30 | 'block_layout_column.content' => 'Column content',
31 |
32 | 'block_carousel.items' => 'Slides',
33 | 'block_carousel.block_name' => 'Carousel',
34 | 'block_carousel.title' => 'Title',
35 | 'block_carousel.caption' => 'Image caption',
36 | 'block_carousel.image' => 'Image',
37 | 'block_carousel.image_link' => 'Link',
38 |
39 | 'block_image_text.block_name' => 'Image with Text',
40 | 'block_image_text.image_position' => 'Image position',
41 | 'block_image_text.left' => 'Left',
42 | 'block_image_text.right' => 'Right',
43 | 'block_image_text.center' => 'Centered',
44 | 'block_image_text.image_shape' => 'Image shape',
45 | 'block_image_text.no_shape' => 'No shape',
46 | 'block_image_text.rounded_corners' => 'Rounded corners',
47 | 'block_image_text.thumbnail' => 'Thumbnail with border',
48 | 'block_image_text.circle' => 'Circle',
49 | 'block_image_text.image' => 'Image',
50 | 'block_image_text.image.width' => 'Image width',
51 | 'block_image_text.image.caption' => 'Image caption',
52 | 'block_image_text.image.caption.visibility' => 'Show image caption',
53 | 'block_image_text.help' => 'Add Images and text into a dynamic layout wrapper',
54 | 'block_image_text.no_text' => 'No text has been added yet.',
55 | 'block_image_text.no_image' => 'No image has been added yet.',
56 | 'block_image_text.link' => 'Image link',
57 | 'block_image_text.file' => 'Attach file',
58 | 'block_image_text.file_download' => 'Download file via image',
59 |
60 | 'block_inlinetext.name'=> 'Inline Text Block',
61 | 'block_inlinetext.empty'=> 'No text has been added yet.',
62 | 'block_inlinetext.size-sm'=> 'Size mobile',
63 | 'block_inlinetext.size-md'=> 'Size tablet',
64 | 'block_inlinetext.size-lg'=> 'Size desktop',
65 | 'block_inlinetext.size-full'=> 'Full width',
66 | 'block_inlinetext.size'=> 'width',
67 |
68 | 'block_inline_wrapper.label'=>'Place inline blocks here ...',
69 | 'block_inline_wrapper.name'=>'Inline Block Container',
70 |
71 | 'block_carousel.config_block_css_class' => 'Block CSS Class',
72 | 'block_carousel.config_caption_css_class' => 'Caption CSS Class',
73 | 'block_carousel.config_controls' => 'Controls',
74 | 'block_carousel.config_indicators' => 'Indicators',
75 | 'block_carousel.config_crossfade' => 'Crossfade',
76 | 'block_carousel.config_interval' => 'Interval',
77 | 'block_carousel.config_keyboard' => 'Keyboard',
78 | 'block_carousel.config_pause' => 'Pause',
79 | 'block_carousel.config_ride' => 'Ride',
80 | 'block_carousel.config_wrap' => 'Wrap',
81 | 'block_carousel.config_row' => 'Row',
82 | 'block_carousel.lazyload' => 'LazyLoad'
83 | ];
84 |
--------------------------------------------------------------------------------
/src/messages/ru/bootstrap4.php:
--------------------------------------------------------------------------------
1 | 'Cписок файлов',
7 | 'block_file_list.files_label' => 'Файлы',
8 | 'block_file_list.show_type_label' => 'Показать тип файла',
9 | 'block_file_list.show_type_icon' => 'Показать иконку типа файла',
10 | 'block_file_list.show_file_size' => 'Показать размер файла',
11 |
12 | 'block_image.block_name' => 'Изображение',
13 | 'block_image.image' => 'Изображение',
14 | 'block_image.align' => 'Положение изображения',
15 | 'block_image.align_left' => 'Слева',
16 | 'block_image.align_right' => 'Справа',
17 | 'block_image.align_center' => 'По центру',
18 | 'block_image.show_caption' => 'Показывать заголовок',
19 |
20 | 'block_layout.block_name' => 'Макет: строка',
21 | 'block_layout.content' => 'Контент в строке',
22 |
23 | 'block_layout_column.block_name' => 'Макет: колонка',
24 | 'block_layout_column.column_count' => 'Размер XS up',
25 | 'block_layout_column.column_count_sm' => 'Размер SM up',
26 | 'block_layout_column.column_count_md' => 'Размер MD up',
27 | 'block_layout_column.column_count_lg' => 'Размер LG up',
28 | 'block_layout_column.column_count_xl' => 'Размер XL up',
29 | 'block_layout_column.content' => 'Контент в колонке',
30 |
31 | 'block_carousel.items' => 'Слайды',
32 | 'block_carousel.block_name' => 'Карусель',
33 | 'block_carousel.title' => 'Заголовок',
34 | 'block_carousel.caption' => 'Показывать заголовок',
35 | 'block_carousel.image' => 'Изображение',
36 | 'block_carousel.image_link' => 'Ссылка',
37 |
38 | 'block_image_text.block_name' => 'Изображение с текстом',
39 | 'block_image_text.image_position' => 'Позиция изображения',
40 | 'block_image_text.left' => 'Слева',
41 | 'block_image_text.right' => 'Справа',
42 | 'block_image_text.center' => 'По центру',
43 | 'block_image_text.image_shape' => 'Форма изображения',
44 | 'block_image_text.no_shape' => 'Нет формы',
45 | 'block_image_text.rounded_corners' => 'Округленные углы',
46 | 'block_image_text.thumbnail' => 'Миниатюра с рамкой',
47 | 'block_image_text.circle' => 'Круг',
48 | 'block_image_text.image' => 'Изображение',
49 | 'block_image_text.image.width' => 'Ширина изображения',
50 | 'block_image_text.image.caption' => 'Заголовок изображения',
51 | 'block_image_text.image.caption.visibility' => 'Отобразить заголовок изображения',
52 | 'block_image_text.help' => 'Добавление изображений и текста в динамическую обертку макета',
53 | 'block_image_text.no_text' => 'Текст еще не добавлен.',
54 | 'block_image_text.no_image' => 'Изображение еще не добавлено.',
55 | 'block_image_text.link' => 'Ссылка на изображение',
56 | 'block_image_text.file' => 'Прикрепить файл',
57 | 'block_image_text.file_download' => 'Загрузить файл через изображение',
58 |
59 | 'block_inlinetext.name'=> 'Встроенные текстовый блок',
60 | 'block_inlinetext.empty'=> 'Текст еще не был добавлен.',
61 | 'block_inlinetext.size-sm'=> 'Размер для мобильных устройств',
62 | 'block_inlinetext.size-md'=> 'Размер для планшетов',
63 | 'block_inlinetext.size-lg'=> 'Размер для настольных компьютеров',
64 | 'block_inlinetext.size-full'=> 'Полная ширина',
65 | 'block_inlinetext.size'=> 'ширина',
66 |
67 | 'block_inline_wrapper.label'=>'Разместить здесь встроенные блоки ...',
68 | 'block_inline_wrapper.name'=>'Контейнер встроенного блока',
69 |
70 | 'block_carousel.config_controls' => 'Элементы управления',
71 | 'block_carousel.config_indicators' => 'Индикатор',
72 | 'block_carousel.config_crossfade' => 'Перекрестное затухание',
73 | 'block_carousel.config_interval' => 'Интервал',
74 | 'block_carousel.config_keyboard' => 'Клавиатура',
75 | 'block_carousel.config_pause' => 'Пауза',
76 | 'block_carousel.config_ride' => 'Режим пролистывания',
77 | 'block_carousel.config_wrap' => 'Обертка',
78 | 'block_carousel.config_row' => 'Строка'
79 | ];
80 |
--------------------------------------------------------------------------------
/src/messages/de/bootstrap4.php:
--------------------------------------------------------------------------------
1 | 'Dateiliste',
7 | 'block_file_list.files_label' => 'Dateien',
8 | 'block_file_list.show_type_label' => 'Dateityp anzeigen',
9 | 'block_file_list.show_type_icon' => 'Dateityp-Icon anzeigen',
10 | 'block_file_list.show_file_size' => 'Dateigrösse anzeigen',
11 |
12 | 'block_image.block_name' => 'Bild',
13 | 'block_image.image' => 'Bild',
14 | 'block_image.align' => 'Bildposition',
15 | 'block_image.align_left' => 'Links',
16 | 'block_image.align_right' => 'Rechts',
17 | 'block_image.align_center' => 'Mittig',
18 | 'block_image.show_caption' => 'Bildlegende anzeigen',
19 | 'block_image.lazyload' => 'LazyLoad',
20 |
21 | 'block_layout.block_name' => 'Layout: Row',
22 | 'block_layout.content' => 'Row Inhalt',
23 |
24 | 'block_layout_column.block_name' => 'Layout: Column',
25 | 'block_layout_column.column_count' => 'Grösse XS aufwärts',
26 | 'block_layout_column.column_count_sm' => 'Grösse SM aufwärts',
27 | 'block_layout_column.column_count_md' => 'Grösse MD aufwärts',
28 | 'block_layout_column.column_count_lg' => 'Grösse LG aufwärts',
29 | 'block_layout_column.column_count_xl' => 'Grösse XL aufwärts',
30 | 'block_layout_column.content' => 'Column Inhalt',
31 |
32 | 'block_carousel.items' => 'Slides',
33 | 'block_carousel.block_name' => 'Carousel',
34 | 'block_carousel.title' => 'Titel',
35 | 'block_carousel.caption' => 'Bildunterschrift',
36 | 'block_carousel.image' => 'Bild',
37 | 'block_carousel.image_link' => 'Link',
38 |
39 | 'block_image_text.block_name' => 'Bild mit Text',
40 | 'block_image_text.image_position' => 'Bildposition',
41 | 'block_image_text.left' => 'Links',
42 | 'block_image_text.right' => 'Rechts',
43 | 'block_image_text.center' => 'Zentriert',
44 | 'block_image_text.image_shape' => 'Bildform',
45 | 'block_image_text.no_shape' => 'Keine Form',
46 | 'block_image_text.rounded_corners' => 'Abgerundete Ecken',
47 | 'block_image_text.thumbnail' => 'Thumbnail mit Umrandung',
48 | 'block_image_text.circle' => 'Kreis',
49 | 'block_image_text.image' => 'Bild',
50 | 'block_image_text.image.width' => 'Bildbreite',
51 | 'block_image_text.image.caption' => 'Bildlegende',
52 | 'block_image_text.image.caption.visibility' => 'Bildlegende anzeigen',
53 | 'block_image_text.help' => 'Bilder mit Text positionieren',
54 | 'block_image_text.no_text' => 'Es wurde noch kein Text hinzugefügt.',
55 | 'block_image_text.no_image' => 'Es wurde noch kein Bild hinzugefügt.',
56 | 'block_image_text.link' => 'Bild verlinken',
57 | 'block_image_text.file' => 'Datei',
58 | 'block_image_text.file_download' => 'Dateidownload via Bild',
59 |
60 | 'block_inlinetext.name'=> 'Inline Textblock',
61 | 'block_inlinetext.empty'=> 'Noch kein Text hinzugefügt',
62 | 'block_inlinetext.size-sm'=> 'Grösse Mobile',
63 | 'block_inlinetext.size-md'=> 'Grösse Tablet',
64 | 'block_inlinetext.size-lg'=> 'Grösse Desktop',
65 | 'block_inlinetext.size-full'=> 'Volle Breite',
66 | 'block_inlinetext.size'=> 'Breite',
67 |
68 | 'block_inline_wrapper.label'=>'Inline Blöcke hier platzieren ...',
69 | 'block_inline_wrapper.name'=>'Inline Textblock Raster',
70 |
71 | 'block_carousel.config_block_css_class' => 'Block CSS Klasse',
72 | 'block_carousel.config_caption_css_class' => 'Caption CSS Klasse',
73 | 'block_carousel.config_controls' => 'Controls',
74 | 'block_carousel.config_indicators' => 'Indicators',
75 | 'block_carousel.config_crossfade' => 'Crossfade',
76 | 'block_carousel.config_interval' => 'Interval',
77 | 'block_carousel.config_keyboard' => 'Keyboard',
78 | 'block_carousel.config_pause' => 'Pause',
79 | 'block_carousel.config_ride' => 'Ride',
80 | 'block_carousel.config_wrap' => 'Wrap',
81 | 'block_carousel.config_row' => 'Row',
82 | 'block_carousel.lazyload' => 'LazyLoad'
83 | ];
84 |
--------------------------------------------------------------------------------
/src/messages/id/bootstrap4.php:
--------------------------------------------------------------------------------
1 | 'List File',
7 | 'block_file_list.files_label' => 'File',
8 | 'block_file_list.show_type_label' => 'Tampilkan tipe file',
9 | 'block_file_list.show_type_icon' => 'Tampilkan tipe ikon file',
10 | 'block_file_list.show_file_size' => 'Tampilkan besar file',
11 |
12 | 'block_image.block_name' => 'Gambar',
13 | 'block_image.image' => 'Gambar',
14 | 'block_image.align' => 'Posisi Gambar',
15 | 'block_image.align_left' => 'Kiri',
16 | 'block_image.align_right' => 'Kanan',
17 | 'block_image.align_center' => 'Tengah',
18 | 'block_image.show_caption' => 'Tampilkan caption',
19 | 'block_image.lazyload' => 'LazyLoad',
20 |
21 | 'block_layout.block_name' => 'Layout: Baris',
22 | 'block_layout.content' => 'konten baris',
23 |
24 | 'block_layout_column.block_name' => 'Layout: Kolom',
25 | 'block_layout_column.column_count' => 'Ukuran XS up',
26 | 'block_layout_column.column_count_sm' => 'Ukuran SM up',
27 | 'block_layout_column.column_count_md' => 'Ukuran MD up',
28 | 'block_layout_column.column_count_lg' => 'Ukuran LG up',
29 | 'block_layout_column.column_count_xl' => 'Ukuran XL up',
30 | 'block_layout_column.content' => 'Konten kolom',
31 |
32 | 'block_carousel.items' => 'Slide',
33 | 'block_carousel.block_name' => 'Carousel',
34 | 'block_carousel.title' => 'Judul',
35 | 'block_carousel.caption' => 'Camption gambar',
36 | 'block_carousel.image' => 'Gambar',
37 | 'block_carousel.image_link' => 'Tautan',
38 |
39 | 'block_image_text.block_name' => 'Gambar dengan teks',
40 | 'block_image_text.image_position' => 'posisi gambar',
41 | 'block_image_text.left' => 'Kiri',
42 | 'block_image_text.right' => 'Kanan',
43 | 'block_image_text.center' => 'Tengah',
44 | 'block_image_text.image_shape' => 'Bentuk gambar',
45 | 'block_image_text.no_shape' => 'Tidak ada bentuk',
46 | 'block_image_text.rounded_corners' => 'Lengkungan tepi',
47 | 'block_image_text.thumbnail' => 'Gambar kecil dengan batasan',
48 | 'block_image_text.circle' => 'Lingkaran',
49 | 'block_image_text.image' => 'Gambar',
50 | 'block_image_text.image.width' => 'Lebar Gambar',
51 | 'block_image_text.image.caption' => 'Caption Gambar',
52 | 'block_image_text.image.caption.visibility' => 'Tampilkan caption image',
53 | 'block_image_text.help' => 'Add Images and text into a dynamic layout wrapper',
54 | 'block_image_text.no_text' => 'Tidak ada teks yang ditambahkan.',
55 | 'block_image_text.no_image' => 'Tidak ada gambar yang ditambahkan.',
56 | 'block_image_text.link' => 'Tautan gambar',
57 | 'block_image_text.file' => 'Menempel file',
58 | 'block_image_text.file_download' => 'Unduh file melalui gambar',
59 |
60 | 'block_inlinetext.name'=> 'Inline Text Block',
61 | 'block_inlinetext.empty'=> 'Tidak ada teks yang ditambahkan.',
62 | 'block_inlinetext.size-sm'=> 'Ukuran mobile',
63 | 'block_inlinetext.size-md'=> 'Ukuran tablet',
64 | 'block_inlinetext.size-lg'=> 'Ukuran desktop',
65 | 'block_inlinetext.size-full'=> 'Lebar penuh',
66 | 'block_inlinetext.size'=> 'Lebar',
67 |
68 | 'block_inline_wrapper.label'=>'Taruh inline blocks disini ...',
69 | 'block_inline_wrapper.name'=>'Inline Block Kontainer',
70 |
71 | 'block_carousel.config_block_css_class' => 'Block CSS Class',
72 | 'block_carousel.config_caption_css_class' => 'Caption CSS Class',
73 | 'block_carousel.config_controls' => 'Kontrol',
74 | 'block_carousel.config_indicators' => 'Indikator',
75 | 'block_carousel.config_crossfade' => 'Crossfade',
76 | 'block_carousel.config_interval' => 'Selang',
77 | 'block_carousel.config_keyboard' => 'Keyboard',
78 | 'block_carousel.config_pause' => 'Hentikan',
79 | 'block_carousel.config_ride' => 'Tunggangi',
80 | 'block_carousel.config_wrap' => 'Pindahkan',
81 | 'block_carousel.config_row' => 'Baris',
82 | 'block_carousel.lazyload' => 'LazyLoad'
83 | ];
84 |
--------------------------------------------------------------------------------
/src/messages/pt/bootstrap4.php:
--------------------------------------------------------------------------------
1 | 'Lista de arquivos',
7 | 'block_file_list.files_label' => 'Arquivos',
8 | 'block_file_list.show_type_label' => 'Mostrar tipo do arquivo',
9 | 'block_file_list.show_type_icon' => 'Mostrar icone do tipo do arquivo',
10 | 'block_file_list.show_file_size' => 'Mostrar tamanho do arquivo',
11 |
12 | 'block_image.block_name' => 'Imagem',
13 | 'block_image.image' => 'Imagem',
14 | 'block_image.align' => 'Posição da Imagem',
15 | 'block_image.align_left' => 'Esquerda',
16 | 'block_image.align_right' => 'Direita',
17 | 'block_image.align_center' => 'Centro',
18 | 'block_image.show_caption' => 'Mostrar legenda',
19 |
20 | 'block_layout.block_name' => 'Layout: Linhas',
21 | 'block_layout.content' => 'Conteúdo da linha',
22 |
23 | 'block_layout_column.block_name' => 'Layout: Coluna',
24 | 'block_layout_column.column_count' => 'Tamanho XS acima',
25 | 'block_layout_column.column_count_sm' => 'Tamanho SM acima',
26 | 'block_layout_column.column_count_md' => 'Tamanho MD acima',
27 | 'block_layout_column.column_count_lg' => 'Tamanho LG acima',
28 | 'block_layout_column.column_count_xl' => 'Tamanho XL acima',
29 | 'block_layout_column.content' => 'Conteúdo da coluna',
30 |
31 | 'block_carousel.items' => 'Slides', //not translated
32 | 'block_carousel.block_name' => 'Carrossel',
33 | 'block_carousel.title' => 'Título',
34 | 'block_carousel.caption' => 'Legenda da imagem',
35 | 'block_carousel.image' => 'Imagem',
36 | 'block_carousel.image_link' => 'Link',
37 |
38 | 'block_image_text.block_name' => 'Imagem com Texto',
39 | 'block_image_text.image_position' => 'Posição da Imagem',
40 | 'block_image_text.left' => 'Esquerda',
41 | 'block_image_text.right' => 'Direita',
42 | 'block_image_text.center' => 'Centro',
43 | 'block_image_text.image_shape' => 'Forma da Imagem',
44 | 'block_image_text.no_shape' => 'Sem forma',
45 | 'block_image_text.rounded_corners' => 'Bordas arredondadas',
46 | 'block_image_text.thumbnail' => 'Miniatura com borda',
47 | 'block_image_text.circle' => 'Círculo',
48 | 'block_image_text.image' => 'Imaem',
49 | 'block_image_text.image.width' => 'Largura da Imagem',
50 | 'block_image_text.image.caption' => 'Legenda da imagem',
51 | 'block_image_text.image.caption.visibility' => 'Mostrar legenda',
52 | 'block_image_text.help' => 'Adicionar Imagens e texto em um layout wrapper dinâmico',
53 | 'block_image_text.no_text' => 'Nenhum texto foi adicionado.',
54 | 'block_image_text.no_image' => 'Nenhuma imagem foi adicionada.',
55 | 'block_image_text.link' => 'Link da imagem',
56 | 'block_image_text.file' => 'Anexar arquivo',
57 | 'block_image_text.file_download' => 'Download do arquivo pela imagem',
58 |
59 | 'block_inlinetext.name'=> 'Bloco de Texto em linha',
60 | 'block_inlinetext.empty'=> 'Nenhum texto foi adicionado.',
61 | 'block_inlinetext.size-sm'=> 'Tamanho mobile',
62 | 'block_inlinetext.size-md'=> 'Tamanho tablet',
63 | 'block_inlinetext.size-lg'=> 'Tamanho desktop',
64 | 'block_inlinetext.size-full'=> 'Largura completa',
65 | 'block_inlinetext.size'=> 'largura',
66 |
67 | 'block_inline_wrapper.label'=>'Coloque os blocos em linha aqui ...',
68 | 'block_inline_wrapper.name'=>'Conteiner de Bloco em Linha',
69 |
70 | 'block_carousel.config_block_css_class' => 'Classe CSS do Bloco',
71 | 'block_carousel.config_caption_css_class' => 'Classe CSS da Legenda',
72 | 'block_carousel.config_controls' => 'Controles',
73 | 'block_carousel.config_indicators' => 'Indicadores',
74 | 'block_carousel.config_crossfade' => 'Crossfade', //no translated
75 | 'block_carousel.config_interval' => 'Intervalo',
76 | 'block_carousel.config_keyboard' => 'Teclado',
77 | 'block_carousel.config_pause' => 'Pausa',
78 | 'block_carousel.config_ride' => 'Direção',
79 | 'block_carousel.config_wrap' => 'Wrap', //not translated
80 | 'block_carousel.config_row' => 'Linha'
81 | ];
82 |
--------------------------------------------------------------------------------
/src/messages/fr/bootstrap4.php:
--------------------------------------------------------------------------------
1 | 'Liste des fichiers',
7 | 'block_file_list.files_label' => 'Fichiers',
8 | 'block_file_list.show_type_label' => 'Afficher le type des fichiers',
9 | 'block_file_list.show_type_icon' => 'Afficher l\'icon du type de fichier',
10 | 'block_file_list.show_file_size' => 'Afficher la taille du fichier',
11 |
12 | 'block_image.block_name' => 'Image',
13 | 'block_image.image' => 'Image',
14 | 'block_image.align' => 'Position de l\'image',
15 | 'block_image.align_left' => 'Gauche',
16 | 'block_image.align_right' => 'Droite',
17 | 'block_image.align_center' => 'Centre',
18 | 'block_image.show_caption' => 'Affficher la légende',
19 | 'block_image.lazyload' => 'Chargement différé',
20 |
21 | 'block_layout.block_name' => 'Disposition: Ligne',
22 | 'block_layout.content' => 'Contenu de la ligne',
23 |
24 | 'block_layout_column.block_name' => 'Disposition: Colonne',
25 | 'block_layout_column.column_count' => 'Taille XS et au dessus',
26 | 'block_layout_column.column_count_sm' => 'Taille SM et au dessus',
27 | 'block_layout_column.column_count_md' => 'Taille MD et au dessus',
28 | 'block_layout_column.column_count_lg' => 'Taille LG et au dessus',
29 | 'block_layout_column.column_count_xl' => 'Taille XL et au dessus',
30 | 'block_layout_column.content' => 'Contenu de la colonne',
31 |
32 | 'block_carousel.items' => 'Diapositives',
33 | 'block_carousel.block_name' => 'Carrousel',
34 | 'block_carousel.title' => 'Titre',
35 | 'block_carousel.caption' => 'Légende de l\'image',
36 | 'block_carousel.image' => 'Image',
37 | 'block_carousel.image_link' => 'Lien',
38 |
39 | 'block_image_text.block_name' => 'Image avec texte',
40 | 'block_image_text.image_position' => 'Position de l\'image',
41 | 'block_image_text.left' => 'Gauche',
42 | 'block_image_text.right' => 'Droite',
43 | 'block_image_text.center' => 'Centré',
44 | 'block_image_text.image_shape' => 'Forme de l\'image',
45 | 'block_image_text.no_shape' => 'Aucune forme',
46 | 'block_image_text.rounded_corners' => 'Coins arrondi',
47 | 'block_image_text.thumbnail' => 'Vignette avec bordure',
48 | 'block_image_text.circle' => 'Cercle',
49 | 'block_image_text.image' => 'Image',
50 | 'block_image_text.image.width' => 'Largeur de l\'image',
51 | 'block_image_text.image.caption' => 'Légende',
52 | 'block_image_text.image.caption.visibility' => 'Afficher la légende',
53 | 'block_image_text.help' => 'Ajouter des images et du texte dans un dispositif de mise en page dynamique ',
54 | 'block_image_text.no_text' => 'Aucun texte n\'a été ajouté pour le moment.',
55 | 'block_image_text.no_image' => 'Aucune image n\'a été ajoutée pour le moment.',
56 | 'block_image_text.link' => 'Lien de l\'image',
57 | 'block_image_text.file' => 'Pièce jointe',
58 | 'block_image_text.file_download' => 'Télécharger le fichier via l\'image',
59 |
60 | 'block_inlinetext.name'=> 'Bloc de texte en ligne',
61 | 'block_inlinetext.empty'=> 'Aucun texte n\'a été ajouté pour le moment.',
62 | 'block_inlinetext.size-sm'=> 'Taille mobile',
63 | 'block_inlinetext.size-md'=> 'Taille tablette',
64 | 'block_inlinetext.size-lg'=> 'Taille ordinateur',
65 | 'block_inlinetext.size-full'=> 'Plein écran',
66 | 'block_inlinetext.size'=> 'largeur',
67 |
68 | 'block_inline_wrapper.label'=>'Placez les blocs en ligne ici ...',
69 | 'block_inline_wrapper.name'=>'Conteneur de bloc en ligne',
70 |
71 | 'block_carousel.config_block_css_class' => 'Classe css de block',
72 | 'block_carousel.config_caption_css_class' => 'Classe CSS de la légende',
73 | 'block_carousel.config_controls' => 'Contrôles',
74 | 'block_carousel.config_indicators' => 'Indicateurs',
75 | 'block_carousel.config_crossfade' => 'Fondu',
76 | 'block_carousel.config_interval' => 'Interval',
77 | 'block_carousel.config_keyboard' => 'Clavier',
78 | 'block_carousel.config_pause' => 'Pause',
79 | 'block_carousel.config_ride' => 'Monter',
80 | 'block_carousel.config_wrap' => 'Envelopper',
81 | 'block_carousel.config_row' => 'Ligne',
82 | 'block_carousel.lazyload' => 'Chargement différé'
83 | ];
84 |
--------------------------------------------------------------------------------
/src/views/blocks/CarouselBlock.php:
--------------------------------------------------------------------------------
1 | extraValue('images');
8 | $indicators = null;
9 | $counter = 0;
10 |
11 | if (!empty($images)):
12 | $this->registerJs("$('.carousel').carousel(".$this->extraValue('jsConfig', '').");");
13 | $id = $this->extraValue('id');
14 | $hasImages = false;
15 | foreach ($images as $image) {
16 | if (isset($image['image'])) {
17 | $hasImages = true;
18 | break;
19 | }
20 | }
21 | if ($hasImages): ?>
22 |
23 |
24 | '; ?>
29 |
63 |
66 |
67 | = ($this->cfgValue('indicators', null) && $counter > 1) ? '
'.$indicators.' ' : '' ?>
68 | = $this->cfgValue(
69 | 'controls',
70 | null,
71 | '
72 |
73 | Previous
74 |
75 |
76 |
77 | Next
78 | '
79 | ); ?>
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/tests/src/blocks/ImageBlockTest.php:
--------------------------------------------------------------------------------
1 | assertSame('', $this->renderFrontendNoSpace());
16 | }
17 |
18 | public function testDefaultOutput()
19 | {
20 | $this->block->addExtraVar('image', (object) ['source' => 'luya.jpg', 'caption' => 'Test']);
21 |
22 | $this->assertContainsTrimmed('
23 |
24 |
25 |
26 |
27 |
', $this->renderFrontendNoSpace());
28 | }
29 |
30 | public function testAlignCenter()
31 | {
32 | $this->block->setVarValues(['align' => 'center']);
33 | $this->block->addExtraVar('image', (object) ['source' => 'luya.jpg', 'caption' => 'Test']);
34 |
35 | $this->assertContainsTrimmed('
36 |
37 |
38 |
39 |
40 |
', $this->renderFrontendNoSpace());
41 | }
42 |
43 | public function testAlignRight()
44 | {
45 | $this->block->setVarValues(['align' => 'right']);
46 | $this->block->addExtraVar('image', (object) ['source' => 'luya.jpg', 'caption' => 'Test']);
47 |
48 | $this->assertContainsTrimmed('
49 |
50 |
51 |
52 |
53 |
', $this->renderFrontendNoSpace());
54 | }
55 |
56 | public function testAlignRightCaption()
57 | {
58 | $this->block->setVarValues(['align' => 'right', 'showCaption' => true]);
59 | $this->block->addExtraVar('image', (object) ['source' => 'luya.jpg', 'caption' => 'Test']);
60 |
61 | $this->assertContainsTrimmed('
62 |
63 |
64 |
65 | Test
66 |
67 |
', $this->renderFrontendNoSpace());
68 | }
69 |
70 | public function testCaptionConfigSetWithEmptyCaptionValue()
71 | {
72 | $this->block->setVarValues(['align' => 'center', 'showCaption' => true]);
73 | $this->block->addExtraVar('image', (object) ['source' => 'luya.jpg']);
74 |
75 | $this->assertContainsTrimmed('
76 |
77 |
78 |
79 |
80 |
', $this->renderFrontendNoSpace());
81 | }
82 |
83 | public function testLazyLoad()
84 | {
85 | $this->block->addExtraVar('image', (object) ['source' => 'luya.jpg', 'caption' => 'Test', 'itemArray' => [ 'resolution_width' => 2, 'resolution_height' => 1]]);
86 | $this->block->setCfgValues(['lazyload' => 1]);
87 |
88 | $this->assertContainsTrimmed('', $this->renderFrontendNoSpace());
89 | }
90 |
91 |
92 | public function testLazyLoadWithEmptyCaption()
93 | {
94 | $this->block->setVarValues(['align' => 'left', 'showCaption' => true]);
95 | $this->block->addExtraVar('image', (object) ['source' => 'luya.jpg', 'itemArray' => [ 'resolution_width' => 2, 'resolution_height' => 1]]);
96 | $this->block->setCfgValues(['lazyload' => 1]);
97 |
98 | $this->assertContainsTrimmed('', $this->renderFrontendNoSpace());
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/tests/src/ActiveFormTest.php:
--------------------------------------------------------------------------------
1 | 'bs4app',
16 | 'basePath' => dirname(__DIR__) . '/../',
17 | 'components' => [
18 | 'assetManager' => [
19 | 'basePath' => dirname(__DIR__) . '/assets',
20 | 'bundles' => [
21 | 'yii\web\JqueryAsset' => false,
22 | 'luya\bootstrap4\Bootstrap4Asset' => false,
23 | ],
24 | ],
25 | 'storage' => [
26 | 'class' => 'luya\admin\filesystem\DummyFileSystem',
27 | 'filesArray' => [],
28 | 'imagesArray' => [],
29 | ],
30 | ]
31 | ];
32 | }
33 |
34 | public function testActiveFormLayout()
35 | {
36 | Yii::setAlias('@webroot', dirname(__DIR__));
37 | $model = new StubModel();
38 | ob_start();
39 | ob_implicit_flush(false);
40 |
41 | $form = ActiveForm::begin(['layout' => 'horizontal']);
42 | echo $form->field($model, 'firstname');
43 | ActiveForm::end();
44 |
45 | $this->assertContainsTrimmed('
46 | ', ob_get_clean());
53 | }
54 | public function testCheckboxSwitch()
55 | {
56 | Yii::setAlias('@webroot', dirname(__DIR__));
57 | $model = new StubModel();
58 | ob_start();
59 | ob_implicit_flush(false);
60 |
61 | $form = ActiveForm::begin(['layout' => 'horizontal']);
62 | echo $form->field($model, 'firstname')->checkboxSwitch();
63 | ActiveForm::end();
64 |
65 | $this->assertContainsTrimmed('
66 | ', ob_get_clean());
67 | }
68 |
69 | public function testActiveFormValidationError()
70 | {
71 | Yii::setAlias('@webroot', dirname(__DIR__));
72 | $model = new StubModel();
73 | $model->addError('firstname', 'Some error!');
74 | ob_start();
75 | ob_implicit_flush(false);
76 |
77 | $form = ActiveForm::begin(['layout' => 'horizontal']);
78 | echo $form->field($model, 'firstname');
79 | ActiveForm::end();
80 | ob_get_clean();
81 |
82 | $this->assertContainsTrimmed('
83 | ', (string) $form->field($model, 'firstname'));
90 | }
91 |
92 | public function testValidAndInvalidWthAttributeHints()
93 | {
94 | $model = new Stub2Model();
95 | $model->addError('lastname', 'Error!');
96 |
97 | ob_start();
98 | $form = ActiveForm::begin([
99 | 'action' => '/something',
100 | 'enableClientScript' => false,
101 | 'validationStateOn' => ActiveForm::VALIDATION_STATE_ON_INPUT,
102 | ]);
103 | ActiveForm::end();
104 | ob_end_clean();
105 |
106 | $this->assertContainsTrimmed('
107 | ', (string) $form->field($model, 'firstname'));
112 | $this->assertContainsTrimmed('
113 | ', (string) $form->field($model, 'lastname'));
118 | $this->assertContainsTrimmed('
119 | ', (string) $form->field($model, 'info'));
125 | }
126 | }
127 |
128 | /* the inline stub model to use for the active form */
129 |
130 | class StubModel extends Model
131 | {
132 | public $firstname = null;
133 |
134 | public function rules()
135 | {
136 | return [
137 | [['firstname'], 'string'],
138 | ];
139 | }
140 | }
141 |
142 |
143 | class Stub2Model extends Model
144 | {
145 | public $firstname = null;
146 | public $lastname;
147 | public $info;
148 |
149 | public function rules()
150 | {
151 | return [
152 | [['firstname', 'lastname', 'info'], 'string'],
153 | ];
154 | }
155 |
156 | public function attributeHints()
157 | {
158 | return ['info' => 'some hint message'];
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/src/blocks/CarouselBlock.php:
--------------------------------------------------------------------------------
1 |
15 | * @since 1.0.0
16 | */
17 | class CarouselBlock extends BaseBootstrap4Block
18 | {
19 | public $module = 'bootstrap4';
20 |
21 | /**
22 | * @inheritdoc
23 | */
24 | public function name()
25 | {
26 | return Module::t('block_carousel.block_name');
27 | }
28 |
29 | /**
30 | * @inheritdoc
31 | */
32 | public function blockGroup()
33 | {
34 | return BootstrapGroup::class;
35 | }
36 |
37 | /**
38 | * @inheritdoc
39 | */
40 | public function icon()
41 | {
42 | return 'view_carousel';
43 | }
44 |
45 | /**
46 | * @inheritdoc
47 | */
48 | public function config()
49 | {
50 | return [
51 | 'vars' => [
52 | ['var' => 'images', 'label' => Module::t('block_carousel.items'), 'type' => self::TYPE_MULTIPLE_INPUTS, 'options' => [
53 | ['var' => 'title', 'type' => self::TYPE_TEXT, 'label' => Module::t('block_carousel.title')],
54 | ['var' => 'caption', 'type' => self::TYPE_TEXTAREA, 'label' => Module::t('block_carousel.caption')],
55 | ['var' => 'image', 'type' => self::TYPE_IMAGEUPLOAD, 'label' => Module::t('block_carousel.image')],
56 | ['var' => 'link', 'type' => self::TYPE_LINK, 'label' => Module::t('block_carousel.image_link')]
57 | ]],
58 | ],
59 | 'cfgs' => [
60 | ['var' => 'blockCssClass', 'type' => self::TYPE_TEXT, 'label' => Module::t('block_carousel.config_block_css_class')],
61 | ['var' => 'captionCssClass', 'type' => self::TYPE_TEXT, 'label' => Module::t('block_carousel.config_caption_css_class')],
62 | ['var' => 'controls', 'type' => self::TYPE_CHECKBOX, 'label' => Module::t('block_carousel.config_controls'), 'initvalue' => 1],
63 | ['var' => 'indicators', 'type' => self::TYPE_CHECKBOX, 'label' => Module::t('block_carousel.config_indicators'), 'initvalue' => 1],
64 | ['var' => 'crossfade', 'type' => self::TYPE_CHECKBOX, 'label' => Module::t('block_carousel.config_crossfade'), 'initvalue' => 1],
65 | ['var' => 'interval', 'type' => self::TYPE_NUMBER, 'label' => Module::t('block_carousel.config_interval')],
66 | ['var' => 'keyboard', 'type' => self::TYPE_CHECKBOX, 'label' => Module::t('block_carousel.config_keyboard'), 'initvalue' => 1],
67 | ['var' => 'pause', 'type' => self::TYPE_TEXT, 'label' => Module::t('block_carousel.config_pause')],
68 | ['var' => 'ride', 'type' => self::TYPE_TEXT, 'label' => Module::t('block_carousel.config_ride')],
69 | ['var' => 'wrap', 'type' => self::TYPE_CHECKBOX, 'label' => Module::t('block_carousel.config_wrap'), 'initvalue' => 0],
70 | ['var' => 'row', 'type' => self::TYPE_CHECKBOX, 'label' => Module::t('block_carousel.config_row'), 'initvalue' => 0],
71 | ['var' => 'lazyload', 'label' => Module::t('block_carousel.lazyload'), 'type' => self::TYPE_CHECKBOX]
72 | ]
73 | ];
74 | }
75 |
76 | public function getFieldHelp()
77 | {
78 | return [
79 | 'blockCssClass' => 'Adds a class to the root contianer of the carousel.',
80 | 'captionCssClass' => 'Adds a class to the carousel item caption element.',
81 | 'controls' => 'Adds the previous and next controls arrows on the left and right side of the image.',
82 | 'indicators' => 'Indicators are additional controls which displays all slides with an indicator which is clickable. The indicator is placed in the middle of the image.',
83 | 'crossfade' => 'Add crossfase to your carousel to animate slides with a fade transition instead of a slide.',
84 | 'interval' => 'The amount of time to delay between automatically cycling an item. If false, carousel will not automatically cycle.',
85 | 'keyboard' => 'Whether the carousel should react to keyboard events.',
86 | 'pause' => 'If set to "hover", pauses the cycling of the carousel on mouseenter and resumes the cycling of the carousel on mouseleave. If set to false, hovering over the carousel won\'t pause it. On touch-enabled devices, when set to "hover", cycling will pause on touchend (once the user finished interacting with the carousel) for two intervals, before automatically resuming. Note that this is in addition to the above mouse behavior.',
87 | 'ride' => 'Autoplays the carousel after the user manually cycles the first item. If "carousel", autoplays the carousel on load.',
88 | 'wrap' => 'Whether the carousel should cycle continuously or have hard stops.',
89 | "row" => 'Adds the row class to the carousel container.',
90 | ];
91 | }
92 |
93 | /**
94 | * Get all carousel images (slides)
95 | *
96 | * @return array images
97 | */
98 | public function images()
99 | {
100 | $images = [];
101 | foreach ($this->getVarValue('images', []) as $item) {
102 | $image = BlockHelper::imageUpload($item['image'], false, true);
103 | if ($image) {
104 | $images[] = [
105 | 'image' => $image,
106 | 'title' => isset($item['title']) ? $item['title'] : null,
107 | 'caption' => isset($item['caption']) ? $item['caption'] : null,
108 | 'link' => isset($item['link']) ? BlockHelper::linkObject($item['link']) : null,
109 | ];
110 | }
111 | }
112 | return $images;
113 | }
114 |
115 | /**
116 | * Returns the carousel javascript configuration
117 | *
118 | * @return string Json encoded configuration
119 | */
120 | public function getJsConfig()
121 | {
122 | return Json::encode([
123 | 'interval' => $this->getCfgValue('interval', 5000),
124 | 'keyboard' => $this->getCfgValue('keyboard', 1) == 1 ? true : false,
125 | 'pause' => $this->getCfgValue('pause', 'hover'),
126 | 'ride' => $this->getCfgValue('ride', false),
127 | 'wrap' => $this->getCfgValue('wrap', 1) == 1 ? true : false,
128 | ]);
129 | }
130 |
131 | /**
132 | * {@inheritdoc}
133 | */
134 | public function extraVars()
135 | {
136 | return [
137 | 'images' => $this->images(),
138 | 'id' => 'carousel_'.md5($this->getEnvOption('id')),
139 | 'jsConfig' => $this->getJsConfig()
140 | ];
141 | }
142 |
143 | /**
144 | * @inheritdoc
145 | */
146 | // Todo: Needs adjustment to display correct
147 | public function admin()
148 | {
149 | return '
150 | {% if extras.images %}
151 | {% set hasImage = false %}
152 | {% for image in extras.images %}
153 | {% if image.image.source %}
154 | {% set hasImage = true %}
155 | {% endif %}
156 | {% endfor %}
157 | {% if hasImage %}
158 |
159 | {% for image in extras.images %}
160 | {% if image.image.source %}
161 |
162 |
163 |
164 | {% endif %}
165 | {% endfor %}
166 |
167 | {% endif %}
168 | {% endif %}';
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/tests/src/widgets/LinkPagerTest.php:
--------------------------------------------------------------------------------
1 | $pag]);
16 |
17 | $this->assertContainsTrimmed('', ob_get_clean());
18 | }
19 |
20 | public function testDefaultOutputWithTotalCount()
21 | {
22 | $pag = new \yii\data\Pagination([
23 | 'totalCount' => 20
24 | ]);
25 | ob_start();
26 | ob_implicit_flush(false);
27 | echo LinkPager::widget(['pagination' => $pag]);
28 |
29 | $this->assertContainsTrimmed('', ob_get_clean());
30 | }
31 |
32 | public function testDefaultOutputWithPageSize()
33 | {
34 | $pag = new \yii\data\Pagination([
35 | 'pageSize' => 5
36 | ]);
37 | ob_start();
38 | ob_implicit_flush(false);
39 | echo LinkPager::widget(['pagination' => $pag]);
40 |
41 | $this->assertContainsTrimmed('', ob_get_clean());
42 | }
43 |
44 | public function testDefaultOutputWithCurrentPage1()
45 | {
46 | $pag = new \yii\data\Pagination([
47 | 'page' => 1
48 | ]);
49 | ob_start();
50 | ob_implicit_flush(false);
51 | echo LinkPager::widget(['pagination' => $pag]);
52 |
53 | $this->assertContainsTrimmed('', ob_get_clean());
54 | }
55 |
56 | public function testDefaultOutputWithCurrentPage4()
57 | {
58 | $pag = new \yii\data\Pagination([
59 | 'page' => 4
60 | ]);
61 | ob_start();
62 | ob_implicit_flush(false);
63 | echo LinkPager::widget(['pagination' => $pag]);
64 |
65 | $this->assertContainsTrimmed('', ob_get_clean());
66 | }
67 |
68 | public function testDefaultOutputWithCurrentPage7()
69 | {
70 | $pag = new \yii\data\Pagination([
71 | 'page' => 7
72 | ]);
73 | ob_start();
74 | ob_implicit_flush(false);
75 | echo LinkPager::widget(['pagination' => $pag]);
76 |
77 | $this->assertContainsTrimmed('', ob_get_clean());
78 | }
79 |
80 | public function testDefaultOutputCombinedPage0of0()
81 | {
82 | $pag = new \yii\data\Pagination([
83 | 'totalCount' => 5,
84 | 'pageSize' => 5,
85 | 'page' => 0
86 | ]);
87 | ob_start();
88 | ob_implicit_flush(false);
89 | echo LinkPager::widget(['pagination' => $pag]);
90 |
91 | $this->assertContainsTrimmed('', ob_get_clean());
92 | }
93 |
94 | public function testDefaultOutputCombinedPage0of1()
95 | {
96 | $pag = new \yii\data\Pagination([
97 | 'totalCount' => 10,
98 | 'pageSize' => 5,
99 | 'page' => 0,
100 | 'route' => 'foobar'
101 | ]);
102 | ob_start();
103 | ob_implicit_flush(false);
104 | echo LinkPager::widget(['pagination' => $pag]);
105 |
106 | $this->assertContainsTrimmed('', ob_get_clean());
120 | }
121 |
122 | public function testDefaultOutputCombinedPage0of7()
123 | {
124 | $pag = new \yii\data\Pagination([
125 | 'totalCount' => 40,
126 | 'pageSize' => 5,
127 | 'page' => 0,
128 | 'route' => 'foobar'
129 | ]);
130 | ob_start();
131 | ob_implicit_flush(false);
132 | echo LinkPager::widget(['pagination' => $pag]);
133 |
134 | $this->assertContainsTrimmed('', ob_get_clean());
166 | }
167 |
168 | public function testDefaultOutputCombinedPage3of7()
169 | {
170 | $pag = new \yii\data\Pagination([
171 | 'totalCount' => 40,
172 | 'pageSize' => 5,
173 | 'page' => 3,
174 | 'route' => 'foobar'
175 | ]);
176 | ob_start();
177 | ob_implicit_flush(false);
178 | echo LinkPager::widget(['pagination' => $pag]);
179 |
180 | $this->assertContainsTrimmed('', ob_get_clean());
212 | }
213 |
214 | public function testDefaultOutputCombinedPage7of7()
215 | {
216 | $pag = new \yii\data\Pagination([
217 | 'totalCount' => 40,
218 | 'pageSize' => 5,
219 | 'page' => 7,
220 | 'route' => 'foobar'
221 | ]);
222 | ob_start();
223 | ob_implicit_flush(false);
224 | echo LinkPager::widget(['pagination' => $pag]);
225 |
226 | $this->assertContainsTrimmed('', ob_get_clean());
258 | }
259 | }
--------------------------------------------------------------------------------
/tests/src/blocks/CarouselBlockTest.php:
--------------------------------------------------------------------------------
1 | assertSameTrimmed('',
16 | $this->renderFrontendNoSpace()
17 | );
18 |
19 | $this->assertSameTrimmed('', $this->renderAdminNoSpace());
20 | }
21 |
22 | public function testEmptyImageArray()
23 | {
24 | $this->block->addExtraVar('images', []);
25 |
26 | $this->assertSameTrimmed(
27 | '',
28 | $this->renderFrontendNoSpace()
29 | );
30 |
31 | $this->assertSameTrimmed('', $this->renderAdminNoSpace());
32 | }
33 |
34 | public function testImageArrayWithEmptyImageInArray()
35 | {
36 | $this->block->addExtraVar('images', [
37 | []
38 | ]);
39 |
40 | $this->assertSameTrimmed(
41 | '',
42 | $this->renderFrontendNoSpace()
43 | );
44 |
45 | $this->assertSameTrimmed('', $this->renderAdminNoSpace());
46 | }
47 |
48 | public function testImageArrayWithEmptyImagesInArray()
49 | {
50 | $this->block->addExtraVar('images', [
51 | [],
52 | [],
53 | []
54 | ]);
55 |
56 | $this->assertSameTrimmed(
57 | '',
58 | $this->renderFrontendNoSpace()
59 | );
60 |
61 | $this->assertSameTrimmed('', $this->renderAdminNoSpace());
62 | }
63 |
64 | public function testImageArrayWithSingleImageInArray()
65 | {
66 | Yii::$app->storage->addDummyFile(['id' => 1]);
67 | Yii::$app->storage->insertDummyFiles();
68 |
69 | $this->block->addExtraVar('images', [
70 | [
71 | 'image' => Item::create(['caption' => 'cap-title', 'file_id' => 1, 'filter_id' => 0]),
72 | 'title' => 'title',
73 | 'link' => 'foobar',
74 | 'caption' => 'caption'
75 | ]
76 | ]);
77 |
78 | $this->assertSameTrimmed(
79 | '',
92 | $this->renderFrontendNoSpace()
93 | );
94 |
95 | $this->assertSameTrimmed('', $this->renderAdminNoSpace());
96 | }
97 |
98 | public function testImageArrayWithEmptyFirstAndSingleImageInArray()
99 | {
100 | Yii::$app->storage->addDummyFile(['id' => 1]);
101 | Yii::$app->storage->insertDummyFiles();
102 |
103 | $this->block->addExtraVar('images', [
104 | [],
105 | [
106 | 'image' => Item::create(['caption' => 'cap-title', 'file_id' => 1, 'filter_id' => 0]),
107 | 'title' => 'title',
108 | 'link' => 'foobar',
109 | 'caption' => 'caption'
110 | ],
111 | ]);
112 |
113 | $this->assertSameTrimmed(
114 | '',
127 | $this->renderFrontendNoSpace()
128 | );
129 |
130 | $this->assertSameTrimmed('', $this->renderAdminNoSpace());
131 | }
132 |
133 | public function testImageArrayWithMultipleImagesInArray()
134 | {
135 | Yii::$app->storage->addDummyFile(['id' => 1]);
136 | Yii::$app->storage->addDummyFile(['id' => 2]);
137 | Yii::$app->storage->insertDummyFiles();
138 |
139 | $this->block->addExtraVar('images', [
140 | [
141 | 'image' => Item::create(['caption' => 'caption', 'file_id' => 1, 'filter_id' => 0]),
142 | 'title' => 'title',
143 | 'caption' => 'caption',
144 | 'link' => 'foobar',
145 |
146 | ],
147 | [
148 | 'image' => Item::create(['caption' => 'caption', 'file_id' => 2, 'filter_id' => 0]),
149 | 'title' => 'title',
150 | 'link' => 'foobar',
151 |
152 | ]
153 | ]);
154 |
155 | $this->assertSameTrimmed('', $this->renderFrontendNoSpace());
176 |
177 | $this->assertSameTrimmed('', $this->renderAdminNoSpace());
178 | }
179 |
180 | public function testImageArrayWithMultipleImagesAndEmptyImageInArray()
181 | {
182 | Yii::$app->storage->addDummyFile(['id' => 1]);
183 | Yii::$app->storage->addDummyFile(['id' => 2]);
184 | Yii::$app->storage->insertDummyFiles();
185 |
186 | $this->block->addExtraVar('images', [
187 | [],
188 | [
189 | 'image' => Item::create(['caption' => 'caption', 'file_id' => 1, 'filter_id' => 0]),
190 | 'title' => 'title',
191 | 'caption' => 'caption',
192 | 'link' => 'foobar',
193 |
194 | ],
195 | [],
196 | [
197 | 'image' => Item::create(['caption' => 'caption', 'file_id' => 2, 'filter_id' => 0]),
198 | 'title' => 'title',
199 | 'link' => 'foobar',
200 |
201 | ]
202 | ]);
203 |
204 | $this->assertSameTrimmed('', $this->renderFrontendNoSpace());
225 |
226 | $this->assertSameTrimmed('', $this->renderAdminNoSpace());
227 | }
228 |
229 | public function testImageWithoutTitle()
230 | {
231 | Yii::$app->storage->addDummyFile(['id' => 1]);
232 | Yii::$app->storage->insertDummyFiles();
233 |
234 | $this->block->addExtraVar('images', [
235 | [
236 | 'image' => Item::create(['caption' => 'cap-title', 'file_id' => 1, 'filter_id' => 0]),
237 | 'link' => 'foobar',
238 | 'caption' => 'caption'
239 | ]
240 | ]);
241 |
242 | $this->assertSameTrimmed(
243 | '',
255 | $this->renderFrontendNoSpace()
256 | );
257 |
258 | $this->assertSameTrimmed('', $this->renderAdminNoSpace());
259 | }
260 |
261 | public function testImageWithEmptyTitle()
262 | {
263 | Yii::$app->storage->addDummyFile(['id' => 1]);
264 | Yii::$app->storage->insertDummyFiles();
265 |
266 | $this->block->addExtraVar('images', [
267 | [
268 | 'image' => Item::create(['caption' => 'cap-title', 'file_id' => 1, 'filter_id' => 0]),
269 | 'title' => '',
270 | 'link' => 'foobar',
271 | 'caption' => 'caption'
272 | ]
273 | ]);
274 |
275 | $this->assertSameTrimmed(
276 | '',
288 | $this->renderFrontendNoSpace()
289 | );
290 |
291 | $this->assertSameTrimmed('', $this->renderAdminNoSpace());
292 | }
293 |
294 | public function testImageWithoutCaption()
295 | {
296 | Yii::$app->storage->addDummyFile(['id' => 1]);
297 | Yii::$app->storage->insertDummyFiles();
298 |
299 | $this->block->addExtraVar('images', [
300 | [
301 | 'image' => Item::create(['caption' => 'cap-title', 'file_id' => 1, 'filter_id' => 0]),
302 | 'title' => 'title',
303 | 'link' => 'foobar'
304 | ]
305 | ]);
306 |
307 | $this->assertSameTrimmed(
308 | '',
320 | $this->renderFrontendNoSpace()
321 | );
322 |
323 | $this->assertSameTrimmed('', $this->renderAdminNoSpace());
324 | }
325 |
326 | public function testImageWithEmptyCaption()
327 | {
328 | Yii::$app->storage->addDummyFile(['id' => 1]);
329 | Yii::$app->storage->insertDummyFiles();
330 |
331 | $this->block->addExtraVar('images', [
332 | [
333 | 'image' => Item::create(['caption' => 'cap-title', 'file_id' => 1, 'filter_id' => 0]),
334 | 'title' => 'title',
335 | 'link' => 'foobar',
336 | 'caption' => ''
337 | ]
338 | ]);
339 |
340 | $this->assertSameTrimmed(
341 | '',
353 | $this->renderFrontendNoSpace()
354 | );
355 |
356 | $this->assertSameTrimmed('', $this->renderAdminNoSpace());
357 | }
358 |
359 | public function testImageWithoutLink()
360 | {
361 | Yii::$app->storage->addDummyFile(['id' => 1]);
362 | Yii::$app->storage->insertDummyFiles();
363 |
364 | $this->block->addExtraVar('images', [
365 | [
366 | 'image' => Item::create(['caption' => 'cap-title', 'file_id' => 1, 'filter_id' => 0]),
367 | 'title' => 'title',
368 | 'caption' => 'caption'
369 | ]
370 | ]);
371 |
372 | $this->assertSameTrimmed(
373 | '
374 |
375 |
376 |
377 |
378 |
title
379 |
caption
380 |
381 |
382 |
383 |
',
384 | $this->renderFrontendNoSpace()
385 | );
386 |
387 | $this->assertSameTrimmed('', $this->renderAdminNoSpace());
388 | }
389 |
390 | public function testImageWithEmptyLink()
391 | {
392 | Yii::$app->storage->addDummyFile(['id' => 1]);
393 | Yii::$app->storage->insertDummyFiles();
394 |
395 | $this->block->addExtraVar('images', [
396 | [
397 | 'image' => Item::create(['caption' => 'cap-title', 'file_id' => 1, 'filter_id' => 0]),
398 | 'title' => 'title',
399 | 'link' => '',
400 | 'caption' => 'caption'
401 | ]
402 | ]);
403 |
404 | $this->assertSameTrimmed(
405 | '
406 |
407 |
408 |
409 |
410 |
title
411 |
caption
412 |
413 |
414 |
415 |
',
416 | $this->renderFrontendNoSpace()
417 | );
418 |
419 | $this->assertSameTrimmed('', $this->renderAdminNoSpace());
420 | }
421 |
422 |
423 | public function testImageWithoutImage()
424 | {
425 | $this->block->addExtraVar('images', [
426 | [
427 | 'title' => 'title',
428 | 'link' => 'foobar',
429 | 'caption' => 'caption'
430 | ]
431 | ]);
432 |
433 | $this->assertSameTrimmed(
434 | '',
435 | $this->renderFrontendNoSpace()
436 | );
437 |
438 | $this->assertSameTrimmed('', $this->renderAdminNoSpace());
439 | }
440 |
441 | // /*
442 | // * @todo var value testing
443 | // */
444 | // public function testVars()
445 | // {
446 | // $this->block->setVarValues(['title' => 'my title', 'caption' => 'caption']);
447 | // $this->block->addExtraVar('image', (object) ['source' => 'image.jpg']);
448 | // $this->assertContainsTrimmed('
449 | // ', $this->renderFrontendNoSpace());
468 | // $this->assertContainsTrimmed('', $this->renderAdminNoSpace());
469 | // }
470 |
471 | public function testIndicatorConfig()
472 | {
473 | Yii::$app->storage->addDummyFile(['id' => 1]);
474 | Yii::$app->storage->addDummyFile(['id' => 2]);
475 | Yii::$app->storage->insertDummyFiles();
476 |
477 | $this->block->setCfgValues(['indicators' => true]);
478 |
479 | $this->block->addExtraVar('images', [
480 | [
481 | 'image' => Item::create(['caption' => 'caption', 'file_id' => 1, 'filter_id' => 0]),
482 | 'title' => 'title',
483 | 'caption' => 'caption',
484 | 'link' => 'foobar',
485 |
486 | ],
487 | [
488 | 'image' => Item::create(['caption' => 'caption', 'file_id' => 2, 'filter_id' => 0]),
489 | 'title' => 'title',
490 | 'link' => 'foobar'
491 | ]
492 | ]);
493 |
494 | $this->assertSameTrimmed('
495 |
514 |
515 |
516 |
517 |
518 |
', $this->renderFrontendNoSpace());
519 |
520 | $this->assertSameTrimmed('', $this->renderAdminNoSpace());
521 | }
522 |
523 | public function testIndicatorConfigurationWithOneImage()
524 | {
525 | Yii::$app->storage->addDummyFile(['id' => 1]);
526 | Yii::$app->storage->insertDummyFiles();
527 |
528 | $this->block->setCfgValues(['indicators' => true]);
529 |
530 | $this->block->addExtraVar('images', [
531 | [
532 | 'image' => Item::create(['caption' => 'caption', 'file_id' => 1, 'filter_id' => 0]),
533 | 'title' => 'title',
534 | 'caption' => 'caption',
535 | 'link' => 'foobar',
536 | ]
537 | ]);
538 |
539 | $this->assertSameTrimmed('', $this->renderFrontendNoSpace());
552 |
553 | $this->assertSameTrimmed('', $this->renderAdminNoSpace());
554 | }
555 |
556 | /*
557 | * @todo test other configs
558 | */
559 |
560 | public function testLazyLoadConfiguration()
561 | {
562 | Yii::$app->storage->addDummyFile(['id' => 1]);
563 | Yii::$app->storage->insertDummyFiles();
564 | $this->block->setCfgValues(['lazyload' => 1]);
565 |
566 | $this->block->addExtraVar('images', [
567 | [
568 | 'image' => Item::create(['caption' => 'cap-title', 'file_id' => 1, 'filter_id' => 0, 'resolution_width' => 2, 'resolution_height' => 1]),
569 | 'title' => 'title',
570 | 'link' => 'foobar',
571 | 'caption' => 'caption'
572 | ]
573 | ]);
574 |
575 | $this->assertSameTrimmed(
576 | '',
598 | $this->renderFrontendNoSpace()
599 | );
600 | }
601 |
602 | public function testBlockName()
603 | {
604 | $this->app->language = 'de';
605 | $this->assertSame('Carousel', $this->block->name());
606 | }
607 | }
608 |
--------------------------------------------------------------------------------