Revert "Rebase October CMS on Laravel 6 (#4893)"
This reverts commit ee0065d353.
This commit is contained in:
parent
ee0065d353
commit
60afd41cc2
|
|
@ -6,18 +6,25 @@ on:
|
|||
jobs:
|
||||
codeQuality:
|
||||
runs-on: ubuntu-latest
|
||||
name: PHPCS
|
||||
name: PHP
|
||||
steps:
|
||||
- name: Checkout changes
|
||||
uses: actions/checkout@v1
|
||||
- name: Install PHP and PHP Code Sniffer
|
||||
uses: shivammathur/setup-php@v1
|
||||
- name: Install PHP
|
||||
uses: shivammathur/setup-php@master
|
||||
with:
|
||||
php-version: '7.3'
|
||||
tools: phpcs
|
||||
- name: Setup problem matcher for PHPCS
|
||||
run: echo "::add-matcher::${{ github.workspace }}/.github/workflows/matchers/phpcs-matcher.json"
|
||||
php-version: 7.2
|
||||
- name: Install Composer dependencies
|
||||
run: composer install --no-interaction --no-progress --no-suggest
|
||||
- name: Reset October modules and library
|
||||
run: |
|
||||
git reset --hard HEAD
|
||||
rm -rf ./vendor/october/rain
|
||||
wget https://github.com/octobercms/library/archive/develop.zip -O ./vendor/october/develop.zip
|
||||
unzip ./vendor/october/develop.zip -d ./vendor/october
|
||||
mv ./vendor/october/library-develop ./vendor/october/rain
|
||||
composer dump-autoload
|
||||
- name: Run code quality checks
|
||||
run: |
|
||||
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" && git fetch
|
||||
phpcs --colors -nq --report="checkstyle" --extensions="php" $(git diff --name-only --diff-filter=ACMR origin/${{ github.base_ref }} HEAD)
|
||||
./vendor/bin/phpcs --colors -nq --report="full" --extensions="php" $(git diff --name-only --diff-filter=ACMR origin/${{ github.base_ref }} HEAD)
|
||||
|
|
|
|||
|
|
@ -9,16 +9,23 @@ on:
|
|||
jobs:
|
||||
codeQuality:
|
||||
runs-on: ubuntu-latest
|
||||
name: PHPCS
|
||||
name: PHP
|
||||
steps:
|
||||
- name: Checkout changes
|
||||
uses: actions/checkout@v1
|
||||
- name: Install PHP and PHP Code Sniffer
|
||||
uses: shivammathur/setup-php@v1
|
||||
- name: Install PHP
|
||||
uses: shivammathur/setup-php@master
|
||||
with:
|
||||
php-version: '7.3'
|
||||
tools: phpcs
|
||||
- name: Setup problem matcher for PHPCS
|
||||
run: echo "::add-matcher::${{ github.workspace }}/.github/workflows/matchers/phpcs-matcher.json"
|
||||
php-version: 7.2
|
||||
- name: Install Composer dependencies
|
||||
run: composer install --no-interaction --no-progress --no-suggest
|
||||
- name: Reset October modules and library
|
||||
run: |
|
||||
git reset --hard HEAD
|
||||
rm -rf ./vendor/october/rain
|
||||
wget https://github.com/octobercms/library/archive/develop.zip -O ./vendor/october/develop.zip
|
||||
unzip ./vendor/october/develop.zip -d ./vendor/october
|
||||
mv ./vendor/october/library-develop ./vendor/october/rain
|
||||
composer dump-autoload
|
||||
- name: Run code quality checks
|
||||
run: phpcs --colors -nq --report="checkstyle" --extensions="php" $(git show --name-only --pretty="" --diff-filter=ACMR ${{ github.sha }})
|
||||
run: ./vendor/bin/phpcs --colors -nq --report="full" --extensions="php" $(git show --name-only --pretty="" --diff-filter=ACMR ${{ github.sha }})
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
name: Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
frontendTests:
|
||||
runs-on: ubuntu-latest
|
||||
name: JavaScript
|
||||
steps:
|
||||
- name: Checkout changes
|
||||
uses: actions/checkout@v1
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 8
|
||||
- name: Install Node dependencies
|
||||
run: npm install
|
||||
- name: Run tests
|
||||
run: npm run test
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "phpcs",
|
||||
"severity": "error",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^<file name=\"(.*)\">$",
|
||||
"file": 1
|
||||
},
|
||||
{
|
||||
"regexp": "<error line=\"(\\d*)\" column=\"(\\d*)\" severity=\"(error|warning)\" message=\"(.*)\" source=\"(.*)(\"\\/>+)$",
|
||||
"line": 1,
|
||||
"column": 2,
|
||||
"severity": 3,
|
||||
"message": 4,
|
||||
"code": 5,
|
||||
"loop": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -8,56 +8,37 @@ on:
|
|||
pull_request:
|
||||
|
||||
jobs:
|
||||
frontendTests:
|
||||
runs-on: ubuntu-latest
|
||||
name: JavaScript
|
||||
steps:
|
||||
- name: Checkout changes
|
||||
uses: actions/checkout@v1
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 8
|
||||
- name: Install Node dependencies
|
||||
run: npm install
|
||||
- name: Run tests
|
||||
run: npm run test
|
||||
phpUnitTests:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
max-parallel: 6
|
||||
matrix:
|
||||
phpVersions: ['7.2', '7.3', '7.4']
|
||||
phpVersions: ['7.1', '7.2', '7.3', '7.4']
|
||||
fail-fast: false
|
||||
name: Unit Tests / PHP ${{ matrix.phpVersions }}
|
||||
name: PHP ${{ matrix.phpVersions }}
|
||||
steps:
|
||||
- name: Checkout changes
|
||||
uses: actions/checkout@v1
|
||||
- name: Install PHP
|
||||
uses: shivammathur/setup-php@v1
|
||||
uses: shivammathur/setup-php@master
|
||||
with:
|
||||
php-version: ${{ matrix.phpVersions }}
|
||||
extensions: mbstring, intl, gd, xml, sqlite
|
||||
- name: Setup problem matchers for PHPUnit
|
||||
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
|
||||
- name: Set Composer cache
|
||||
id: composer-cache
|
||||
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
- name: Cache Composer dependencies
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
|
||||
restore-keys: ${{ runner.os }}-composer-
|
||||
extension-csv: mbstring, intl, gd, xml, sqlite
|
||||
- name: Install Composer dependencies
|
||||
run: composer install --no-interaction --no-progress --no-suggest --no-scripts
|
||||
- name: Run post-update Composer scripts
|
||||
run: php artisan package:discover
|
||||
- name: Reset October modules
|
||||
- name: Reset October modules and library
|
||||
run: |
|
||||
git reset --hard HEAD
|
||||
composer dumpautoload
|
||||
rm -rf ./vendor/october/rain
|
||||
wget https://github.com/octobercms/library/archive/develop.zip -O ./vendor/october/develop.zip
|
||||
unzip ./vendor/october/develop.zip -d ./vendor/october
|
||||
mv ./vendor/october/library-develop ./vendor/october/rain
|
||||
composer dump-autoload
|
||||
- name: Run post-update Composer scripts
|
||||
run: |
|
||||
php artisan october:util set build
|
||||
php artisan package:discover
|
||||
- name: Run Linting and Tests
|
||||
run: |
|
||||
./vendor/bin/parallel-lint --exclude vendor --exclude storage --exclude tests/fixtures/plugins/testvendor/goto/Plugin.php .
|
||||
./vendor/bin/phpunit --prepend ./vendor/october/rain/src/Support/helpers.php
|
||||
./vendor/bin/phpunit
|
||||
|
|
|
|||
|
|
@ -1,32 +1,24 @@
|
|||
# Composer ignores
|
||||
/bootstrap/compiled.php
|
||||
/vendor
|
||||
composer.phar
|
||||
composer.lock
|
||||
|
||||
# Framework ignores
|
||||
.DS_Store
|
||||
.idea
|
||||
.env
|
||||
.env.*.php
|
||||
.env.php
|
||||
selenium.php
|
||||
/bootstrap/compiled.php
|
||||
.phpunit.result.cache
|
||||
|
||||
# Hosting ignores
|
||||
php_errors.log
|
||||
nginx-error.log
|
||||
nginx-access.log
|
||||
nginx-ssl.access.log
|
||||
nginx-ssl.error.log
|
||||
php-errors.log
|
||||
sftp-config.json
|
||||
.ftpconfig
|
||||
|
||||
# Editor ignores
|
||||
nbproject
|
||||
.idea
|
||||
.vscode
|
||||
_ide_helper.php
|
||||
|
||||
# Other ignores
|
||||
.DS_Store
|
||||
selenium.php
|
||||
composer.lock
|
||||
package-lock.json
|
||||
/node_modules
|
||||
_ide_helper.php
|
||||
|
||||
# for netbeans
|
||||
nbproject
|
||||
|
|
|
|||
4
artisan
4
artisan
|
|
@ -28,7 +28,7 @@ $app = require_once __DIR__.'/bootstrap/app.php';
|
|||
|
|
||||
*/
|
||||
|
||||
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
|
||||
$kernel = $app->make('Illuminate\Contracts\Console\Kernel');
|
||||
|
||||
$status = $kernel->handle(
|
||||
$input = new Symfony\Component\Console\Input\ArgvInput,
|
||||
|
|
@ -48,4 +48,4 @@ $status = $kernel->handle(
|
|||
|
||||
$kernel->terminate($input, $status);
|
||||
|
||||
exit($status);
|
||||
exit($status);
|
||||
|
|
@ -35,3 +35,20 @@ require $helperPath;
|
|||
*/
|
||||
|
||||
require __DIR__.'/../vendor/autoload.php';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Include The Compiled Class File
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| To dramatically increase your application's performance, you may use a
|
||||
| compiled class file which contains all of the classes commonly used
|
||||
| by a request. The Artisan "optimize" is used to create this file.
|
||||
|
|
||||
*/
|
||||
|
||||
$compiledPath = __DIR__.'/../storage/framework/compiled.php';
|
||||
|
||||
if (file_exists($compiledPath)) {
|
||||
require $compiledPath;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "october/october",
|
||||
"description": "October CMS",
|
||||
"description": "OctoberCMS",
|
||||
"homepage": "https://octobercms.com",
|
||||
"type": "project",
|
||||
"keywords": ["october", "cms", "octobercms", "laravel"],
|
||||
|
|
@ -24,34 +24,37 @@
|
|||
}
|
||||
],
|
||||
"support": {
|
||||
"paid": "https://octobercms.com/premium-support",
|
||||
"issues": "https://github.com/octobercms/october/issues",
|
||||
"forum": "https://octobercms.com/forum/",
|
||||
"docs": "https://octobercms.com/docs/",
|
||||
"irc": "irc://irc.freenode.net/october",
|
||||
"source": "https://github.com/octobercms/october"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"october/rain": "dev-develop as 1.0",
|
||||
"october/system": "dev-develop",
|
||||
"october/backend": "dev-develop",
|
||||
"october/cms": "dev-develop",
|
||||
"laravel/framework": "~6.0",
|
||||
"php": ">=7.0.8",
|
||||
"ext-mbstring": "*",
|
||||
"ext-openssl": "*",
|
||||
"october/rain": "~1.0",
|
||||
"october/system": "~1.0",
|
||||
"october/backend": "~1.0",
|
||||
"october/cms": "~1.0",
|
||||
"laravel/framework": "~5.5.40",
|
||||
"wikimedia/composer-merge-plugin": "1.4.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^8.0|^9.0",
|
||||
"fzaninotto/faker": "~1.9",
|
||||
"fzaninotto/faker": "~1.7",
|
||||
"phpunit/phpunit": "~6.5",
|
||||
"phpunit/phpunit-selenium": "~1.2",
|
||||
"meyfa/phpunit-assert-gd": "1.1.0",
|
||||
"squizlabs/php_codesniffer": "3.*",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.0",
|
||||
"meyfa/phpunit-assert-gd": "^2.0.0",
|
||||
"dms/phpunit-arraysubset-asserts": "^0.1.0"
|
||||
"php-parallel-lint/php-parallel-lint": "^1.0"
|
||||
},
|
||||
"autoload-dev": {
|
||||
"classmap": [
|
||||
"tests/concerns/InteractsWithAuthentication.php",
|
||||
"tests/fixtures/backend/models/UserFixture.php",
|
||||
"tests/TestCase.php",
|
||||
"tests/UiTestCase.php",
|
||||
"tests/PluginTestCase.php"
|
||||
]
|
||||
},
|
||||
|
|
@ -63,21 +66,12 @@
|
|||
"post-update-cmd": [
|
||||
"php artisan october:util set build",
|
||||
"php artisan package:discover"
|
||||
],
|
||||
"test": [
|
||||
"phpunit --stop-on-failure"
|
||||
],
|
||||
"lint": [
|
||||
"parallel-lint --exclude vendor --exclude storage --exclude tests/fixtures/plugins/testvendor/goto/Plugin.php ."
|
||||
],
|
||||
"sniff": [
|
||||
"phpcs --colors -nq --report=\"full\" --extensions=\"php\""
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"preferred-install": "dist",
|
||||
"platform": {
|
||||
"php": "7.2"
|
||||
"php": "7.0.8"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
|
|
|
|||
|
|
@ -111,6 +111,21 @@ return [
|
|||
|
||||
'cipher' => 'AES-256-CBC',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Logging Configuration
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure the log settings for your application. Out of
|
||||
| the box, Laravel uses the Monolog PHP logging library. This gives
|
||||
| you a variety of powerful log handlers / formatters to utilize.
|
||||
|
|
||||
| Available Settings: "single", "daily", "syslog", "errorlog"
|
||||
|
|
||||
*/
|
||||
|
||||
'log' => 'single',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Autoloaded Service Providers
|
||||
|
|
@ -129,26 +144,6 @@ return [
|
|||
'System\ServiceProvider',
|
||||
]),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Load automatically discovered packages
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| By default, October CMS disables the loading of discovered packages
|
||||
| through Laravel's package discovery service, in order to allow packages
|
||||
| used by plugins to be disabled if the plugin itself is disabled.
|
||||
|
|
||||
| Set this to `true` to enable automatic loading of these packages. This
|
||||
| will result in packages being loaded, even if the plugin using them is
|
||||
| disabled. This is NOT RECOMMENDED.
|
||||
|
|
||||
| Please note that packages defined in `app.providers` will still be loaded
|
||||
| even if discovery is disabled.
|
||||
|
|
||||
*/
|
||||
|
||||
'loadDiscoveredPackages' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Class Aliases
|
||||
|
|
|
|||
|
|
@ -116,7 +116,6 @@ return [
|
|||
|
||||
'redis' => [
|
||||
|
||||
'client' => 'predis',
|
||||
'cluster' => false,
|
||||
|
||||
'default' => [
|
||||
|
|
|
|||
|
|
@ -20,27 +20,5 @@ return [
|
|||
*/
|
||||
|
||||
'decompileBackendAssets' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Allow deep-level symlinks
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| October CMS, by default, will allow symlinks within the first level of
|
||||
| subdirectories. When this feature is enabled, the system will allow
|
||||
| symlinks to be used at any directory level. This can be useful for
|
||||
| symlinking individual plugins or themes.
|
||||
|
|
||||
| Please note that this has a negative effect on performance. This feature
|
||||
| abides by "cms.restrictBaseDir" - if enabled, symlinks cannot point to
|
||||
| resources outside of the root folder.
|
||||
|
|
||||
| true - allow symlinks at any level
|
||||
|
|
||||
| false - only allow symlinks at the first level of subdirectories (default)
|
||||
|
|
||||
*/
|
||||
|
||||
'allowDeepSymlinks' => false,
|
||||
|
||||
];
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ return [
|
|||
| by the framework. A "local" driver, as well as a variety of cloud
|
||||
| based drivers are available for your choosing. Just store away!
|
||||
|
|
||||
| Supported: "local", "ftp", "sftp", "s3", "rackspace"
|
||||
| Supported: "local", "s3", "rackspace"
|
||||
|
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -1,52 +0,0 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Hash Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default hash driver that will be used to hash
|
||||
| passwords for your application. By default, the bcrypt algorithm is
|
||||
| used; however, you remain free to modify this option if you wish.
|
||||
|
|
||||
| Supported: "bcrypt", "argon", "argon2id"
|
||||
|
|
||||
*/
|
||||
|
||||
'driver' => 'bcrypt',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Bcrypt Options
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the configuration options that should be used when
|
||||
| passwords are hashed using the Bcrypt algorithm. This will allow you
|
||||
| to control the amount of time it takes to hash the given password.
|
||||
|
|
||||
*/
|
||||
|
||||
'bcrypt' => [
|
||||
'rounds' => env('BCRYPT_ROUNDS', 10),
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Argon Options
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the configuration options that should be used when
|
||||
| passwords are hashed using the Argon algorithm. These will allow you
|
||||
| to control the amount of time it takes to hash the given password.
|
||||
|
|
||||
*/
|
||||
|
||||
'argon' => [
|
||||
'memory' => 1024,
|
||||
'threads' => 2,
|
||||
'time' => 2,
|
||||
],
|
||||
|
||||
];
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Log Channel
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option defines the default log channel that gets used when writing
|
||||
| messages to the logs. The name specified in this option should match
|
||||
| one of the channels defined in the "channels" configuration array.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('LOG_CHANNEL', 'single'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Log Channels
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure the log channels for your application. Out of
|
||||
| the box, Laravel uses the Monolog PHP logging library. This gives
|
||||
| you a variety of powerful log handlers / formatters to utilize.
|
||||
|
|
||||
| Available Drivers: "single", "daily", "slack", "syslog",
|
||||
| "errorlog", "monolog",
|
||||
| "custom", "stack"
|
||||
|
|
||||
*/
|
||||
|
||||
'channels' => [
|
||||
'stack' => [
|
||||
'driver' => 'stack',
|
||||
'channels' => ['daily'],
|
||||
'ignore_exceptions' => false,
|
||||
],
|
||||
|
||||
'single' => [
|
||||
'driver' => 'single',
|
||||
'path' => storage_path('logs/system.log'),
|
||||
'level' => 'debug',
|
||||
],
|
||||
|
||||
'daily' => [
|
||||
'driver' => 'daily',
|
||||
'path' => storage_path('logs/system.log'),
|
||||
'level' => 'debug',
|
||||
'days' => 14,
|
||||
],
|
||||
|
||||
'slack' => [
|
||||
'driver' => 'slack',
|
||||
'url' => env('LOG_SLACK_WEBHOOK_URL'),
|
||||
'username' => 'October CMS Log',
|
||||
'emoji' => ':boom:',
|
||||
'level' => 'critical',
|
||||
],
|
||||
|
||||
'papertrail' => [
|
||||
'driver' => 'monolog',
|
||||
'level' => 'debug',
|
||||
'handler' => \Monolog\Handler\SyslogUdpHandler::class,
|
||||
'handler_with' => [
|
||||
'host' => env('PAPERTRAIL_URL'),
|
||||
'port' => env('PAPERTRAIL_PORT'),
|
||||
],
|
||||
],
|
||||
|
||||
'stderr' => [
|
||||
'driver' => 'monolog',
|
||||
'handler' => \Monolog\Handler\StreamHandler::class,
|
||||
'formatter' => env('LOG_STDERR_FORMATTER'),
|
||||
'with' => [
|
||||
'stream' => 'php://stderr',
|
||||
],
|
||||
],
|
||||
|
||||
'syslog' => [
|
||||
'driver' => 'syslog',
|
||||
'level' => 'debug',
|
||||
],
|
||||
|
||||
'errorlog' => [
|
||||
'driver' => 'errorlog',
|
||||
'level' => 'debug',
|
||||
],
|
||||
],
|
||||
|
||||
];
|
||||
|
|
@ -12,7 +12,7 @@ return [
|
|||
| your application here. By default, Laravel is setup for SMTP mail.
|
||||
|
|
||||
| Supported: "smtp", "sendmail", "mailgun", "mandrill", "ses",
|
||||
| "postmark", "sparkpost", "log", "array"
|
||||
| "sparkpost", "log", "array"
|
||||
|
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -24,10 +24,6 @@ return [
|
|||
'secret' => '',
|
||||
],
|
||||
|
||||
'postmark' => [
|
||||
'token' => '',
|
||||
],
|
||||
|
||||
'ses' => [
|
||||
'key' => '',
|
||||
'secret' => '',
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ $app = require_once __DIR__.'/bootstrap/app.php';
|
|||
|
|
||||
*/
|
||||
|
||||
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
|
||||
$kernel = $app->make('Illuminate\Contracts\Http\Kernel');
|
||||
|
||||
$response = $kernel->handle(
|
||||
$request = Illuminate\Http\Request::capture()
|
||||
|
|
|
|||
|
|
@ -80,7 +80,6 @@ class ServiceProvider extends ModuleServiceProvider
|
|||
$combiner->registerBundle('~/modules/backend/formwidgets/colorpicker/assets/less/colorpicker.less');
|
||||
$combiner->registerBundle('~/modules/backend/formwidgets/permissioneditor/assets/less/permissioneditor.less');
|
||||
$combiner->registerBundle('~/modules/backend/formwidgets/markdowneditor/assets/less/markdowneditor.less');
|
||||
$combiner->registerBundle('~/modules/backend/formwidgets/sensitive/assets/less/sensitive.less');
|
||||
|
||||
/*
|
||||
* Rich Editor is protected by DRM
|
||||
|
|
@ -200,7 +199,6 @@ class ServiceProvider extends ModuleServiceProvider
|
|||
$manager->registerFormWidget('Backend\FormWidgets\TagList', 'taglist');
|
||||
$manager->registerFormWidget('Backend\FormWidgets\MediaFinder', 'mediafinder');
|
||||
$manager->registerFormWidget('Backend\FormWidgets\NestedForm', 'nestedform');
|
||||
$manager->registerFormWidget('Backend\FormWidgets\Sensitive', 'sensitive');
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use Backend\Behaviors\ImportExportController\TranscodeFilter;
|
|||
use Illuminate\Database\Eloquent\MassAssignmentException;
|
||||
use League\Csv\Reader as CsvReader;
|
||||
use League\Csv\Writer as CsvWriter;
|
||||
use League\Csv\EscapeFormula as CsvEscapeFormula;
|
||||
use October\Rain\Parse\League\EscapeFormula as CsvEscapeFormula;
|
||||
use ApplicationException;
|
||||
use SplTempFileObject;
|
||||
use Exception;
|
||||
|
|
@ -624,7 +624,9 @@ class ImportExportController extends ControllerBehavior
|
|||
$csv->setDelimiter($options['delimiter']);
|
||||
$csv->setEnclosure($options['enclosure']);
|
||||
$csv->setEscape($options['escape']);
|
||||
$csv->addFormatter(new CsvEscapeFormula());
|
||||
|
||||
// Temporary until upgrading to league/csv >= 9.1.0 (will be $csv->addFormatter($formatter))
|
||||
$formatter = new CsvEscapeFormula();
|
||||
|
||||
/*
|
||||
* Add headers
|
||||
|
|
@ -660,6 +662,9 @@ class ImportExportController extends ControllerBehavior
|
|||
$record[] = $value;
|
||||
}
|
||||
|
||||
// Temporary until upgrading to league/csv >= 9.1.0
|
||||
$record = $formatter($record);
|
||||
|
||||
$csv->insertOne($record);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ class FormField
|
|||
/**
|
||||
* @var string Specifies a comment to accompany the field
|
||||
*/
|
||||
public $comment = '';
|
||||
public $comment;
|
||||
|
||||
/**
|
||||
* @var string Specifies the comment position.
|
||||
|
|
@ -139,7 +139,7 @@ class FormField
|
|||
/**
|
||||
* @var string Specifies a message to display when there is no value supplied (placeholder).
|
||||
*/
|
||||
public $placeholder = '';
|
||||
public $placeholder;
|
||||
|
||||
/**
|
||||
* @var array Contains a list of attributes specified in the field configuration.
|
||||
|
|
|
|||
|
|
@ -8,13 +8,11 @@
|
|||
"authors": [
|
||||
{
|
||||
"name": "Alexey Bobkov",
|
||||
"email": "aleksey.bobkov@gmail.com",
|
||||
"role": "Co-founder"
|
||||
"email": "aleksey.bobkov@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Samuel Georges",
|
||||
"email": "daftspunky@gmail.com",
|
||||
"role": "Co-founder"
|
||||
"email": "daftspunky@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Luke Towers",
|
||||
|
|
@ -24,10 +22,9 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"php": ">=7.0",
|
||||
"composer/installers": "~1.0",
|
||||
"october/rain": "~1.0",
|
||||
"laravel/framework": "~6.0"
|
||||
"october/rain": "~1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ class DatabaseSeeder extends Seeder
|
|||
*/
|
||||
public function run()
|
||||
{
|
||||
Eloquent::unguarded(function () {
|
||||
$this->call('Backend\Database\Seeds\SeedSetupAdmin');
|
||||
});
|
||||
Eloquent::unguard();
|
||||
|
||||
$this->call('Backend\Database\Seeds\SeedSetupAdmin');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,117 +0,0 @@
|
|||
<?php namespace Backend\FormWidgets;
|
||||
|
||||
use Backend\Classes\FormWidgetBase;
|
||||
|
||||
/**
|
||||
* Sensitive widget.
|
||||
*
|
||||
* Renders a password field that can be optionally made visible
|
||||
*
|
||||
* @package october\backend
|
||||
*/
|
||||
class Sensitive extends FormWidgetBase
|
||||
{
|
||||
/**
|
||||
* @var bool If true, the sensitive field cannot be edited, but can be toggled.
|
||||
*/
|
||||
public $readOnly = false;
|
||||
|
||||
/**
|
||||
* @var bool If true, the sensitive field is disabled.
|
||||
*/
|
||||
public $disabled = false;
|
||||
|
||||
/**
|
||||
* @var bool If true, a button will be available to copy the value.
|
||||
*/
|
||||
public $allowCopy = false;
|
||||
|
||||
/**
|
||||
* @var string The string that will be used as a placeholder for an unrevealed sensitive value.
|
||||
*/
|
||||
public $hiddenPlaceholder = '__hidden__';
|
||||
|
||||
/**
|
||||
* @var bool If true, the sensitive input will be hidden if the user changes to another tab in their browser.
|
||||
*/
|
||||
public $hideOnTabChange = true;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected $defaultAlias = 'sensitive';
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$this->fillFromConfig([
|
||||
'readOnly',
|
||||
'disabled',
|
||||
'allowCopy',
|
||||
'hiddenPlaceholder',
|
||||
'hideOnTabChange',
|
||||
]);
|
||||
|
||||
if ($this->formField->disabled || $this->formField->readOnly) {
|
||||
$this->previewMode = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
$this->prepareVars();
|
||||
|
||||
return $this->makePartial('sensitive');
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the view data for the widget partial.
|
||||
*/
|
||||
public function prepareVars()
|
||||
{
|
||||
$this->vars['readOnly'] = $this->readOnly;
|
||||
$this->vars['disabled'] = $this->disabled;
|
||||
$this->vars['hasValue'] = !empty($this->getLoadValue());
|
||||
$this->vars['allowCopy'] = $this->allowCopy;
|
||||
$this->vars['hiddenPlaceholder'] = $this->hiddenPlaceholder;
|
||||
$this->vars['hideOnTabChange'] = $this->hideOnTabChange;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reveals the value of a hidden, unmodified sensitive field.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function onShowValue()
|
||||
{
|
||||
return [
|
||||
'value' => $this->getLoadValue()
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getSaveValue($value)
|
||||
{
|
||||
if ($value === $this->hiddenPlaceholder) {
|
||||
$value = $this->getLoadValue();
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function loadAssets()
|
||||
{
|
||||
$this->addCss('css/sensitive.css', 'core');
|
||||
$this->addJs('js/sensitive.js', 'core');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
div[data-control="sensitive"] a[data-toggle],
|
||||
div[data-control="sensitive"] a[data-copy] {box-shadow:none;border:1px solid #d1d6d9;border-left:0}
|
||||
|
|
@ -1,192 +0,0 @@
|
|||
/*
|
||||
* Sensitive field widget plugin.
|
||||
*
|
||||
* Data attributes:
|
||||
* - data-control="sensitive" - enables the plugin on an element
|
||||
*
|
||||
* JavaScript API:
|
||||
* $('div#someElement').sensitive({...})
|
||||
*/
|
||||
+function ($) { "use strict";
|
||||
var Base = $.oc.foundation.base,
|
||||
BaseProto = Base.prototype
|
||||
|
||||
var Sensitive = function(element, options) {
|
||||
this.$el = $(element)
|
||||
this.options = options
|
||||
this.clean = Boolean(this.$el.data('clean'))
|
||||
this.hidden = true
|
||||
|
||||
this.$input = this.$el.find('[data-input]').first()
|
||||
this.$toggle = this.$el.find('[data-toggle]').first()
|
||||
this.$icon = this.$el.find('[data-icon]').first()
|
||||
this.$loader = this.$el.find('[data-loader]').first()
|
||||
this.$copy = this.$el.find('[data-copy]').first()
|
||||
|
||||
$.oc.foundation.controlUtils.markDisposable(element)
|
||||
Base.call(this)
|
||||
this.init()
|
||||
}
|
||||
|
||||
Sensitive.DEFAULTS = {
|
||||
readOnly: false,
|
||||
disabled: false,
|
||||
eventHandler: null,
|
||||
hideOnTabChange: false,
|
||||
}
|
||||
|
||||
Sensitive.prototype = Object.create(BaseProto)
|
||||
Sensitive.prototype.constructor = Sensitive
|
||||
|
||||
Sensitive.prototype.init = function() {
|
||||
this.$input.on('keydown', this.proxy(this.onInput))
|
||||
this.$toggle.on('click', this.proxy(this.onToggle))
|
||||
|
||||
if (this.options.hideOnTabChange) {
|
||||
// Watch for tab change or minimise
|
||||
document.addEventListener('visibilitychange', this.proxy(this.onTabChange))
|
||||
}
|
||||
|
||||
if (this.$copy.length) {
|
||||
this.$copy.on('click', this.proxy(this.onCopy))
|
||||
}
|
||||
}
|
||||
|
||||
Sensitive.prototype.dispose = function () {
|
||||
this.$input.off('keydown', this.proxy(this.onInput))
|
||||
this.$toggle.off('click', this.proxy(this.onToggle))
|
||||
|
||||
if (this.options.hideOnTabChange) {
|
||||
document.removeEventListener('visibilitychange', this.proxy(this.onTabChange))
|
||||
}
|
||||
|
||||
if (this.$copy.length) {
|
||||
this.$copy.off('click', this.proxy(this.onCopy))
|
||||
}
|
||||
|
||||
this.$input = this.$toggle = this.$icon = this.$loader = null
|
||||
this.$el = null
|
||||
|
||||
BaseProto.dispose.call(this)
|
||||
}
|
||||
|
||||
Sensitive.prototype.onInput = function() {
|
||||
if (this.clean) {
|
||||
this.clean = false
|
||||
this.$input.val('')
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
Sensitive.prototype.onToggle = function() {
|
||||
if (this.$input.val() !== '' && this.clean) {
|
||||
this.reveal()
|
||||
} else {
|
||||
this.toggleVisibility()
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
Sensitive.prototype.onTabChange = function() {
|
||||
if (document.hidden && !this.hidden) {
|
||||
this.toggleVisibility()
|
||||
}
|
||||
}
|
||||
|
||||
Sensitive.prototype.onCopy = function() {
|
||||
var that = this,
|
||||
deferred = $.Deferred(),
|
||||
isHidden = this.hidden
|
||||
|
||||
deferred.then(function () {
|
||||
if (that.hidden) {
|
||||
that.toggleVisibility()
|
||||
}
|
||||
|
||||
that.$input.focus()
|
||||
that.$input.select()
|
||||
|
||||
try {
|
||||
document.execCommand('copy')
|
||||
} catch (err) {
|
||||
}
|
||||
|
||||
that.$input.blur()
|
||||
if (isHidden) {
|
||||
that.toggleVisibility()
|
||||
}
|
||||
})
|
||||
|
||||
if (this.$input.val() !== '' && this.clean) {
|
||||
this.reveal(deferred)
|
||||
} else {
|
||||
deferred.resolve()
|
||||
}
|
||||
}
|
||||
|
||||
Sensitive.prototype.toggleVisibility = function() {
|
||||
if (this.hidden) {
|
||||
this.$input.attr('type', 'text')
|
||||
} else {
|
||||
this.$input.attr('type', 'password')
|
||||
}
|
||||
|
||||
this.$icon.toggleClass('icon-eye icon-eye-slash')
|
||||
|
||||
this.hidden = !this.hidden
|
||||
}
|
||||
|
||||
Sensitive.prototype.reveal = function(deferred) {
|
||||
var that = this
|
||||
this.$icon.css({
|
||||
visibility: 'hidden'
|
||||
})
|
||||
this.$loader.removeClass('hide')
|
||||
|
||||
this.$input.request(this.options.eventHandler, {
|
||||
success: function (data) {
|
||||
that.$input.val(data.value)
|
||||
that.clean = false
|
||||
|
||||
that.$icon.css({
|
||||
visibility: 'visible'
|
||||
})
|
||||
that.$loader.addClass('hide')
|
||||
|
||||
that.toggleVisibility()
|
||||
|
||||
if (deferred) {
|
||||
deferred.resolve()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.sensitive
|
||||
|
||||
$.fn.sensitive = function (option) {
|
||||
var args = Array.prototype.slice.call(arguments, 1), result
|
||||
this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('oc.sensitive')
|
||||
var options = $.extend({}, Sensitive.DEFAULTS, $this.data(), typeof option == 'object' && option)
|
||||
if (!data) $this.data('oc.sensitive', (data = new Sensitive(this, options)))
|
||||
if (typeof option == 'string') result = data[option].apply(data, args)
|
||||
if (typeof result != 'undefined') return false
|
||||
})
|
||||
|
||||
return result ? result : this
|
||||
}
|
||||
|
||||
$.fn.sensitive.noConflict = function () {
|
||||
$.fn.sensitive = old
|
||||
return this
|
||||
}
|
||||
|
||||
$(document).render(function () {
|
||||
$('[data-control="sensitive"]').sensitive()
|
||||
});
|
||||
|
||||
}(window.jQuery);
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
@import "../../../../assets/less/core/boot.less";
|
||||
|
||||
div[data-control="sensitive"] {
|
||||
a[data-toggle],
|
||||
a[data-copy] {
|
||||
box-shadow: none;
|
||||
border: 1px solid @input-group-addon-border-color;
|
||||
border-left: 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
<div
|
||||
data-control="sensitive"
|
||||
data-clean="true"
|
||||
data-event-handler="<?= $this->getEventHandler('onShowValue') ?>"
|
||||
<?php if ($hideOnTabChange): ?>data-hide-on-tab-change="true"<?php endif ?>
|
||||
>
|
||||
<div class="loading-indicator-container size-form-field">
|
||||
<div class="input-group">
|
||||
<input
|
||||
type="password"
|
||||
name="<?= $this->getFieldName() ?>"
|
||||
id="<?= $this->getId() ?>"
|
||||
value="<?= ($hasValue) ? $hiddenPlaceholder : '' ?>"
|
||||
placeholder="<?= e(trans($this->formField->placeholder)) ?>"
|
||||
class="form-control"
|
||||
<?php if ($this->previewMode): ?>disabled="disabled"<?php endif ?>
|
||||
autocomplete="off"
|
||||
data-input
|
||||
/>
|
||||
<?php if ($allowCopy): ?>
|
||||
<a
|
||||
href="javascript:;"
|
||||
class="input-group-addon btn btn-secondary"
|
||||
data-copy
|
||||
>
|
||||
<i class="icon-copy"></i>
|
||||
</a>
|
||||
<?php endif ?>
|
||||
<a
|
||||
href="javascript:;"
|
||||
class="input-group-addon btn btn-secondary"
|
||||
data-toggle
|
||||
>
|
||||
<i class="icon-eye" data-icon></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="loading-indicator hide" data-loader>
|
||||
<span class="p-a"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -5,7 +5,7 @@ use Lang;
|
|||
use Model;
|
||||
use Response;
|
||||
use League\Csv\Writer as CsvWriter;
|
||||
use League\Csv\EscapeFormula as CsvEscapeFormula;
|
||||
use October\Rain\Parse\League\EscapeFormula as CsvEscapeFormula;
|
||||
use ApplicationException;
|
||||
use SplTempFileObject;
|
||||
|
||||
|
|
@ -112,7 +112,8 @@ abstract class ExportModel extends Model
|
|||
$csv->setEscape($options['escape']);
|
||||
}
|
||||
|
||||
$csv->addFormatter(new CsvEscapeFormula());
|
||||
// Temporary until upgrading to league/csv >= 9.1.0 (will be $csv->addFormatter($formatter))
|
||||
$formatter = new CsvEscapeFormula();
|
||||
|
||||
/*
|
||||
* Add headers
|
||||
|
|
@ -127,6 +128,10 @@ abstract class ExportModel extends Model
|
|||
*/
|
||||
foreach ($results as $result) {
|
||||
$data = $this->matchDataToColumns($result, $columns);
|
||||
|
||||
// Temporary until upgrading to league/csv >= 9.1.0
|
||||
$data = $formatter($data);
|
||||
|
||||
$csv->insertOne($data);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ use Str;
|
|||
use Lang;
|
||||
use Model;
|
||||
use League\Csv\Reader as CsvReader;
|
||||
use League\Csv\Statement as CsvStatement;
|
||||
|
||||
/**
|
||||
* Model used for importing data
|
||||
|
|
@ -109,6 +108,11 @@ abstract class ImportModel extends Model
|
|||
*/
|
||||
$reader = CsvReader::createFromPath($filePath, 'r');
|
||||
|
||||
// Filter out empty rows
|
||||
$reader->addFilter(function (array $row) {
|
||||
return count($row) > 1 || reset($row) !== null;
|
||||
});
|
||||
|
||||
if ($options['delimiter'] !== null) {
|
||||
$reader->setDelimiter($options['delimiter']);
|
||||
}
|
||||
|
|
@ -121,11 +125,15 @@ abstract class ImportModel extends Model
|
|||
$reader->setEscape($options['escape']);
|
||||
}
|
||||
|
||||
if ($options['firstRowTitles']) {
|
||||
$reader->setOffset(1);
|
||||
}
|
||||
|
||||
if (
|
||||
$options['encoding'] !== null &&
|
||||
$reader->supportsStreamFilter()
|
||||
$reader->isActiveStreamFilter()
|
||||
) {
|
||||
$reader->addStreamFilter(sprintf(
|
||||
$reader->appendStreamFilter(sprintf(
|
||||
'%s%s:%s',
|
||||
TranscodeFilter::FILTER_NAME,
|
||||
strtolower($options['encoding']),
|
||||
|
|
@ -133,19 +141,8 @@ abstract class ImportModel extends Model
|
|||
));
|
||||
}
|
||||
|
||||
// Create reader statement
|
||||
$stmt = (new CsvStatement)
|
||||
->where(function (array $row) {
|
||||
// Filter out empty rows
|
||||
return count($row) > 1 || reset($row) !== null;
|
||||
});
|
||||
|
||||
if ($options['firstRowTitles']) {
|
||||
$stmt = $stmt->offset(1);
|
||||
}
|
||||
|
||||
$result = [];
|
||||
$contents = $stmt->process($reader);
|
||||
$contents = $reader->fetch();
|
||||
foreach ($contents as $row) {
|
||||
$result[] = $this->processImportRow($row, $matches);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ class User extends UserBase
|
|||
public $rules = [
|
||||
'email' => 'required|between:6,255|email|unique:backend_users',
|
||||
'login' => 'required|between:2,255|unique:backend_users',
|
||||
'password' => 'required:create|min:4|confirmed',
|
||||
'password_confirmation' => 'required_with:password|min:4'
|
||||
'password' => 'required:create|between:4,255|confirmed',
|
||||
'password_confirmation' => 'required_with:password|between:4,255'
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ App::before(function ($request) {
|
|||
'middleware' => ['web'],
|
||||
'prefix' => Config::get('cms.backendUri', 'backend')
|
||||
], function () {
|
||||
Route::any('{slug?}', 'Backend\Classes\BackendController@run')->where('slug', '(.*)?');
|
||||
Route::any('{slug}', 'Backend\Classes\BackendController@run')->where('slug', '(.*)?');
|
||||
})
|
||||
;
|
||||
|
||||
|
|
|
|||
|
|
@ -287,14 +287,25 @@ class Asset extends Extendable
|
|||
|
||||
$directory = $this->theme->getPath() . '/' . $this->dirName . '/';
|
||||
$filePath = $directory . $fileName;
|
||||
$resolvedPath = resolve_path($filePath);
|
||||
$path = realpath($filePath);
|
||||
|
||||
/**
|
||||
* If the path doesn't exist yet, then create it temporarily
|
||||
* in order to run realpath() resolution on it to verify the
|
||||
* final destination and then remove the temporary file.
|
||||
*/
|
||||
if (!$path) {
|
||||
touch($filePath);
|
||||
$path = realpath($filePath);
|
||||
unlink($filePath);
|
||||
}
|
||||
|
||||
// Limit paths to those under the theme's assets directory
|
||||
if (!starts_with($resolvedPath, $directory)) {
|
||||
if (!starts_with($path, $directory)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $resolvedPath;
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -316,8 +316,7 @@ class CmsCompoundObject extends CmsObject
|
|||
|
||||
self::$objectComponentPropertyMap = $objectComponentMap;
|
||||
|
||||
$expiresAt = now()->addMinutes(Config::get('cms.parsedPageCacheTTL', 10));
|
||||
Cache::put($key, base64_encode(serialize($objectComponentMap)), $expiresAt);
|
||||
Cache::put($key, base64_encode(serialize($objectComponentMap)), Config::get('cms.parsedPageCacheTTL', 10));
|
||||
|
||||
if (array_key_exists($componentName, $objectComponentMap[$objectCode])) {
|
||||
return $objectComponentMap[$objectCode][$componentName];
|
||||
|
|
|
|||
|
|
@ -227,16 +227,7 @@ class CmsObject extends HalcyonModel implements CmsObjectContract
|
|||
$fileName = $this->fileName;
|
||||
}
|
||||
|
||||
$directory = $this->theme->getPath() . '/' . $this->getObjectTypeDirName() . '/';
|
||||
$filePath = $directory . $fileName;
|
||||
$resolvedPath = resolve_path($filePath);
|
||||
|
||||
// Limit paths to those under the corresponding theme directory
|
||||
if (!starts_with($resolvedPath, $directory)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $resolvedPath;
|
||||
return $this->theme->getPath().'/'.$this->getObjectTypeDirName().'/'.$fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
<?php namespace Cms\Classes;
|
||||
|
||||
use ApplicationException;
|
||||
use October\Rain\Support\Collection as CollectionBase;
|
||||
|
||||
/**
|
||||
|
|
@ -38,32 +37,15 @@ class CmsObjectCollection extends CollectionBase
|
|||
|
||||
/**
|
||||
* Returns objects whose properties match the supplied value.
|
||||
*
|
||||
* Note that this deviates from Laravel 6's Illuminate\Support\Traits\EnumeratesValues::where() method signature,
|
||||
* which uses ($key, $operator = null, $value = null) as parameters and that this class extends.
|
||||
*
|
||||
* To ensure backwards compatibility with our current Halcyon functionality, this method retains the original
|
||||
* parameters and functions the same way as before, with handling for the $value and $strict parameters to ensure
|
||||
* they match the previously expected formats. This means that you cannot use operators for "where" queries on
|
||||
* CMS object collections.
|
||||
*
|
||||
* @param string $property
|
||||
* @param string $value
|
||||
* @param bool $strict
|
||||
* @param string $property
|
||||
* @param string $value
|
||||
* @param bool $strict
|
||||
* @return static
|
||||
*/
|
||||
public function where($property, $value = null, $strict = null)
|
||||
public function where($property, $value, $strict = true)
|
||||
{
|
||||
if (empty($value) || !is_string($value)) {
|
||||
throw new ApplicationException('You must provide a string value to compare with when executing a "where" '
|
||||
. 'query for CMS object collections.');
|
||||
}
|
||||
|
||||
if (!isset($strict) || !is_bool($strict)) {
|
||||
$strict = true;
|
||||
}
|
||||
|
||||
return $this->filter(function ($object) use ($property, $value, $strict) {
|
||||
|
||||
if (!array_key_exists($property, $object->settings)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -224,8 +224,7 @@ class CodeParser
|
|||
$cached = $this->getCachedInfo() ?: [];
|
||||
$cached[$this->filePath] = $cacheItem;
|
||||
|
||||
$expiresAt = now()->addMinutes(1440);
|
||||
Cache::put($this->dataCacheKey, base64_encode(serialize($cached)), $expiresAt);
|
||||
Cache::put($this->dataCacheKey, base64_encode(serialize($cached)), 1440);
|
||||
|
||||
self::$cache[$this->filePath] = $result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,11 +127,10 @@ class Router
|
|||
: $fileName;
|
||||
|
||||
$key = $this->getUrlListCacheKey();
|
||||
$expiresAt = now()->addMinutes(Config::get('cms.urlCacheTtl', 1));
|
||||
Cache::put(
|
||||
$key,
|
||||
base64_encode(serialize($urlList)),
|
||||
$expiresAt
|
||||
Config::get('cms.urlCacheTtl', 1)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -252,8 +251,7 @@ class Router
|
|||
|
||||
$this->urlMap = $map;
|
||||
if ($cacheable) {
|
||||
$expiresAt = now()->addMinutes(Config::get('cms.urlCacheTtl', 1));
|
||||
Cache::put($key, base64_encode(serialize($map)), $expiresAt);
|
||||
Cache::put($key, base64_encode(serialize($map)), Config::get('cms.urlCacheTtl', 1));
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -158,8 +158,7 @@ class Theme
|
|||
if ($checkDatabase && App::hasDatabase()) {
|
||||
try {
|
||||
try {
|
||||
$expiresAt = now()->addMinutes(1440);
|
||||
$dbResult = Cache::remember(self::ACTIVE_KEY, $expiresAt, function () {
|
||||
$dbResult = Cache::remember(self::ACTIVE_KEY, 1440, function () {
|
||||
return Parameter::applyKey(self::ACTIVE_KEY)->value('value');
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,13 +8,11 @@
|
|||
"authors": [
|
||||
{
|
||||
"name": "Alexey Bobkov",
|
||||
"email": "aleksey.bobkov@gmail.com",
|
||||
"role": "Co-founder"
|
||||
"email": "aleksey.bobkov@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Samuel Georges",
|
||||
"email": "daftspunky@gmail.com",
|
||||
"role": "Co-founder"
|
||||
"email": "daftspunky@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Luke Towers",
|
||||
|
|
@ -24,10 +22,9 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"php": ">=7.0",
|
||||
"composer/installers": "~1.0",
|
||||
"october/rain": "~1.0",
|
||||
"laravel/framework": "~6.0"
|
||||
"october/rain": "~1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ App::before(function ($request) {
|
|||
* The CMS module intercepts all URLs that were not
|
||||
* handled by the back-end modules.
|
||||
*/
|
||||
Route::any('{slug?}', 'Cms\Classes\CmsController@run')->where('slug', '(.*)?')->middleware('web');
|
||||
Route::any('{slug}', 'Cms\Classes\CmsController@run')->where('slug', '(.*)?')->middleware('web');
|
||||
|
||||
/**
|
||||
* @event cms.route
|
||||
|
|
|
|||
|
|
@ -190,8 +190,7 @@ trait UrlMaker
|
|||
'mtime' => @File::lastModified($filePath)
|
||||
];
|
||||
|
||||
$expiresAt = now()->addMinutes(Config::get('cms.parsedPageCacheTTL', 1440));
|
||||
Cache::put($key, serialize($cached), $expiresAt);
|
||||
Cache::put($key, serialize($cached), Config::get('cms.parsedPageCacheTTL', 1440));
|
||||
|
||||
return static::$urlPageName = $baseFileName;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use Cms\Classes\Controller;
|
|||
use Cms\Classes\ComponentBase;
|
||||
use Illuminate\Pagination\Paginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
|
||||
use Illuminate\Support\Debug\HtmlDumper;
|
||||
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||
use October\Rain\Database\Model;
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,6 @@ class ServiceProvider extends ModuleServiceProvider
|
|||
}
|
||||
}
|
||||
|
||||
Paginator::useBootstrapThree();
|
||||
Paginator::defaultSimpleView('system::pagination.simple-default');
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ return [
|
|||
'Eloquent' => Illuminate\Database\Eloquent\Model::class,
|
||||
'Event' => Illuminate\Support\Facades\Event::class,
|
||||
'Hash' => Illuminate\Support\Facades\Hash::class,
|
||||
'Input' => Illuminate\Support\Facades\Input::class,
|
||||
'Lang' => Illuminate\Support\Facades\Lang::class,
|
||||
'Log' => Illuminate\Support\Facades\Log::class,
|
||||
'Mail' => Illuminate\Support\Facades\Mail::class,
|
||||
|
|
@ -29,6 +30,7 @@ return [
|
|||
'Storage' => Illuminate\Support\Facades\Storage::class,
|
||||
'Url' => Illuminate\Support\Facades\URL::class, // Preferred
|
||||
'URL' => Illuminate\Support\Facades\URL::class,
|
||||
'Validator' => Illuminate\Support\Facades\Validator::class,
|
||||
'View' => Illuminate\Support\Facades\View::class,
|
||||
|
||||
/*
|
||||
|
|
@ -40,7 +42,6 @@ return [
|
|||
'Config' => October\Rain\Support\Facades\Config::class,
|
||||
'Seeder' => October\Rain\Database\Updates\Seeder::class,
|
||||
'Flash' => October\Rain\Support\Facades\Flash::class,
|
||||
'Input' => October\Rain\Support\Facades\Input::class,
|
||||
'Form' => October\Rain\Support\Facades\Form::class,
|
||||
'Html' => October\Rain\Support\Facades\Html::class,
|
||||
'Http' => October\Rain\Support\Facades\Http::class,
|
||||
|
|
@ -51,7 +52,6 @@ return [
|
|||
'Twig' => October\Rain\Support\Facades\Twig::class,
|
||||
'DbDongle' => October\Rain\Support\Facades\DbDongle::class,
|
||||
'Schema' => October\Rain\Support\Facades\Schema::class,
|
||||
'Validator' => October\Rain\Support\Facades\Validator::class,
|
||||
'Cms' => Cms\Facades\Cms::class,
|
||||
'Backend' => Backend\Facades\Backend::class,
|
||||
'BackendMenu' => Backend\Facades\BackendMenu::class,
|
||||
|
|
@ -60,12 +60,4 @@ return [
|
|||
'SystemException' => October\Rain\Exception\SystemException::class,
|
||||
'ApplicationException' => October\Rain\Exception\ApplicationException::class,
|
||||
'ValidationException' => October\Rain\Exception\ValidationException::class,
|
||||
|
||||
/*
|
||||
* Fallback aliases
|
||||
*/
|
||||
// Input facade was removed in Laravel 6 - we are keeping it in the Rain library for backwards compatibility.
|
||||
'Illuminate\Support\Facades\Input' => October\Rain\Support\Facades\Input::class,
|
||||
// Illuminate's HtmlDumper was "dumped" in Laravel 6 - we'll route this to Symfony's HtmlDumper as Laravel have done.
|
||||
'Illuminate\Support\Debug\HtmlDumper' => Symfony\Component\VarDumper\Dumper\HtmlDumper::class,
|
||||
];
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ use Route;
|
|||
use Config;
|
||||
use Request;
|
||||
use Response;
|
||||
use October\Rain\Assetic\Asset\FileAsset;
|
||||
use October\Rain\Assetic\Asset\AssetCache;
|
||||
use October\Rain\Assetic\Asset\AssetCollection;
|
||||
use October\Rain\Assetic\Cache\FilesystemCache;
|
||||
use October\Rain\Assetic\Factory\AssetFactory;
|
||||
use Assetic\Asset\FileAsset;
|
||||
use Assetic\Asset\AssetCache;
|
||||
use Assetic\Asset\AssetCollection;
|
||||
use Assetic\Factory\AssetFactory;
|
||||
use October\Rain\Parse\Assetic\FilesystemCache;
|
||||
use System\Helpers\Cache as CacheHelper;
|
||||
use ApplicationException;
|
||||
use DateTime;
|
||||
|
|
@ -126,22 +126,22 @@ class CombineAssets
|
|||
/*
|
||||
* Register JavaScript filters
|
||||
*/
|
||||
$this->registerFilter('js', new \October\Rain\Assetic\Filter\JavascriptImporter);
|
||||
$this->registerFilter('js', new \October\Rain\Parse\Assetic\JavascriptImporter);
|
||||
|
||||
/*
|
||||
* Register CSS filters
|
||||
*/
|
||||
$this->registerFilter('css', new \October\Rain\Assetic\Filter\CssImportFilter);
|
||||
$this->registerFilter(['css', 'less', 'scss'], new \October\Rain\Assetic\Filter\CssRewriteFilter);
|
||||
$this->registerFilter('less', new \October\Rain\Assetic\Filter\LessCompiler);
|
||||
$this->registerFilter('scss', new \October\Rain\Assetic\Filter\ScssCompiler);
|
||||
$this->registerFilter('css', new \Assetic\Filter\CssImportFilter);
|
||||
$this->registerFilter(['css', 'less', 'scss'], new \Assetic\Filter\CssRewriteFilter);
|
||||
$this->registerFilter('less', new \October\Rain\Parse\Assetic\LessCompiler);
|
||||
$this->registerFilter('scss', new \October\Rain\Parse\Assetic\ScssCompiler);
|
||||
|
||||
/*
|
||||
* Minification filters
|
||||
*/
|
||||
if ($this->useMinify) {
|
||||
$this->registerFilter('js', new \October\Rain\Assetic\Filter\JSMinFilter);
|
||||
$this->registerFilter(['css', 'less', 'scss'], new \October\Rain\Assetic\Filter\StylesheetMinify);
|
||||
$this->registerFilter('js', new \Assetic\Filter\JSMinFilter);
|
||||
$this->registerFilter(['css', 'less', 'scss'], new \October\Rain\Parse\Assetic\StylesheetMinify);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -134,11 +134,10 @@ class MediaLibrary
|
|||
$folderContents = $this->scanFolderContents($fullFolderPath);
|
||||
|
||||
$cached[$fullFolderPath] = $folderContents;
|
||||
$expiresAt = now()->addMinutes(Config::get('cms.storage.media.ttl', 10));
|
||||
Cache::put(
|
||||
$this->cacheKey,
|
||||
base64_encode(serialize($cached)),
|
||||
$expiresAt
|
||||
Config::get('cms.storage.media.ttl', 10)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,11 @@ class UpdateManager
|
|||
{
|
||||
use \October\Rain\Support\Traits\Singleton;
|
||||
|
||||
/**
|
||||
* @var array The notes for the current operation.
|
||||
*/
|
||||
protected $notes = [];
|
||||
|
||||
/**
|
||||
* @var \Illuminate\Console\OutputStyle
|
||||
*/
|
||||
|
|
@ -340,13 +345,13 @@ class UpdateManager
|
|||
/*
|
||||
* Rollback modules
|
||||
*/
|
||||
if (isset($this->notesOutput)) {
|
||||
$this->migrator->setOutput($this->notesOutput);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
$rolledBack = $this->migrator->rollback($paths, ['pretend' => false]);
|
||||
|
||||
foreach ($this->migrator->getNotes() as $note) {
|
||||
$this->note($note);
|
||||
}
|
||||
|
||||
if (count($rolledBack) == 0) {
|
||||
break;
|
||||
}
|
||||
|
|
@ -398,13 +403,13 @@ class UpdateManager
|
|||
*/
|
||||
public function migrateModule($module)
|
||||
{
|
||||
if (isset($this->notesOutput)) {
|
||||
$this->migrator->setOutput($this->notesOutput);
|
||||
}
|
||||
$this->migrator->run(base_path() . '/modules/' . strtolower($module) . '/database/migrations');
|
||||
|
||||
$this->note($module);
|
||||
|
||||
$this->migrator->run(base_path() . '/modules/'.strtolower($module).'/database/migrations');
|
||||
foreach ($this->migrator->getNotes() as $note) {
|
||||
$this->note(' - ' . $note);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
@ -513,9 +518,13 @@ class UpdateManager
|
|||
|
||||
$this->note($name);
|
||||
|
||||
$this->versionManager->setNotesOutput($this->notesOutput);
|
||||
$this->versionManager->resetNotes()->setNotesOutput($this->notesOutput);
|
||||
|
||||
$this->versionManager->updatePlugin($plugin);
|
||||
if ($this->versionManager->updatePlugin($plugin) !== false) {
|
||||
foreach ($this->versionManager->getNotes() as $note) {
|
||||
$this->note($note);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
@ -704,8 +713,7 @@ class UpdateManager
|
|||
}
|
||||
|
||||
$data = $this->requestServerData($type . '/popular');
|
||||
$expiresAt = now()->addMinutes(60);
|
||||
Cache::put($cacheKey, base64_encode(serialize($data)), $expiresAt);
|
||||
Cache::put($cacheKey, base64_encode(serialize($data)), 60);
|
||||
|
||||
foreach ($data as $product) {
|
||||
$code = array_get($product, 'code', -1);
|
||||
|
|
@ -794,11 +802,35 @@ class UpdateManager
|
|||
{
|
||||
if ($this->notesOutput !== null) {
|
||||
$this->notesOutput->writeln($message);
|
||||
} else {
|
||||
$this->notes[] = $message;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notes for the last operation.
|
||||
* @return array
|
||||
*/
|
||||
public function getNotes()
|
||||
{
|
||||
return $this->notes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the notes store.
|
||||
* @return self
|
||||
*/
|
||||
public function resetNotes()
|
||||
{
|
||||
$this->notesOutput = null;
|
||||
|
||||
$this->notes = [];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an output stream for writing notes.
|
||||
* @param Illuminate\Console\Command $output
|
||||
|
|
|
|||
|
|
@ -29,6 +29,12 @@ class VersionManager
|
|||
const HISTORY_TYPE_COMMENT = 'comment';
|
||||
const HISTORY_TYPE_SCRIPT = 'script';
|
||||
|
||||
/**
|
||||
* The notes for the current operation.
|
||||
* @var array
|
||||
*/
|
||||
protected $notes = [];
|
||||
|
||||
/**
|
||||
* @var \Illuminate\Console\OutputStyle
|
||||
*/
|
||||
|
|
@ -420,7 +426,6 @@ class VersionManager
|
|||
* Execute the database PHP script
|
||||
*/
|
||||
$updateFile = $this->pluginManager->getPluginPath($code) . '/updates/' . $script;
|
||||
|
||||
$this->updater->packDown($updateFile);
|
||||
|
||||
Db::table('system_plugin_history')
|
||||
|
|
@ -503,11 +508,35 @@ class VersionManager
|
|||
{
|
||||
if ($this->notesOutput !== null) {
|
||||
$this->notesOutput->writeln($message);
|
||||
} else {
|
||||
$this->notes[] = $message;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notes for the last operation.
|
||||
* @return array
|
||||
*/
|
||||
public function getNotes()
|
||||
{
|
||||
return $this->notes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the notes store.
|
||||
* @return self
|
||||
*/
|
||||
public function resetNotes()
|
||||
{
|
||||
$this->notesOutput = null;
|
||||
|
||||
$this->notes = [];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an output stream for writing notes.
|
||||
* @param Illuminate\Console\Command $output
|
||||
|
|
@ -521,7 +550,8 @@ class VersionManager
|
|||
}
|
||||
|
||||
/**
|
||||
* Extract script and comments from version details
|
||||
* @param $details
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function extractScriptsAndComments($details): array
|
||||
|
|
@ -536,8 +566,7 @@ class VersionManager
|
|||
$scripts = array_values(array_filter($details, function ($detail) use ($fileNamePattern) {
|
||||
return preg_match($fileNamePattern, $detail);
|
||||
}));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$comments = (array)$details;
|
||||
$scripts = [];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,13 +8,11 @@
|
|||
"authors": [
|
||||
{
|
||||
"name": "Alexey Bobkov",
|
||||
"email": "aleksey.bobkov@gmail.com",
|
||||
"role": "Co-founder"
|
||||
"email": "aleksey.bobkov@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Samuel Georges",
|
||||
"email": "daftspunky@gmail.com",
|
||||
"role": "Co-founder"
|
||||
"email": "daftspunky@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Luke Towers",
|
||||
|
|
@ -24,10 +22,9 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"php": ">=7.0",
|
||||
"composer/installers": "~1.0",
|
||||
"october/rain": "~1.0",
|
||||
"laravel/framework": "~6.0"
|
||||
"october/rain": "~1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
|
|||
|
|
@ -369,7 +369,7 @@ class OctoberEnv extends Command
|
|||
'SESSION_DRIVER' => 'driver',
|
||||
],
|
||||
'queue' => [
|
||||
'QUEUE_CONNECTION' => 'default',
|
||||
'QUEUE_DRIVER' => 'default',
|
||||
],
|
||||
'mail' => [
|
||||
'MAIL_DRIVER' => 'driver',
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ use Symfony\Component\Console\Input\InputOption;
|
|||
*/
|
||||
class OctoberUpdate extends Command
|
||||
{
|
||||
|
||||
/**
|
||||
* The console command name.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
use Lang;
|
||||
use Flash;
|
||||
use Config;
|
||||
use Request;
|
||||
use Backend;
|
||||
use BackendMenu;
|
||||
use System\Classes\SettingsManager;
|
||||
|
|
@ -141,22 +139,6 @@ class Settings extends Controller
|
|||
return $this->formWidget->render($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the form widget used by this behavior.
|
||||
*
|
||||
* @return \Backend\Widgets\Form
|
||||
*/
|
||||
public function formGetWidget()
|
||||
{
|
||||
if (is_null($this->formWidget)) {
|
||||
$item = $this->findSettingItem();
|
||||
$model = $this->createModel($item);
|
||||
$this->initWidgets($model);
|
||||
}
|
||||
|
||||
return $this->formWidget;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the widgets used by this action
|
||||
* Model $model
|
||||
|
|
@ -187,22 +169,10 @@ class Settings extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Locates a setting item for a module or plugin.
|
||||
*
|
||||
* If none of the parameters are provided, they will be auto-guessed from the URL.
|
||||
*
|
||||
* @param string|null $author
|
||||
* @param string|null $plugin
|
||||
* @param string|null $code
|
||||
*
|
||||
* @return array
|
||||
* Locates a setting item for a module or plugin
|
||||
*/
|
||||
protected function findSettingItem($author = null, $plugin = null, $code = null)
|
||||
protected function findSettingItem($author, $plugin, $code)
|
||||
{
|
||||
if (is_null($author) || is_null($plugin)) {
|
||||
[$author, $plugin, $code] = $this->guessSettingItem();
|
||||
}
|
||||
|
||||
$manager = SettingsManager::instance();
|
||||
|
||||
$moduleOwner = $author;
|
||||
|
|
@ -217,23 +187,4 @@ class Settings extends Controller
|
|||
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Guesses the requested setting item from the current URL segments provided by the Request object.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function guessSettingItem()
|
||||
{
|
||||
$segments = Request::segments();
|
||||
|
||||
if (!empty(Config::get('cms.backendUri', 'backend'))) {
|
||||
array_splice($segments, 0, 4);
|
||||
} else {
|
||||
array_splice($segments, 0, 3);
|
||||
}
|
||||
|
||||
// Ensure there's at least 3 segments
|
||||
return array_pad($segments, 3, null);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ class DatabaseSeeder extends Seeder
|
|||
*/
|
||||
public function run()
|
||||
{
|
||||
Eloquent::unguarded(function () {
|
||||
$this->call('System\Database\Seeds\SeedSetupMailLayouts');
|
||||
});
|
||||
Eloquent::unguard();
|
||||
|
||||
$this->call('System\Database\Seeds\SeedSetupMailLayouts');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ return [
|
|||
'boolean' => 'The :attribute field must be true or false.',
|
||||
'confirmed' => 'The :attribute confirmation does not match.',
|
||||
'date' => 'The :attribute is not a valid date.',
|
||||
'date_equals' => 'The :attribute must be a date equal to :date.',
|
||||
'date_format' => 'The :attribute does not match the format :format.',
|
||||
'different' => 'The :attribute and :other must be different.',
|
||||
'digits' => 'The :attribute must be :digits digits.',
|
||||
|
|
@ -40,22 +39,9 @@ return [
|
|||
'dimensions' => 'The :attribute has invalid image dimensions.',
|
||||
'distinct' => 'The :attribute field has a duplicate value.',
|
||||
'email' => 'The :attribute must be a valid email address.',
|
||||
'ends_with' => 'The :attribute must end with one of the following: :values.',
|
||||
'exists' => 'The selected :attribute is invalid.',
|
||||
'file' => 'The :attribute must be a file.',
|
||||
'filled' => 'The :attribute field must have a value.',
|
||||
'gt' => [
|
||||
'numeric' => 'The :attribute must be greater than :value.',
|
||||
'file' => 'The :attribute must be greater than :value kilobytes.',
|
||||
'string' => 'The :attribute must be greater than :value characters.',
|
||||
'array' => 'The :attribute must have more than :value items.',
|
||||
],
|
||||
'gte' => [
|
||||
'numeric' => 'The :attribute must be greater than or equal :value.',
|
||||
'file' => 'The :attribute must be greater than or equal :value kilobytes.',
|
||||
'string' => 'The :attribute must be greater than or equal :value characters.',
|
||||
'array' => 'The :attribute must have :value items or more.',
|
||||
],
|
||||
'image' => 'The :attribute must be an image.',
|
||||
'in' => 'The selected :attribute is invalid.',
|
||||
'in_array' => 'The :attribute field does not exist in :other.',
|
||||
|
|
@ -64,18 +50,6 @@ return [
|
|||
'ipv4' => 'The :attribute must be a valid IPv4 address.',
|
||||
'ipv6' => 'The :attribute must be a valid IPv6 address.',
|
||||
'json' => 'The :attribute must be a valid JSON string.',
|
||||
'lt' => [
|
||||
'numeric' => 'The :attribute must be less than :value.',
|
||||
'file' => 'The :attribute must be less than :value kilobytes.',
|
||||
'string' => 'The :attribute must be less than :value characters.',
|
||||
'array' => 'The :attribute must have less than :value items.',
|
||||
],
|
||||
'lte' => [
|
||||
'numeric' => 'The :attribute must be less than or equal :value.',
|
||||
'file' => 'The :attribute must be less than or equal :value kilobytes.',
|
||||
'string' => 'The :attribute must be less than or equal :value characters.',
|
||||
'array' => 'The :attribute must not have more than :value items.',
|
||||
],
|
||||
'max' => [
|
||||
'numeric' => 'The :attribute may not be greater than :max.',
|
||||
'file' => 'The :attribute may not be greater than :max kilobytes.',
|
||||
|
|
@ -91,7 +65,6 @@ return [
|
|||
'array' => 'The :attribute must have at least :min items.',
|
||||
],
|
||||
'not_in' => 'The selected :attribute is invalid.',
|
||||
'not_regex' => 'The :attribute format is invalid.',
|
||||
'numeric' => 'The :attribute must be a number.',
|
||||
'present' => 'The :attribute field must be present.',
|
||||
'regex' => 'The :attribute format is invalid.',
|
||||
|
|
@ -109,13 +82,11 @@ return [
|
|||
'string' => 'The :attribute must be :size characters.',
|
||||
'array' => 'The :attribute must contain :size items.',
|
||||
],
|
||||
'starts_with' => 'The :attribute must start with one of the following: :values.',
|
||||
'string' => 'The :attribute must be a string.',
|
||||
'timezone' => 'The :attribute must be a valid zone.',
|
||||
'unique' => 'The :attribute has already been taken.',
|
||||
'uploaded' => 'The :attribute failed to upload.',
|
||||
'url' => 'The :attribute format is invalid.',
|
||||
'uuid' => 'The :attribute must be a valid UUID.',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -79,7 +79,6 @@ tabs:
|
|||
smtp_password:
|
||||
label: system::lang.mail.smtp_password
|
||||
tab: system::lang.mail.general
|
||||
type: sensitive
|
||||
span: right
|
||||
trigger:
|
||||
action: show
|
||||
|
|
@ -108,7 +107,6 @@ tabs:
|
|||
label: system::lang.mail.mailgun_secret
|
||||
commentAbove: system::lang.mail.mailgun_secret_comment
|
||||
tab: system::lang.mail.general
|
||||
type: sensitive
|
||||
trigger:
|
||||
action: show
|
||||
field: send_mode
|
||||
|
|
@ -118,7 +116,6 @@ tabs:
|
|||
label: system::lang.mail.mandrill_secret
|
||||
commentAbove: system::lang.mail.mandrill_secret_comment
|
||||
tab: system::lang.mail.general
|
||||
type: sensitive
|
||||
trigger:
|
||||
action: show
|
||||
field: send_mode
|
||||
|
|
@ -138,7 +135,6 @@ tabs:
|
|||
label: system::lang.mail.ses_secret
|
||||
commentAbove: system::lang.mail.ses_secret_comment
|
||||
tab: system::lang.mail.general
|
||||
type: sensitive
|
||||
span: right
|
||||
trigger:
|
||||
action: show
|
||||
|
|
@ -158,7 +154,6 @@ tabs:
|
|||
sparkpost_secret:
|
||||
label: system::lang.mail.sparkpost_secret
|
||||
commentAbove: system::lang.mail.sparkpost_secret_comment
|
||||
type: sensitive
|
||||
tab: system::lang.mail.general
|
||||
trigger:
|
||||
action: show
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@ return [
|
|||
Illuminate\Pagination\PaginationServiceProvider::class,
|
||||
Illuminate\Pipeline\PipelineServiceProvider::class,
|
||||
Illuminate\Queue\QueueServiceProvider::class,
|
||||
Illuminate\Redis\RedisServiceProvider::class,
|
||||
Illuminate\Session\SessionServiceProvider::class,
|
||||
Illuminate\Validation\ValidationServiceProvider::class,
|
||||
Illuminate\View\ViewServiceProvider::class,
|
||||
Laravel\Tinker\TinkerServiceProvider::class,
|
||||
|
||||
|
|
@ -34,7 +36,5 @@ return [
|
|||
October\Rain\Flash\FlashServiceProvider::class,
|
||||
October\Rain\Mail\MailServiceProvider::class,
|
||||
October\Rain\Argon\ArgonServiceProvider::class,
|
||||
October\Rain\Redis\RedisServiceProvider::class,
|
||||
October\Rain\Validation\ValidationServiceProvider::class,
|
||||
|
||||
];
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false"
|
||||
syntaxCheck="false"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="October CMS Test Suite">
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ abstract class PluginTestCase extends TestCase
|
|||
$app['cache']->setDefaultDriver('array');
|
||||
$app->setLocale('en');
|
||||
|
||||
$app->singleton('backend.auth', function ($app) {
|
||||
$app->singleton('auth', function ($app) {
|
||||
$app['auth.loaded'] = true;
|
||||
|
||||
return AuthManager::instance();
|
||||
|
|
@ -67,7 +67,7 @@ abstract class PluginTestCase extends TestCase
|
|||
* Perform test case set up.
|
||||
* @return void
|
||||
*/
|
||||
public function setUp() : void
|
||||
public function setUp()
|
||||
{
|
||||
/*
|
||||
* Force reload of October singletons
|
||||
|
|
@ -105,7 +105,7 @@ abstract class PluginTestCase extends TestCase
|
|||
* Flush event listeners and collect garbage.
|
||||
* @return void
|
||||
*/
|
||||
public function tearDown() : void
|
||||
public function tearDown()
|
||||
{
|
||||
$this->flushModelEventListeners();
|
||||
parent::tearDown();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Plugin testing
|
||||
|
||||
Individual plugin test cases can be run by running `../../../vendor/bin/phpunit` in the plugin's base directory (ex. `plugins/acme/demo`.
|
||||
Plugin unit tests can be performed by running `phpunit` in the base plugin directory.
|
||||
|
||||
### Creating plugin tests
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ The test class should extend the base class `PluginTestCase` and this is a speci
|
|||
|
||||
class BaseTestCase extends PluginTestCase
|
||||
{
|
||||
public function setUp(): void
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
|
|
@ -72,7 +72,7 @@ The test class should extend the base class `PluginTestCase` and this is a speci
|
|||
$pluginManager->bootAll(true);
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
public function tearDown()
|
||||
{
|
||||
parent::tearDown();
|
||||
|
||||
|
|
@ -96,10 +96,39 @@ To perform unit testing on the core October files, you should download a develop
|
|||
|
||||
### Unit tests
|
||||
|
||||
Unit tests can be performed by running `vendor/bin/phpunit` in the root directory of your October CMS installation.
|
||||
Unit tests can be performed by running `phpunit` in the root directory or inside `/tests/unit`.
|
||||
|
||||
### Functional tests
|
||||
|
||||
Functional tests can be performed by installing the [RainLab Dusk](https://octobercms.com/plugin/rainlab-dusk) in your October CMS installation. The RainLab Dusk plugin is powered by Laravel Dusk, a comprehensive testing suite for the Laravel framework that is designed to test interactions with a fully operational October CMS instance through a virtual browser.
|
||||
Functional tests can be performed by running `phpunit` in the `/tests/functional` directory. Ensure the following configuration is met:
|
||||
|
||||
For information on installing and setting up your October CMS install to run functional tests, please review the [README](https://github.com/rainlab/dusk-plugin/blob/master/README.md) for the plugin.
|
||||
- Active theme is `demo`
|
||||
- Language preference is `en`
|
||||
|
||||
#### Selenium set up
|
||||
|
||||
1. Download latest Java SE from http://java.sun.com/ and install
|
||||
1. Download a distribution archive of [Selenium Server](http://seleniumhq.org/download/).
|
||||
1. Unzip the distribution archive and copy selenium-server-standalone-2.42.2.jar (check the version suffix) to /usr/local/bin, for instance.
|
||||
1. Start the Selenium Server server by running `java -jar /usr/local/bin/selenium-server-standalone-2.42.2.jar`.
|
||||
|
||||
#### Selenium configuration
|
||||
|
||||
Create a new file `selenium.php` in the root directory, add the following content:
|
||||
|
||||
<?php
|
||||
|
||||
// Selenium server details
|
||||
define('TEST_SELENIUM_HOST', '127.0.0.1');
|
||||
define('TEST_SELENIUM_PORT', 4444);
|
||||
define('TEST_SELENIUM_BROWSER', '*firefox');
|
||||
|
||||
// Back-end URL
|
||||
define('TEST_SELENIUM_URL', 'http://localhost/backend/');
|
||||
|
||||
// Active Theme
|
||||
define('TEST_SELENIUM_THEME', 'demo');
|
||||
|
||||
// Back-end credentials
|
||||
define('TEST_SELENIUM_USER', 'admin');
|
||||
define('TEST_SELENIUM_PASS', 'admin');
|
||||
|
|
|
|||
|
|
@ -0,0 +1,111 @@
|
|||
<?php
|
||||
|
||||
class UiTestCase extends PHPUnit_Extensions_SeleniumTestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
/*
|
||||
* Look for selenium configuration
|
||||
*/
|
||||
if (file_exists($seleniumEnv = __DIR__.'/../selenium.php')) {
|
||||
require_once $seleniumEnv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure selenium
|
||||
*/
|
||||
if (!defined('TEST_SELENIUM_URL')) {
|
||||
return $this->markTestSkipped('Selenium skipped');
|
||||
}
|
||||
|
||||
if (defined('TEST_SELENIUM_HOST')) {
|
||||
$this->setHost(TEST_SELENIUM_HOST);
|
||||
}
|
||||
if (defined('TEST_SELENIUM_PORT')) {
|
||||
$this->setPort(TEST_SELENIUM_PORT);
|
||||
}
|
||||
if (defined('TEST_SELENIUM_BROWSER')) {
|
||||
$this->setBrowser(TEST_SELENIUM_BROWSER);
|
||||
}
|
||||
$this->setBrowserUrl(TEST_SELENIUM_URL);
|
||||
}
|
||||
|
||||
//
|
||||
// OctoberCMS Helpers
|
||||
//
|
||||
|
||||
protected function signInToBackend()
|
||||
{
|
||||
$this->open('backend');
|
||||
$this->type("name=login", TEST_SELENIUM_USER);
|
||||
$this->type("name=password", TEST_SELENIUM_PASS);
|
||||
$this->click("//button[@type='submit']");
|
||||
$this->waitForPageToLoad("30000");
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to the native getConfirmation() function
|
||||
*/
|
||||
protected function getSweetConfirmation($expectedText = null, $clickOk = true)
|
||||
{
|
||||
$this->waitForElementPresent("xpath=(//div[@class='sweet-alert showSweetAlert visible'])[1]");
|
||||
|
||||
if ($expectedText) {
|
||||
$this->verifyText("//div[@class='sweet-alert showSweetAlert visible']//h4", $expectedText);
|
||||
}
|
||||
|
||||
$this->verifyText("//div[@class='sweet-alert showSweetAlert visible']//button[@class='confirm btn btn-primary']", "OK");
|
||||
|
||||
if ($clickOk) {
|
||||
$this->click("xpath=(//div[@class='sweet-alert showSweetAlert visible']//button[@class='confirm btn btn-primary'])[1]");
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Selenium helpers
|
||||
//
|
||||
|
||||
protected function waitForElementPresent($target, $timeout = 60)
|
||||
{
|
||||
$second = 0;
|
||||
|
||||
while (true) {
|
||||
if ($second >= $timeout) {
|
||||
$this->fail('timeout');
|
||||
}
|
||||
|
||||
try {
|
||||
if ($this->isElementPresent($target)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
++$second;
|
||||
}
|
||||
}
|
||||
|
||||
protected function waitForElementNotPresent($target, $timeout = 60)
|
||||
{
|
||||
$second = 0;
|
||||
|
||||
while (true) {
|
||||
if ($second >= $timeout) {
|
||||
$this->fail('timeout');
|
||||
}
|
||||
|
||||
try {
|
||||
if (!$this->isElementPresent($target)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
++$second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -19,3 +19,14 @@ $loader->addDirectories([
|
|||
'modules',
|
||||
'plugins'
|
||||
]);
|
||||
|
||||
/*
|
||||
* Monkey patch PHPUnit\Framework\MockObject\Generator to avoid
|
||||
* "Function ReflectionType::__toString() is deprecated" warnings
|
||||
*/
|
||||
$generatorPatchPath = __DIR__ . '/resources/patches/php-generator-7.php';
|
||||
$generatorSourcePath = __DIR__ . '/../vendor/phpunit/phpunit-mock-objects/src/Generator.php';
|
||||
|
||||
if (file_exists($generatorSourcePath)) {
|
||||
file_put_contents($generatorSourcePath, file_get_contents($generatorPatchPath));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ trait InteractsWithAuthentication
|
|||
*/
|
||||
public function be(UserContract $user, $driver = null)
|
||||
{
|
||||
$this->app['backend.auth']->setUser($user);
|
||||
$this->app['auth']->setUser($user);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -66,7 +66,7 @@ trait InteractsWithAuthentication
|
|||
*/
|
||||
protected function isAuthenticated($guard = null)
|
||||
{
|
||||
return $this->app->make('backend.auth')->guard($guard)->check();
|
||||
return $this->app->make('auth')->guard($guard)->check();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -78,7 +78,7 @@ trait InteractsWithAuthentication
|
|||
*/
|
||||
public function assertAuthenticatedAs($user, $guard = null)
|
||||
{
|
||||
$expected = $this->app->make('backend.auth')->guard($guard)->user();
|
||||
$expected = $this->app->make('auth')->guard($guard)->user();
|
||||
|
||||
$this->assertNotNull($expected, 'The current user is not authenticated.');
|
||||
|
||||
|
|
@ -140,7 +140,7 @@ trait InteractsWithAuthentication
|
|||
*/
|
||||
protected function hasCredentials(array $credentials, $guard = null)
|
||||
{
|
||||
$provider = $this->app->make('backend.auth')->guard($guard)->getProvider();
|
||||
$provider = $this->app->make('auth')->guard($guard)->getProvider();
|
||||
|
||||
$user = $provider->retrieveByCredentials($credentials);
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ class Author extends Model
|
|||
*/
|
||||
public $belongsTo = [
|
||||
'user' => ['Database\Tester\Models\User', 'delete' => true],
|
||||
'country' => ['Database\Tester\Models\Country'],
|
||||
'user_soft' => ['Database\Tester\Models\SoftDeleteUser', 'key' => 'user_id', 'softDelete' => true],
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
<?php namespace Database\Tester\Models;
|
||||
|
||||
use Model;
|
||||
|
||||
class Country extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string The database table used by the model.
|
||||
*/
|
||||
public $table = 'database_tester_countries';
|
||||
|
||||
/**
|
||||
* @var array Guarded fields
|
||||
*/
|
||||
protected $guarded = [];
|
||||
|
||||
public $hasMany = [
|
||||
'users' => [
|
||||
'Database\Tester\Models\User',
|
||||
],
|
||||
];
|
||||
|
||||
public $hasManyThrough = [
|
||||
'posts' => [
|
||||
'Database\Tester\Models\Post',
|
||||
'through' => 'Database\Tester\Models\Author',
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
class SoftDeleteCountry extends Country
|
||||
{
|
||||
use \October\Rain\Database\Traits\SoftDelete;
|
||||
}
|
||||
|
|
@ -17,19 +17,6 @@ class User extends Model
|
|||
/**
|
||||
* @var array Relations
|
||||
*/
|
||||
public $hasOne = [
|
||||
'author' => [
|
||||
'Database\Tester\Models\Author',
|
||||
]
|
||||
];
|
||||
|
||||
public $hasOneThrough = [
|
||||
'phone' => [
|
||||
'Database\Tester\Models\Phone',
|
||||
'through' => 'Database\Tester\Models\Author',
|
||||
],
|
||||
];
|
||||
|
||||
public $attachOne = [
|
||||
'avatar' => 'System\Models\File'
|
||||
];
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ class CreateAuthorsTable extends Migration
|
|||
$table->engine = 'InnoDB';
|
||||
$table->increments('id');
|
||||
$table->integer('user_id')->unsigned()->index()->nullable();
|
||||
$table->integer('country_id')->unsigned()->index()->nullable();
|
||||
$table->string('name')->nullable();
|
||||
$table->string('email')->nullable();
|
||||
$table->softDeletes();
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
<?php namespace Database\Tester\Updates;
|
||||
|
||||
use Schema;
|
||||
use October\Rain\Database\Updates\Migration;
|
||||
|
||||
class CreateCountriesTable extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::create('database_tester_countries', function ($table) {
|
||||
$table->engine = 'InnoDB';
|
||||
$table->increments('id');
|
||||
$table->string('name')->nullable();
|
||||
$table->softDeletes();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('database_tester_countries');
|
||||
}
|
||||
}
|
||||
|
|
@ -9,4 +9,3 @@
|
|||
- create_users_table.php
|
||||
- create_event_log_table.php
|
||||
- create_meta_table.php
|
||||
- create_countries_table.php
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
console.log('script1.js');
|
||||
|
|
@ -1 +0,0 @@
|
|||
console.log('script2.js');
|
||||
|
|
@ -1 +0,0 @@
|
|||
console.log('subdir/script1.js');
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
class AuthTest extends UiTestCase
|
||||
{
|
||||
public function testSignInAndOut()
|
||||
{
|
||||
$this->open('backend');
|
||||
|
||||
$cssLogoutLink = '#layout-mainmenu .mainmenu-accountmenu > ul > li:first-child > a';
|
||||
|
||||
try {
|
||||
$this->assertTitle('Administration Area');
|
||||
$this->assertTrue($this->isElementPresent("name=login"));
|
||||
$this->assertTrue($this->isElementPresent("name=password"));
|
||||
$this->assertTrue($this->isElementPresent("//button[@type='submit']"));
|
||||
$this->verifyText("//button[@type='submit']", "Login");
|
||||
}
|
||||
catch (PHPUnit_Framework_AssertionFailedError $e) {
|
||||
array_push($this->verificationErrors, $e->toString());
|
||||
}
|
||||
|
||||
/*
|
||||
* Sign in
|
||||
*/
|
||||
$this->type("name=login", TEST_SELENIUM_USER);
|
||||
$this->type("name=password", TEST_SELENIUM_PASS);
|
||||
$this->click("//button[@type='submit']");
|
||||
$this->waitForPageToLoad("30000");
|
||||
|
||||
try {
|
||||
$this->assertTitle('Dashboard | October CMS');
|
||||
$this->assertTrue($this->isElementPresent('css='.$cssLogoutLink));
|
||||
}
|
||||
catch (PHPUnit_Framework_AssertionFailedError $e) {
|
||||
array_push($this->verificationErrors, $e->toString());
|
||||
}
|
||||
|
||||
$this->verifyText('css='.$cssLogoutLink, "Sign out");
|
||||
|
||||
/*
|
||||
* Log out
|
||||
*/
|
||||
$this->click('css='.$cssLogoutLink);
|
||||
$this->waitForPageToLoad("30000");
|
||||
|
||||
try {
|
||||
$this->assertTitle('Administration Area');
|
||||
}
|
||||
catch (PHPUnit_Framework_AssertionFailedError $e) {
|
||||
array_push($this->verificationErrors, $e->toString());
|
||||
}
|
||||
}
|
||||
|
||||
public function testPasswordReset()
|
||||
{
|
||||
$this->open('backend');
|
||||
|
||||
try {
|
||||
$this->assertTrue($this->isElementPresent("link=exact:Forgot your password?"));
|
||||
}
|
||||
catch (PHPUnit_Framework_AssertionFailedError $e) {
|
||||
array_push($this->verificationErrors, $e->toString());
|
||||
}
|
||||
|
||||
$this->click('link=exact:Forgot your password?');
|
||||
$this->waitForPageToLoad("30000");
|
||||
|
||||
try {
|
||||
$this->assertTrue($this->isElementPresent("//button[@type='submit']"));
|
||||
$this->verifyText("//button[@type='submit']", "Restore");
|
||||
$this->assertTrue($this->isElementPresent("link=Cancel"));
|
||||
}
|
||||
catch (PHPUnit_Framework_AssertionFailedError $e) {
|
||||
array_push($this->verificationErrors, $e->toString());
|
||||
}
|
||||
|
||||
$this->type("name=login", TEST_SELENIUM_USER);
|
||||
sleep(1);
|
||||
$this->click("//button[@type='submit']");
|
||||
$this->waitForPageToLoad("30000");
|
||||
|
||||
try {
|
||||
$this->assertTitle('Administration Area');
|
||||
$this->assertTrue($this->isElementPresent("css=p.flash-message.success"));
|
||||
$this->verifyText("css=p.flash-message.success", "An email has been sent to your email address with password restore instructions.×");
|
||||
}
|
||||
catch (PHPUnit_Framework_AssertionFailedError $e) {
|
||||
array_push($this->verificationErrors, $e->toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
<?php
|
||||
class TemplateTest extends UiTestCase
|
||||
{
|
||||
public function testOpenTemplates()
|
||||
{
|
||||
$this->signInToBackend();
|
||||
$this->open('cms');
|
||||
$this->waitForPageToLoad("30000");
|
||||
|
||||
// Fix the sidebar
|
||||
$this->click("xpath=(//a[@class='fix-button'])[1]");
|
||||
|
||||
/*
|
||||
* Page
|
||||
*/
|
||||
|
||||
// Create a new page
|
||||
$this->click("xpath=(//form[@data-template-type='page']//button[@data-control='create-template'])[1]");
|
||||
$this->waitForElementPresent("name=settings[title]");
|
||||
|
||||
// Populate page details
|
||||
$this->type('name=settings[title]', 'Functional Test Page');
|
||||
$this->type('name=settings[url]', '/xxx/functional/test/page');
|
||||
$this->type('name=fileName', 'xxx_functional_test_page');
|
||||
|
||||
// Save the new page
|
||||
$this->click("xpath=(//a[@data-request='onSave'])[1]");
|
||||
$this->waitForElementPresent("xpath=(//li[@data-tab-id='page-".TEST_SELENIUM_THEME."-xxx_functional_test_page.htm'])[1]");
|
||||
|
||||
// Close the tab
|
||||
$this->click("xpath=(//li[@data-tab-id='page-".TEST_SELENIUM_THEME."-xxx_functional_test_page.htm']/span[@class='tab-close'])[1]");
|
||||
|
||||
// Reopen the tab
|
||||
$this->waitForElementPresent("xpath=(//div[@id='TemplateList-pageList-template-list']//li[@data-item-path='xxx_functional_test_page.htm']/a)[1]");
|
||||
$this->click("xpath=(//div[@id='TemplateList-pageList-template-list']//li[@data-item-path='xxx_functional_test_page.htm']/a)[1]");
|
||||
$this->waitForElementPresent("name=settings[title]");
|
||||
sleep(1);
|
||||
|
||||
// Delete the page
|
||||
$this->click("xpath=(//button[@data-request='onDelete'])[1]");
|
||||
$this->getSweetConfirmation('Do you really want delete this page?');
|
||||
// $this->assertTrue((bool)preg_match('/^Do you really want delete this page[\s\S]$/',$this->getConfirmation()));
|
||||
$this->waitForElementNotPresent("name=settings[title]");
|
||||
|
||||
/*
|
||||
* Partial
|
||||
*/
|
||||
|
||||
// Click partials menu item
|
||||
$this->click("xpath=(//li[@data-menu-item='partials']/a)[1]");
|
||||
|
||||
// Create a new partial
|
||||
$this->click("xpath=(//form[@data-template-type='partial']//button[@data-control='create-template'])[1]");
|
||||
$this->waitForElementPresent("name=fileName");
|
||||
|
||||
// Populate partial details
|
||||
$this->type('name=fileName', 'xxx_functional_test_partial');
|
||||
$this->type('name=settings[description]', 'Test partial');
|
||||
|
||||
// Save the new partial
|
||||
$this->click("xpath=(//a[@data-request='onSave'])[1]");
|
||||
$this->waitForElementPresent("xpath=(//li[@data-tab-id='partial-".TEST_SELENIUM_THEME."-xxx_functional_test_partial.htm'])[1]");
|
||||
|
||||
// Close the tab
|
||||
$this->click("xpath=(//li[@data-tab-id='partial-".TEST_SELENIUM_THEME."-xxx_functional_test_partial.htm']/span[@class='tab-close'])[1]");
|
||||
|
||||
// Reopen the tab
|
||||
$this->waitForElementPresent("xpath=(//div[@id='TemplateList-partialList-template-list']//li[@data-item-path='xxx_functional_test_partial.htm']/a)[1]");
|
||||
$this->click("xpath=(//div[@id='TemplateList-partialList-template-list']//li[@data-item-path='xxx_functional_test_partial.htm']/a)[1]");
|
||||
$this->waitForElementPresent("name=fileName");
|
||||
sleep(1);
|
||||
|
||||
// Delete the partial
|
||||
$this->click("xpath=(//button[@data-request='onDelete'])[1]");
|
||||
$this->getSweetConfirmation('Do you really want delete this partial?');
|
||||
$this->waitForElementNotPresent("name=fileName");
|
||||
|
||||
/*
|
||||
* Layout
|
||||
*/
|
||||
|
||||
// Click layouts menu item
|
||||
$this->click("xpath=(//li[@data-menu-item='layouts']/a)[1]");
|
||||
|
||||
// Create a new layout
|
||||
$this->click("xpath=(//form[@data-template-type='layout']//button[@data-control='create-template'])[1]");
|
||||
$this->waitForElementPresent("name=fileName");
|
||||
|
||||
// Populate layout details
|
||||
$this->type('name=fileName', 'xxx_functional_test_layout');
|
||||
$this->type('name=settings[description]', 'Test layout');
|
||||
|
||||
// Save the new layout
|
||||
$this->click("xpath=(//a[@data-request='onSave'])[1]");
|
||||
$this->waitForElementPresent("xpath=(//li[@data-tab-id='layout-".TEST_SELENIUM_THEME."-xxx_functional_test_layout.htm'])[1]");
|
||||
|
||||
// Close the tab
|
||||
$this->click("xpath=(//li[@data-tab-id='layout-".TEST_SELENIUM_THEME."-xxx_functional_test_layout.htm']/span[@class='tab-close'])[1]");
|
||||
|
||||
// Reopen the tab
|
||||
$this->waitForElementPresent("xpath=(//div[@id='TemplateList-layoutList-template-list']//li[@data-item-path='xxx_functional_test_layout.htm']/a)[1]");
|
||||
$this->click("xpath=(//div[@id='TemplateList-layoutList-template-list']//li[@data-item-path='xxx_functional_test_layout.htm']/a)[1]");
|
||||
$this->waitForElementPresent("name=fileName");
|
||||
sleep(1);
|
||||
|
||||
// Delete the layout
|
||||
$this->click("xpath=(//button[@data-request='onDelete'])[1]");
|
||||
$this->getSweetConfirmation('Do you really want delete this layout?');
|
||||
$this->waitForElementNotPresent("name=fileName");
|
||||
|
||||
/*
|
||||
* Content
|
||||
*/
|
||||
|
||||
// Click contents menu item
|
||||
$this->click("xpath=(//li[@data-menu-item='content']/a)[1]");
|
||||
|
||||
// Create a new content
|
||||
$this->click("xpath=(//form[@data-template-type='content']//button[@data-control='create-template'])[1]");
|
||||
$this->waitForElementPresent("name=fileName");
|
||||
|
||||
// Populate content details
|
||||
$this->type('name=fileName', 'xxx_functional_test_content.txt');
|
||||
|
||||
// Save the new content
|
||||
$this->click("xpath=(//a[@data-request='onSave'])[1]");
|
||||
$this->waitForElementPresent("xpath=(//li[@data-tab-id='content-".TEST_SELENIUM_THEME."-xxx_functional_test_content.txt'])[1]");
|
||||
|
||||
// Close the tab
|
||||
$this->click("xpath=(//li[@data-tab-id='content-".TEST_SELENIUM_THEME."-xxx_functional_test_content.txt']/span[@class='tab-close'])[1]");
|
||||
|
||||
// Reopen the tab
|
||||
$this->waitForElementPresent("xpath=(//div[@id='TemplateList-contentList-template-list']//li[@data-item-path='xxx_functional_test_content.txt']/a)[1]");
|
||||
$this->click("xpath=(//div[@id='TemplateList-contentList-template-list']//li[@data-item-path='xxx_functional_test_content.txt']/a)[1]");
|
||||
$this->waitForElementPresent("name=fileName");
|
||||
sleep(1);
|
||||
|
||||
// Delete the content
|
||||
$this->click("xpath=(//button[@data-request='onDelete'])[1]");
|
||||
$this->getSweetConfirmation('Do you really want delete this content file?');
|
||||
$this->waitForElementNotPresent("name=fileName");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
bootstrap="../../bootstrap/autoload.php"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="true"
|
||||
syntaxCheck="false"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="October Test Suite">
|
||||
<directory>./</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
</phpunit>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -4,7 +4,7 @@ use October\Rain\Exception\SystemException;
|
|||
|
||||
class AuthManagerTest extends TestCase
|
||||
{
|
||||
public function setUp(): void
|
||||
public function setUp()
|
||||
{
|
||||
$this->createApplication();
|
||||
|
||||
|
|
@ -23,7 +23,7 @@ class AuthManagerTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
public function tearDown()
|
||||
{
|
||||
AuthManager::forgetInstance();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,18 +59,18 @@ class NavigationManagerTest extends TestCase
|
|||
$manager->setContext('October.Tester', 'blog');
|
||||
|
||||
$items = $manager->listSideMenuItems();
|
||||
$this->assertIsArray($items);
|
||||
$this->assertInternalType('array', $items);
|
||||
$this->assertArrayHasKey('posts', $items);
|
||||
$this->assertArrayHasKey('categories', $items);
|
||||
|
||||
$this->assertIsObject($items['posts']);
|
||||
$this->assertInternalType('object', $items['posts']);
|
||||
$this->assertObjectHasAttribute('code', $items['posts']);
|
||||
$this->assertObjectHasAttribute('owner', $items['posts']);
|
||||
$this->assertEquals('posts', $items['posts']->code);
|
||||
$this->assertEquals('October.Tester', $items['posts']->owner);
|
||||
|
||||
$this->assertObjectHasAttribute('permissions', $items['posts']);
|
||||
$this->assertIsArray($items['posts']->permissions);
|
||||
$this->assertInternalType('array', $items['posts']->permissions);
|
||||
$this->assertCount(1, $items['posts']->permissions);
|
||||
|
||||
$this->assertObjectHasAttribute('order', $items['posts']);
|
||||
|
|
@ -92,7 +92,7 @@ class NavigationManagerTest extends TestCase
|
|||
|
||||
$items = $manager->listMainMenuItems();
|
||||
|
||||
$this->assertIsArray($items);
|
||||
$this->assertInternalType('array', $items);
|
||||
$this->assertArrayHasKey('OCTOBER.TESTER.PRINT', $items);
|
||||
|
||||
$item = $items['OCTOBER.TESTER.PRINT'];
|
||||
|
|
@ -143,10 +143,10 @@ class NavigationManagerTest extends TestCase
|
|||
$manager->setContext('October.Tester', 'blog');
|
||||
$items = $manager->listSideMenuItems();
|
||||
|
||||
$this->assertIsArray($items);
|
||||
$this->assertInternalType('array', $items);
|
||||
$this->assertArrayHasKey('foo', $items);
|
||||
|
||||
$this->assertIsObject($items['foo']);
|
||||
$this->assertInternalType('object', $items['foo']);
|
||||
$this->assertObjectHasAttribute('code', $items['foo']);
|
||||
$this->assertObjectHasAttribute('owner', $items['foo']);
|
||||
$this->assertObjectHasAttribute('order', $items['foo']);
|
||||
|
|
@ -156,7 +156,7 @@ class NavigationManagerTest extends TestCase
|
|||
$this->assertEquals('October.Tester', $items['foo']->owner);
|
||||
|
||||
$this->assertObjectHasAttribute('permissions', $items['foo']);
|
||||
$this->assertIsArray($items['foo']->permissions);
|
||||
$this->assertInternalType('array', $items['foo']->permissions);
|
||||
$this->assertCount(2, $items['foo']->permissions);
|
||||
$this->assertContains('october.tester.access_foo', $items['foo']->permissions);
|
||||
$this->assertContains('october.tester.access_bar', $items['foo']->permissions);
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ class BackendHelperTest extends TestCase
|
|||
$assets = $backendHelper->decompileAsset('tests/fixtures/backend/assets/compilation.js');
|
||||
|
||||
$this->assertCount(2, $assets);
|
||||
$this->assertStringContainsString('file1.js', $assets[0]);
|
||||
$this->assertStringContainsString('file2.js', $assets[1]);
|
||||
$this->assertContains('file1.js', $assets[0]);
|
||||
$this->assertContains('file2.js', $assets[1]);
|
||||
}
|
||||
|
||||
public function testDecompileMissingFile()
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class WidgetMakerTest extends TestCase
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUp() : void
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,119 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Cms\Classes\Theme;
|
||||
use Cms\Classes\Asset;
|
||||
|
||||
class AssetTest extends TestCase
|
||||
{
|
||||
public function testLoad()
|
||||
{
|
||||
$theme = Theme::load('test');
|
||||
|
||||
// Valid direct path
|
||||
$this->assertStringContainsString(
|
||||
'console.log(\'script1.js\');',
|
||||
Asset::load($theme, 'js/script1.js')->content
|
||||
);
|
||||
|
||||
// Valid direct subdirectory path
|
||||
$this->assertStringContainsString(
|
||||
'console.log(\'subdir/script1.js\');',
|
||||
Asset::load($theme, 'js/subdir/script1.js')->content
|
||||
);
|
||||
|
||||
// Valid relative path
|
||||
$this->assertStringContainsString(
|
||||
'console.log(\'script2.js\');',
|
||||
Asset::load($theme, 'js/subdir/../script2.js')->content
|
||||
);
|
||||
|
||||
// Invalid theme path
|
||||
$this->assertNull(
|
||||
Asset::load($theme, 'js/invalid.js')
|
||||
);
|
||||
|
||||
// Check that we cannot break out of assets directory
|
||||
$this->assertNull(
|
||||
Asset::load($theme, '../../../../js/helpers/fakeDom.js')
|
||||
);
|
||||
$this->assertNull(
|
||||
Asset::load($theme, '../content/html-content.htm')
|
||||
);
|
||||
|
||||
// Check that we cannot load directories directly
|
||||
$this->assertNull(
|
||||
Asset::load($theme, 'js/subdir')
|
||||
);
|
||||
|
||||
// Check that we definitely cannot load external PHP files
|
||||
$this->assertNull(
|
||||
Asset::load($theme, '../../../../../config/database.php')
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetPath()
|
||||
{
|
||||
// Test some pathing fringe cases
|
||||
|
||||
$theme = Theme::load('test');
|
||||
$assetClass = new Asset($theme);
|
||||
$themeDir = $theme->getPath();
|
||||
|
||||
// Direct paths
|
||||
$this->assertEquals(
|
||||
$themeDir . '/assets/js/script1.js',
|
||||
$assetClass->getFilePath('js/script1.js')
|
||||
);
|
||||
$this->assertEquals(
|
||||
$themeDir . '/assets/js/script1.js',
|
||||
$assetClass->getFilePath('/js/script1.js')
|
||||
);
|
||||
|
||||
// Direct path to a directory
|
||||
$this->assertEquals(
|
||||
$themeDir . '/assets/js/subdir',
|
||||
$assetClass->getFilePath('/js/subdir')
|
||||
);
|
||||
$this->assertEquals(
|
||||
$themeDir . '/assets/js/subdir',
|
||||
$assetClass->getFilePath('/js/subdir/')
|
||||
);
|
||||
|
||||
// Relative paths
|
||||
$this->assertEquals(
|
||||
$themeDir . '/assets/js/script2.js',
|
||||
$assetClass->getFilePath('./js/script2.js')
|
||||
);
|
||||
$this->assertEquals(
|
||||
$themeDir . '/assets/js/script2.js',
|
||||
$assetClass->getFilePath('/js/subdir/../script2.js')
|
||||
);
|
||||
|
||||
// Missing file, but valid directory (allows for new files)
|
||||
$this->assertEquals(
|
||||
$themeDir . '/assets/js/missing.js',
|
||||
$assetClass->getFilePath('/js/missing.js')
|
||||
);
|
||||
$this->assertEquals(
|
||||
$themeDir . '/assets/js/missing.js',
|
||||
$assetClass->getFilePath('js/missing.js')
|
||||
);
|
||||
|
||||
// Missing file and missing directory (new directories are created as needed)
|
||||
$this->assertEquals(
|
||||
$themeDir . '/assets/js/missing/missing.js',
|
||||
$assetClass->getFilePath('/js/missing/missing.js')
|
||||
);
|
||||
|
||||
// Ensure we cannot get paths outside of the assets directory
|
||||
$this->assertFalse(
|
||||
$assetClass->getFilePath('../../../../js/helpers/fakeDom.js')
|
||||
);
|
||||
$this->assertFalse(
|
||||
$assetClass->getFilePath('../content/html-content.htm')
|
||||
);
|
||||
$this->assertFalse(
|
||||
$assetClass->getFilePath('../../../../../config/database.php')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -30,7 +30,7 @@ class TestTemporaryCmsCompoundObject extends CmsCompoundObject
|
|||
|
||||
class CmsCompoundObjectTest extends TestCase
|
||||
{
|
||||
public function setUp() : void
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
Model::clearBootedModels();
|
||||
|
|
@ -44,16 +44,16 @@ class CmsCompoundObjectTest extends TestCase
|
|||
$theme = Theme::load('test');
|
||||
|
||||
$obj = TestCmsCompoundObject::load($theme, 'compound.htm');
|
||||
$this->assertStringContainsString("\$controller->data['something'] = 'some value'", $obj->code);
|
||||
$this->assertContains("\$controller->data['something'] = 'some value'", $obj->code);
|
||||
$this->assertEquals('<p>This is a paragraph</p>', $obj->markup);
|
||||
$this->assertIsArray($obj->settings);
|
||||
$this->assertInternalType('array', $obj->settings);
|
||||
$this->assertArrayHasKey('var', $obj->settings);
|
||||
$this->assertEquals('value', $obj->settings['var']);
|
||||
|
||||
$this->assertArrayHasKey('components', $obj->settings);
|
||||
|
||||
$this->assertArrayHasKey('section', $obj->settings['components']);
|
||||
$this->assertIsArray($obj->settings['components']['section']);
|
||||
$this->assertInternalType('array', $obj->settings['components']['section']);
|
||||
$this->assertArrayHasKey('version', $obj->settings['components']['section']);
|
||||
$this->assertEquals(10, $obj->settings['components']['section']['version']);
|
||||
|
||||
|
|
@ -69,7 +69,7 @@ class CmsCompoundObjectTest extends TestCase
|
|||
|
||||
$obj = TestCmsCompoundObject::load($theme, 'component.htm');
|
||||
$this->assertArrayHasKey('components', $obj->settings);
|
||||
$this->assertIsArray($obj->settings['components']);
|
||||
$this->assertInternalType('array', $obj->settings['components']);
|
||||
$this->assertArrayHasKey('testArchive', $obj->settings['components']);
|
||||
$this->assertArrayHasKey('posts-per-page', $obj->settings['components']['testArchive']);
|
||||
$this->assertEquals(10, $obj->settings['components']['testArchive']['posts-per-page']);
|
||||
|
|
@ -82,7 +82,7 @@ class CmsCompoundObjectTest extends TestCase
|
|||
$obj = TestCmsCompoundObject::load($theme, 'components.htm');
|
||||
$this->assertArrayHasKey('components', $obj->settings);
|
||||
|
||||
$this->assertIsArray($obj->settings['components']);
|
||||
$this->assertInternalType('array', $obj->settings['components']);
|
||||
$this->assertArrayHasKey('testArchive firstAlias', $obj->settings['components']);
|
||||
$this->assertArrayHasKey('October\Tester\Components\Post secondAlias', $obj->settings['components']);
|
||||
|
||||
|
|
@ -108,7 +108,7 @@ class CmsCompoundObjectTest extends TestCase
|
|||
$properties = $obj->getComponentProperties('October\Tester\Components\Post');
|
||||
$emptyProperties = $obj->getComponentProperties('October\Tester\Components\Archive');
|
||||
$notExistingProperties = $obj->getComponentProperties('This\Is\Not\Component');
|
||||
$this->assertIsArray($properties);
|
||||
$this->assertInternalType('array', $properties);
|
||||
$this->assertArrayHasKey('show-featured', $properties);
|
||||
$this->assertTrue((bool)$properties['show-featured']);
|
||||
$this->assertEquals('true', $properties['show-featured']);
|
||||
|
|
@ -148,18 +148,18 @@ class CmsCompoundObjectTest extends TestCase
|
|||
$this->assertEquals($testContent, $obj->getContent());
|
||||
$this->assertEquals('testcompound.htm', $obj->getFileName());
|
||||
$this->assertEquals('<p>This is a paragraph</p>', $obj->markup);
|
||||
$this->assertIsArray($obj->settings);
|
||||
$this->assertInternalType('array', $obj->settings);
|
||||
$this->assertArrayHasKey('var', $obj->settings);
|
||||
$this->assertEquals('value', $obj->settings['var']);
|
||||
|
||||
$this->assertArrayHasKey('components', $obj->settings);
|
||||
|
||||
$this->assertIsArray($obj->settings['components']['section']);
|
||||
$this->assertInternalType('array', $obj->settings['components']['section']);
|
||||
$this->assertArrayHasKey('version', $obj->settings['components']['section']);
|
||||
$this->assertEquals(10, $obj->settings['components']['section']['version']);
|
||||
|
||||
$this->assertEquals('value', $obj->var);
|
||||
$this->assertIsArray($obj->settings['components']['section']);
|
||||
$this->assertInternalType('array', $obj->settings['components']['section']);
|
||||
$this->assertArrayHasKey('version', $obj->settings['components']['section']);
|
||||
$this->assertEquals(10, $obj->settings['components']['section']['version']);
|
||||
|
||||
|
|
@ -173,18 +173,18 @@ class CmsCompoundObjectTest extends TestCase
|
|||
$this->assertEquals($testContent, $obj->getContent());
|
||||
$this->assertEquals('testcompound.htm', $obj->getFileName());
|
||||
$this->assertEquals('<p>This is a paragraph</p>', $obj->markup);
|
||||
$this->assertIsArray($obj->settings);
|
||||
$this->assertInternalType('array', $obj->settings);
|
||||
$this->assertArrayHasKey('var', $obj->settings);
|
||||
$this->assertEquals('value', $obj->settings['var']);
|
||||
|
||||
$this->assertArrayHasKey('components', $obj->settings);
|
||||
|
||||
$this->assertIsArray($obj->settings['components']['section']);
|
||||
$this->assertInternalType('array', $obj->settings['components']['section']);
|
||||
$this->assertArrayHasKey('version', $obj->settings['components']['section']);
|
||||
$this->assertEquals(10, $obj->settings['components']['section']['version']);
|
||||
|
||||
$this->assertEquals('value', $obj->var);
|
||||
$this->assertIsArray($obj->settings['components']['section']);
|
||||
$this->assertInternalType('array', $obj->settings['components']['section']);
|
||||
$this->assertArrayHasKey('version', $obj->settings['components']['section']);
|
||||
$this->assertEquals(10, $obj->settings['components']['section']['version']);
|
||||
}
|
||||
|
|
@ -280,14 +280,14 @@ class CmsCompoundObjectTest extends TestCase
|
|||
$obj = TestParsedCmsCompoundObject::load($theme, 'viewbag.htm');
|
||||
$this->assertNull($obj->code);
|
||||
$this->assertEquals('<p>Chop Suey!</p>', $obj->markup);
|
||||
$this->assertIsArray($obj->settings);
|
||||
$this->assertInternalType('array', $obj->settings);
|
||||
$this->assertArrayHasKey('var', $obj->settings);
|
||||
$this->assertEquals('value', $obj->settings['var']);
|
||||
|
||||
$this->assertArrayHasKey('components', $obj->settings);
|
||||
|
||||
$this->assertArrayHasKey('viewBag', $obj->settings['components']);
|
||||
$this->assertIsArray($obj->settings['components']['viewBag']);
|
||||
$this->assertInternalType('array', $obj->settings['components']['viewBag']);
|
||||
$this->assertArrayHasKey('title', $obj->settings['components']['viewBag']);
|
||||
$this->assertEquals('Toxicity', $obj->settings['components']['viewBag']['title']);
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use October\Rain\Halcyon\Model;
|
|||
|
||||
class CmsObjectQueryTest extends TestCase
|
||||
{
|
||||
public function setUp() : void
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
|
|
|
|||
|
|
@ -148,11 +148,12 @@ class CmsObjectTest extends TestCase
|
|||
$this->assertNull($obj->something);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \October\Rain\Exception\ValidationException
|
||||
* @expectedExceptionMessage Invalid file name
|
||||
*/
|
||||
public function testFillInvalidFileNameSymbol()
|
||||
{
|
||||
$this->expectException(\October\Rain\Exception\ValidationException::class);
|
||||
$this->expectExceptionMessage('Invalid file name');
|
||||
|
||||
$theme = Theme::load('apitest');
|
||||
|
||||
$testContents = 'mytestcontent';
|
||||
|
|
@ -163,11 +164,12 @@ class CmsObjectTest extends TestCase
|
|||
$obj->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \October\Rain\Exception\ValidationException
|
||||
* @expectedExceptionMessage Invalid file name
|
||||
*/
|
||||
public function testFillInvalidFileNamePath()
|
||||
{
|
||||
$this->expectException(\October\Rain\Exception\ValidationException::class);
|
||||
$this->expectExceptionMessage('Invalid file name');
|
||||
|
||||
$theme = Theme::load('apitest');
|
||||
|
||||
$testContents = 'mytestcontent';
|
||||
|
|
@ -178,11 +180,12 @@ class CmsObjectTest extends TestCase
|
|||
$obj->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \October\Rain\Exception\ValidationException
|
||||
* @expectedExceptionMessage Invalid file name
|
||||
*/
|
||||
public function testFillInvalidFileSlash()
|
||||
{
|
||||
$this->expectException(\October\Rain\Exception\ValidationException::class);
|
||||
$this->expectExceptionMessage('Invalid file name');
|
||||
|
||||
$theme = Theme::load('apitest');
|
||||
|
||||
$testContents = 'mytestcontent';
|
||||
|
|
@ -193,11 +196,12 @@ class CmsObjectTest extends TestCase
|
|||
$obj->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \October\Rain\Exception\ValidationException
|
||||
* @expectedExceptionMessage The File Name field is required
|
||||
*/
|
||||
public function testFillEmptyFileName()
|
||||
{
|
||||
$this->expectException(\October\Rain\Exception\ValidationException::class);
|
||||
$this->expectExceptionMessage('The File Name field is required');
|
||||
|
||||
$theme = Theme::load('apitest');
|
||||
|
||||
$testContents = 'mytestcontent';
|
||||
|
|
@ -262,12 +266,11 @@ class CmsObjectTest extends TestCase
|
|||
|
||||
/**
|
||||
* @depends testRename
|
||||
* @expectedException \October\Rain\Exception\ApplicationException
|
||||
* @expectedExceptionMessage already exists
|
||||
*/
|
||||
public function testRenameToExistingFile()
|
||||
{
|
||||
$this->expectException(\October\Rain\Exception\ApplicationException::class);
|
||||
$this->expectExceptionMessageMatches('/already\sexists/');
|
||||
|
||||
$theme = Theme::load('apitest');
|
||||
|
||||
$srcFilePath = $theme->getPath().'/testobjects/anotherobj.htm';
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use Cms\Classes\Controller;
|
|||
|
||||
class CodeParserTest extends TestCase
|
||||
{
|
||||
public function setUp() : void
|
||||
public function setUp()
|
||||
{
|
||||
parent::setup();
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ class CodeParserTest extends TestCase
|
|||
$parser = new CodeParser($layout);
|
||||
$info = $parser->parse();
|
||||
|
||||
$this->assertIsArray($info);
|
||||
$this->assertInternalType('array', $info);
|
||||
$this->assertArrayHasKey('filePath', $info);
|
||||
$this->assertArrayHasKey('className', $info);
|
||||
$this->assertArrayHasKey('source', $info);
|
||||
|
|
@ -78,7 +78,7 @@ class CodeParserTest extends TestCase
|
|||
|
||||
$parser = new CodeParser($layout);
|
||||
$info = $parser->parse();
|
||||
$this->assertIsArray($info);
|
||||
$this->assertInternalType('array', $info);
|
||||
$this->assertEquals('request-cache', $info['source']);
|
||||
$this->assertFileExists($info['filePath']);
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ class CodeParserTest extends TestCase
|
|||
|
||||
$parser = new CodeParser($layout);
|
||||
$info = $parser->parse();
|
||||
$this->assertIsArray($info);
|
||||
$this->assertInternalType('array', $info);
|
||||
$this->assertEquals('cache', $info['source']);
|
||||
$this->assertFileExists($info['filePath']);
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ class CodeParserTest extends TestCase
|
|||
|
||||
$parser = new CodeParser($layout);
|
||||
$info = $parser->parse();
|
||||
$this->assertIsArray($info);
|
||||
$this->assertInternalType('array', $info);
|
||||
$this->assertEquals('request-cache', $info['source']);
|
||||
$this->assertFileExists($info['filePath']);
|
||||
|
||||
|
|
@ -110,14 +110,13 @@ class CodeParserTest extends TestCase
|
|||
*/
|
||||
|
||||
$this->assertTrue(@touch($layout->getFilePath()));
|
||||
clearstatcache();
|
||||
$layout = Layout::load($theme, 'php-parser-test.htm');
|
||||
$this->assertNotEmpty($layout);
|
||||
$parser = new CodeParser($layout);
|
||||
$property->setValue($parser, []);
|
||||
|
||||
$info = $parser->parse();
|
||||
$this->assertIsArray($info);
|
||||
$this->assertInternalType('array', $info);
|
||||
$this->assertEquals('parser', $info['source']);
|
||||
$this->assertFileExists($info['filePath']);
|
||||
}
|
||||
|
|
@ -132,7 +131,7 @@ class CodeParserTest extends TestCase
|
|||
$parser = new CodeParser($layout);
|
||||
$info = $parser->parse();
|
||||
|
||||
$this->assertIsArray($info);
|
||||
$this->assertInternalType('array', $info);
|
||||
$this->assertArrayHasKey('filePath', $info);
|
||||
$this->assertArrayHasKey('className', $info);
|
||||
$this->assertArrayHasKey('source', $info);
|
||||
|
|
@ -158,7 +157,7 @@ class CodeParserTest extends TestCase
|
|||
$parser = new CodeParser($page);
|
||||
$info = $parser->parse();
|
||||
|
||||
$this->assertIsArray($info);
|
||||
$this->assertInternalType('array', $info);
|
||||
$this->assertArrayHasKey('filePath', $info);
|
||||
$this->assertArrayHasKey('className', $info);
|
||||
$this->assertArrayHasKey('source', $info);
|
||||
|
|
@ -192,7 +191,7 @@ class CodeParserTest extends TestCase
|
|||
$parser = new CodeParser($page);
|
||||
$info = $parser->parse();
|
||||
|
||||
$this->assertIsArray($info);
|
||||
$this->assertInternalType('array', $info);
|
||||
$this->assertArrayHasKey('filePath', $info);
|
||||
$this->assertArrayHasKey('className', $info);
|
||||
$this->assertArrayHasKey('source', $info);
|
||||
|
|
@ -221,7 +220,7 @@ class CodeParserTest extends TestCase
|
|||
$parser = new CodeParser($page);
|
||||
$info = $parser->parse();
|
||||
|
||||
$this->assertIsArray($info);
|
||||
$this->assertInternalType('array', $info);
|
||||
$this->assertArrayHasKey('filePath', $info);
|
||||
$this->assertArrayHasKey('className', $info);
|
||||
$this->assertArrayHasKey('source', $info);
|
||||
|
|
@ -256,7 +255,7 @@ class CodeParserTest extends TestCase
|
|||
$parser = new CodeParser($page);
|
||||
$info = $parser->parse();
|
||||
|
||||
$this->assertIsArray($info);
|
||||
$this->assertInternalType('array', $info);
|
||||
$this->assertArrayHasKey('filePath', $info);
|
||||
$this->assertArrayHasKey('className', $info);
|
||||
$this->assertArrayHasKey('source', $info);
|
||||
|
|
@ -285,7 +284,7 @@ class CodeParserTest extends TestCase
|
|||
$parser = new CodeParser($page);
|
||||
$info = $parser->parse();
|
||||
|
||||
$this->assertIsArray($info);
|
||||
$this->assertInternalType('array', $info);
|
||||
$this->assertArrayHasKey('filePath', $info);
|
||||
$this->assertArrayHasKey('className', $info);
|
||||
$this->assertArrayHasKey('source', $info);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use Cms\Classes\ComponentManager;
|
|||
|
||||
class ComponentManagerTest extends TestCase
|
||||
{
|
||||
public function setUp() : void
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use October\Rain\Halcyon\Model;
|
|||
|
||||
class ControllerTest extends TestCase
|
||||
{
|
||||
public function setUp() : void
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
|
|
@ -69,7 +69,7 @@ class ControllerTest extends TestCase
|
|||
$response = $controller->run('/some-page-that-doesnt-exist');
|
||||
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response);
|
||||
$content = $response->getContent();
|
||||
$this->assertIsString($content);
|
||||
$this->assertInternalType('string', $content);
|
||||
$this->assertEquals('<p>Page not found</p>', $content);
|
||||
}
|
||||
|
||||
|
|
@ -83,15 +83,16 @@ class ControllerTest extends TestCase
|
|||
$response = $controller->run('/');
|
||||
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response);
|
||||
$content = $response->getContent();
|
||||
$this->assertIsString($content);
|
||||
$this->assertInternalType('string', $content);
|
||||
$this->assertEquals('<h1>My Webpage</h1>', trim($content));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Cms\Classes\CmsException
|
||||
* @expectedExceptionMessage is not found
|
||||
*/
|
||||
public function testLayoutNotFound()
|
||||
{
|
||||
$this->expectException(\Cms\Classes\CmsException::class);
|
||||
$this->expectExceptionMessageMatches('/is\snot\sfound/');
|
||||
|
||||
$theme = Theme::load('test');
|
||||
$controller = new Controller($theme);
|
||||
$response = $controller->run('/no-layout');
|
||||
|
|
@ -145,11 +146,12 @@ class ControllerTest extends TestCase
|
|||
$this->assertEquals("<div>LAYOUT CONTENT <h1>This page is a subdirectory</h1></div>", $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Twig\Error\RuntimeError
|
||||
* @expectedExceptionMessage is not found
|
||||
*/
|
||||
public function testPartialNotFound()
|
||||
{
|
||||
$this->expectException(\Twig\Error\RuntimeError::class);
|
||||
$this->expectExceptionMessageMatches('/is\snot\sfound/');
|
||||
|
||||
$theme = Theme::load('test');
|
||||
$controller = new Controller($theme);
|
||||
$response = $controller->run('/no-partial')->getContent();
|
||||
|
|
@ -191,11 +193,12 @@ class ControllerTest extends TestCase
|
|||
return $requestMock;
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Cms\Classes\CmsException
|
||||
* @expectedExceptionMessage AJAX handler 'onNoHandler' was not found.
|
||||
*/
|
||||
public function testAjaxHandlerNotFound()
|
||||
{
|
||||
$this->expectException(\Cms\Classes\CmsException::class);
|
||||
$this->expectExceptionMessage('AJAX handler \'onNoHandler\' was not found.');
|
||||
|
||||
Request::swap($this->configAjaxRequestMock('onNoHandler', ''));
|
||||
|
||||
$theme = Theme::load('test');
|
||||
|
|
@ -203,11 +206,12 @@ class ControllerTest extends TestCase
|
|||
$controller->run('/ajax-test');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Cms\Classes\CmsException
|
||||
* @expectedExceptionMessage Invalid AJAX handler name: delete.
|
||||
*/
|
||||
public function testAjaxInvalidHandlerName()
|
||||
{
|
||||
$this->expectException(\Cms\Classes\CmsException::class);
|
||||
$this->expectExceptionMessage('Invalid AJAX handler name: delete.');
|
||||
|
||||
Request::swap($this->configAjaxRequestMock('delete'));
|
||||
|
||||
$theme = Theme::load('test');
|
||||
|
|
@ -215,11 +219,12 @@ class ControllerTest extends TestCase
|
|||
$controller->run('/ajax-test');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Cms\Classes\CmsException
|
||||
* @expectedExceptionMessage Invalid partial name: p:artial.
|
||||
*/
|
||||
public function testAjaxInvalidPartial()
|
||||
{
|
||||
$this->expectException(\Cms\Classes\CmsException::class);
|
||||
$this->expectExceptionMessage('Invalid partial name: p:artial.');
|
||||
|
||||
Request::swap($this->configAjaxRequestMock('onTest', 'p:artial'));
|
||||
|
||||
$theme = Theme::load('test');
|
||||
|
|
@ -227,11 +232,12 @@ class ControllerTest extends TestCase
|
|||
$controller->run('/ajax-test');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Cms\Classes\CmsException
|
||||
* @expectedExceptionMessage The partial 'partial' is not found.
|
||||
*/
|
||||
public function testAjaxPartialNotFound()
|
||||
{
|
||||
$this->expectException(\Cms\Classes\CmsException::class);
|
||||
$this->expectExceptionMessage('The partial \'partial\' is not found.');
|
||||
|
||||
Request::swap($this->configAjaxRequestMock('onTest', 'partial'));
|
||||
|
||||
$theme = Theme::load('test');
|
||||
|
|
@ -249,7 +255,7 @@ class ControllerTest extends TestCase
|
|||
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response);
|
||||
|
||||
$content = $response->getOriginalContent();
|
||||
$this->assertIsArray($content);
|
||||
$this->assertInternalType('array', $content);
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$this->assertCount(1, $content);
|
||||
$this->assertArrayHasKey('ajax-result', $content);
|
||||
|
|
@ -266,7 +272,7 @@ class ControllerTest extends TestCase
|
|||
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response);
|
||||
|
||||
$content = $response->getOriginalContent();
|
||||
$this->assertIsArray($content);
|
||||
$this->assertInternalType('array', $content);
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$this->assertCount(1, $content);
|
||||
$this->assertArrayHasKey('ajax-result', $content);
|
||||
|
|
@ -283,7 +289,7 @@ class ControllerTest extends TestCase
|
|||
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response);
|
||||
|
||||
$content = $response->getOriginalContent();
|
||||
$this->assertIsArray($content);
|
||||
$this->assertInternalType('array', $content);
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$this->assertCount(2, $content);
|
||||
$this->assertArrayHasKey('ajax-result', $content);
|
||||
|
|
@ -297,7 +303,7 @@ class ControllerTest extends TestCase
|
|||
$theme = Theme::load('test');
|
||||
$controller = new Controller($theme);
|
||||
$response = $controller->run('/with-component')->getContent();
|
||||
$page = self::getProtectedProperty($controller, 'page');
|
||||
$page = $this->readAttribute($controller, 'page');
|
||||
$this->assertArrayHasKey('testArchive', $page->components);
|
||||
|
||||
$component = $page->components['testArchive'];
|
||||
|
|
@ -325,7 +331,7 @@ ESC;
|
|||
$theme = Theme::load('test');
|
||||
$controller = new Controller($theme);
|
||||
$response = $controller->run('/with-components')->getContent();
|
||||
$page = self::getProtectedProperty($controller, 'page');
|
||||
$page = $this->readAttribute($controller, 'page');
|
||||
|
||||
$this->assertArrayHasKey('firstAlias', $page->components);
|
||||
$this->assertArrayHasKey('secondAlias', $page->components);
|
||||
|
|
@ -357,18 +363,19 @@ ESC;
|
|||
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response);
|
||||
|
||||
$content = $response->getOriginalContent();
|
||||
$this->assertIsArray($content);
|
||||
$this->assertInternalType('array', $content);
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$this->assertCount(1, $content);
|
||||
$this->assertArrayHasKey('ajax-result', $content);
|
||||
$this->assertEquals('page', $content['ajax-result']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException October\Rain\Exception\SystemException
|
||||
* @expectedExceptionMessage is not registered for the component
|
||||
*/
|
||||
public function testComponentClassNotFound()
|
||||
{
|
||||
$this->expectException(\October\Rain\Exception\SystemException::class);
|
||||
$this->expectExceptionMessageMatches('/is\snot\sregistered\sfor\sthe\scomponent/');
|
||||
|
||||
$theme = Theme::load('test');
|
||||
$controller = new Controller($theme);
|
||||
$response = $controller->run('/no-component-class')->getContent();
|
||||
|
|
@ -388,7 +395,7 @@ ESC;
|
|||
$theme = Theme::load('test');
|
||||
$controller = new Controller($theme);
|
||||
$response = $controller->run('/with-soft-component-class')->getContent();
|
||||
$page = $controller->getPage();
|
||||
$page = $this->readAttribute($controller, 'page');
|
||||
$this->assertArrayHasKey('testArchive', $page->components);
|
||||
|
||||
$component = $page->components['testArchive'];
|
||||
|
|
@ -414,7 +421,7 @@ ESC;
|
|||
$theme = Theme::load('test');
|
||||
$controller = new Controller($theme);
|
||||
$response = $controller->run('/with-soft-component-class-alias')->getContent();
|
||||
$page = $controller->getPage();
|
||||
$page = $this->readAttribute($controller, 'page');
|
||||
$this->assertArrayHasKey('someAlias', $page->components);
|
||||
|
||||
$component = $page->components['someAlias'];
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ class RouterTest extends TestCase
|
|||
{
|
||||
protected static $theme = null;
|
||||
|
||||
public function setUp() : void
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ class RouterTest extends TestCase
|
|||
$this->assertFalse($value);
|
||||
$map = $property->getValue($router);
|
||||
|
||||
$this->assertIsArray($map);
|
||||
$this->assertInternalType('array', $map);
|
||||
$this->assertGreaterThanOrEqual(4, count($map));
|
||||
|
||||
/*
|
||||
|
|
@ -52,7 +52,7 @@ class RouterTest extends TestCase
|
|||
$value = $method->invoke($router);
|
||||
$this->assertTrue($value);
|
||||
$map = $property->getValue($router);
|
||||
$this->assertIsArray($map);
|
||||
$this->assertInternalType('array', $map);
|
||||
$this->assertGreaterThanOrEqual(4, count($map));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use Cms\Classes\Theme;
|
|||
|
||||
class ThemeTest extends TestCase
|
||||
{
|
||||
public function setUp() : void
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ class ThemeTest extends TestCase
|
|||
|
||||
$pageCollection = $theme->listPages();
|
||||
$pages = array_values($pageCollection->all());
|
||||
$this->assertIsArray($pages);
|
||||
$this->assertInternalType('array', $pages);
|
||||
|
||||
$expectedPageNum = $this->countThemePages(base_path().'/tests/fixtures/themes/test/pages');
|
||||
$this->assertCount($expectedPageNum, $pages);
|
||||
|
|
@ -63,11 +63,12 @@ class ThemeTest extends TestCase
|
|||
$this->assertEquals('test', $activeTheme->getDirName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \October\Rain\Exception\SystemException
|
||||
* @expectedExceptionMessage The active theme is not set.
|
||||
*/
|
||||
public function testNoActiveTheme()
|
||||
{
|
||||
$this->expectException(\October\Rain\Exception\SystemException::class);
|
||||
$this->expectExceptionMessage('The active theme is not set.');
|
||||
|
||||
Config::set('cms.activeTheme', null);
|
||||
Theme::getActiveTheme();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use Database\Tester\Models\User;
|
|||
|
||||
class AttachManyModelTest extends PluginTestCase
|
||||
{
|
||||
public function setUp() : void
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Symfony\Component\HttpFoundation\File\UploadedFile;
|
|||
|
||||
class AttachOneModelTest extends PluginTestCase
|
||||
{
|
||||
public function setUp() : void
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use Database\Tester\Models\Author;
|
|||
|
||||
class BelongsToManyModelTest extends PluginTestCase
|
||||
{
|
||||
public function setUp() : void
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use Database\Tester\Models\Author;
|
|||
|
||||
class BelongsToModelTest extends PluginTestCase
|
||||
{
|
||||
public function setUp() : void
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use October\Rain\Database\Models\DeferredBinding;
|
|||
|
||||
class DeferredBindingTest extends PluginTestCase
|
||||
{
|
||||
public function setUp() : void
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use October\Rain\Database\Collection;
|
|||
|
||||
class HasManyModelTest extends PluginTestCase
|
||||
{
|
||||
public function setUp() : void
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
|
|
@ -63,6 +63,8 @@ class HasManyModelTest extends PluginTestCase
|
|||
|
||||
public function testGetRelationValue()
|
||||
{
|
||||
$this->markTestSkipped('Marked as \'skipped\' for further investigation');
|
||||
|
||||
Model::unguard();
|
||||
$author = Author::create(['name' => 'Stevie']);
|
||||
$post1 = Post::create(['title' => "First post", 'author_id' => $author->id]);
|
||||
|
|
|
|||
|
|
@ -1,54 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Database\Tester\Models\Author;
|
||||
use Database\Tester\Models\Country;
|
||||
use Database\Tester\Models\Post;
|
||||
use October\Rain\Database\Collection;
|
||||
|
||||
class HasManyThroughModelTest extends PluginTestCase
|
||||
{
|
||||
public function setUp() : void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
include_once base_path().'/tests/fixtures/plugins/database/tester/models/Post.php';
|
||||
include_once base_path().'/tests/fixtures/plugins/database/tester/models/Author.php';
|
||||
include_once base_path().'/tests/fixtures/plugins/database/tester/models/Country.php';
|
||||
|
||||
$this->runPluginRefreshCommand('Database.Tester');
|
||||
}
|
||||
|
||||
public function testGet()
|
||||
{
|
||||
Model::unguard();
|
||||
$country = Country::create(['name' => 'Australia']);
|
||||
$author1 = Author::create(['name' => 'Stevie', 'email' => 'stevie@email.tld']);
|
||||
$author2 = Author::create(['name' => 'Louie', 'email' => 'louie@email.tld']);
|
||||
$post1 = Post::create(['title' => "First post", 'description' => "Yay!!"]);
|
||||
$post2 = Post::create(['title' => "Second post", 'description' => "Woohoo!!"]);
|
||||
$post3 = Post::create(['title' => "Third post", 'description' => "Yipiee!!"]);
|
||||
$post4 = Post::make(['title' => "Fourth post", 'description' => "Hooray!!"]);
|
||||
Model::reguard();
|
||||
|
||||
// Set data
|
||||
$author1->country = $country;
|
||||
$author2->country = $country;
|
||||
|
||||
$author1->posts = new Collection([$post1, $post2]);
|
||||
$author2->posts = new Collection([$post3, $post4]);
|
||||
|
||||
$author1->save();
|
||||
$author2->save();
|
||||
|
||||
$country = Country::with([
|
||||
'posts'
|
||||
])->find($country->id);
|
||||
|
||||
$this->assertEquals([
|
||||
$post1->id,
|
||||
$post2->id,
|
||||
$post3->id,
|
||||
$post4->id
|
||||
], $country->posts->pluck('id')->toArray());
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ use Database\Tester\Models\Phone;
|
|||
|
||||
class HasOneModelTest extends PluginTestCase
|
||||
{
|
||||
public function setUp() : void
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,39 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Database\Tester\Models\Author;
|
||||
use Database\Tester\Models\Phone;
|
||||
use Database\Tester\Models\User;
|
||||
|
||||
class HasOneThroughModelTest extends PluginTestCase
|
||||
{
|
||||
public function setUp() : void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
include_once base_path().'/tests/fixtures/plugins/database/tester/models/User.php';
|
||||
include_once base_path().'/tests/fixtures/plugins/database/tester/models/Author.php';
|
||||
include_once base_path().'/tests/fixtures/plugins/database/tester/models/Phone.php';
|
||||
|
||||
$this->runPluginRefreshCommand('Database.Tester');
|
||||
}
|
||||
|
||||
public function testGet()
|
||||
{
|
||||
Model::unguard();
|
||||
$phone = Phone::create(['number' => '08 1234 5678']);
|
||||
$author = Author::create(['name' => 'Stevie', 'email' => 'stevie@email.tld']);
|
||||
$user = User::create(['name' => 'Stevie', 'email' => 'stevie@email.tld']);
|
||||
Model::reguard();
|
||||
|
||||
// Set data
|
||||
$author->phone = $phone;
|
||||
$author->user = $user;
|
||||
$author->save();
|
||||
|
||||
$user = User::with([
|
||||
'phone'
|
||||
])->find($user->id);
|
||||
|
||||
$this->assertEquals($phone->id, $user->phone->id);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ use Database\Tester\Models\Post;
|
|||
|
||||
class ModelTest extends PluginTestCase
|
||||
{
|
||||
public function setUp() : void
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
|
|
@ -23,11 +23,12 @@ class ModelTest extends PluginTestCase
|
|||
$this->assertEquals(1, $post->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Illuminate\Database\Eloquent\MassAssignmentException
|
||||
* @expectedExceptionMessage title
|
||||
*/
|
||||
public function testGuardedAttribute()
|
||||
{
|
||||
$this->expectException(\Illuminate\Database\Eloquent\MassAssignmentException::class);
|
||||
$this->expectExceptionMessageMatches('/title/');
|
||||
|
||||
Post::create(['title' => 'Hi!', 'slug' => 'authenticity']);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use October\Rain\Database\Collection;
|
|||
|
||||
class MorphManyModelTest extends PluginTestCase
|
||||
{
|
||||
public function setUp() : void
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue