Skip to content

Commit 5affc89

Browse files
authored
Own layout (#26)
* Start own layout. * Fix up frontend.
1 parent e6f1108 commit 5affc89

34 files changed

+1152
-404
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ bin/cake plugin load TestHelper --only-debug
4444

4545
This will also load the routes.
4646

47+
### Authorization Plugin
48+
49+
If you are using the [CakePHP Authorization plugin](https://github.com/cakephp/authorization), you need to configure TestHelper to bypass authorization checks. Add this to your `config/bootstrap.php`:
50+
51+
```php
52+
Configure::write('TestHelper.ignoreAuthorization', true);
53+
```
54+
55+
This is similar to how DebugKit handles authorization and is necessary to prevent `AuthorizationRequiredException` errors when accessing TestHelper routes.
56+
4757
### non-dev mode
4858
In certain apps it can be useful to have some of the helper functionality available also for staging and prod.
4959
Here you must make sure then to not load the routes, though:

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@
2222
"homepage": "https://github.com/dereuromark/cakephp-test-helper",
2323
"require": {
2424
"php": ">=8.1",
25-
"cakephp/cakephp": "^5.1.1",
26-
"dereuromark/cakephp-tools": "^3.0.0"
25+
"cakephp/cakephp": "^5.1.1"
2726
},
2827
"require-dev": {
28+
"dereuromark/cakephp-templating": "^0.2.12",
2929
"fig-r/psr2r-sniffer": "dev-master",
3030
"phpunit/phpunit": "^10.5 || ^11.5 || ^12.1",
3131
"sebastian/diff": "^5.0.0 || ^6.0.0 || ^7.0.0"

config/config.dist.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
<?php
22

33
return [
4-
'TestHelper' => [],
4+
'TestHelper' => [
5+
// Set to true to bypass authorization checks for TestHelper routes
6+
// when using the CakePHP Authorization plugin
7+
'ignoreAuthorization' => true,
8+
],
59

610
'Icon' => [
711
'map' => [

docs/README.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ Browse `/test-helper` to see all functionality available.
88
- Run tests and display results or coverage in backend.
99

1010
## Configuration
11-
- TestHelper.command: If you need a custom phpunit command to run with.
12-
Both `php phpunit.phar` and `vendor/bin/phpunit` work out of the box.
13-
- TestHelper.coverage: Set to `xdebug` if you have this enabled, it otherwise uses pcov by default.
11+
- **TestHelper.command**: If you need a custom phpunit command to run with. Both `php phpunit.phar` and `vendor/bin/phpunit` work out of the box.
12+
- **TestHelper.coverage**: Set to `xdebug` if you have this enabled, it otherwise uses pcov by default.
13+
- **TestHelper.ignoreAuthorization**: Set to `true` to bypass authorization checks when using the CakePHP Authorization plugin. Default: `false`.
1414

1515
### Your own template
1616
The default template ships with bootstrap (5) and fontawesome icons.
@@ -21,6 +21,16 @@ Overwrite the `test_cases` element if you want to support e.g. foundation and th
2121

2222
## Troubleshooting
2323

24+
### Authorization Plugin Errors
25+
26+
If you are using the [CakePHP Authorization plugin](https://github.com/cakephp/authorization) and encounter `AuthorizationRequiredException` errors when accessing TestHelper routes, add this to your `config/bootstrap.php`:
27+
28+
```php
29+
Configure::write('TestHelper.ignoreAuthorization', true);
30+
```
31+
32+
This will skip authorization checks for all TestHelper routes, similar to how DebugKit handles authorization.
33+
2434
### Generated code coverage is black&white
2535
If the assets don't work, make sure your Nginx/Apache (like CakeBox Vagrant VM by default) doesn't block hidden files.
2636

src/Command/FixtureCheckCommand.php

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace TestHelper\Command;
44

5+
use Cake\Command\Command;
56
use Cake\Console\Arguments;
67
use Cake\Console\ConsoleIo;
78
use Cake\Console\ConsoleOptionParser;
@@ -11,8 +12,6 @@
1112
use Cake\Datasource\ConnectionManager;
1213
use Cake\Error\Debugger;
1314
use Cake\ORM\Table;
14-
use Shim\Command\Command;
15-
use Shim\Filesystem\Folder;
1615

1716
if (!defined('TESTS')) {
1817
define('TESTS', ROOT . DS . 'tests' . DS);
@@ -58,6 +57,16 @@ class FixtureCheckCommand extends Command {
5857
*/
5958
protected array $_missingFields = [];
6059

60+
/**
61+
* @var \Cake\Console\Arguments
62+
*/
63+
protected Arguments $args;
64+
65+
/**
66+
* @var \Cake\Console\ConsoleIo
67+
*/
68+
protected ConsoleIo $io;
69+
6170
/**
6271
* @inheritDoc
6372
*/
@@ -76,6 +85,9 @@ public function initialize(): void {
7685
public function execute(Arguments $args, ConsoleIo $io) {
7786
parent::execute($args, $io);
7887

88+
$this->args = $args;
89+
$this->io = $io;
90+
7991
$fixtures = $this->_getFixtures();
8092
$this->io->out(count($fixtures) . ' fixtures found, processing:');
8193
$this->io->out('');
@@ -439,12 +451,18 @@ protected function _getFixtureFiles() {
439451
$fixtureFolder = Plugin::path($plugin) . 'tests' . DS . 'Fixture' . DS;
440452
}
441453

442-
$folder = new Folder($fixtureFolder);
443-
$content = $folder->read();
444-
445454
$fixtures = [];
446-
foreach ($content[1] as $file) {
447-
$fixture = substr($file, 0, -4);
455+
if (!is_dir($fixtureFolder)) {
456+
return $fixtures;
457+
}
458+
459+
$files = array_values(array_diff(scandir($fixtureFolder), ['.', '..']));
460+
foreach ($files as $file) {
461+
if (!is_file($fixtureFolder . $file) || pathinfo($file, PATHINFO_EXTENSION) !== 'php') {
462+
continue;
463+
}
464+
465+
$fixture = pathinfo($file, PATHINFO_FILENAME);
448466
if (substr($fixture, -7) !== 'Fixture') {
449467
continue;
450468
}

src/Controller/Component/PluginsComponent.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ protected function addProperty(string $content, string $part, array $result): st
245245

246246
$pos = null;
247247
foreach ($pieces as $i => $piece) {
248-
if (strpos($piece, 'class Plugin extends BasePlugin') === false) {
248+
if (!str_contains($piece, 'class Plugin extends BasePlugin')) {
249249
continue;
250250
}
251251

@@ -264,7 +264,7 @@ protected function addProperty(string $content, string $part, array $result): st
264264
$indentation . '/**',
265265
$indentation . ' * @var bool',
266266
$indentation . ' */',
267-
$indentation . 'protected $' . $part . 'Enabled = ' . ($result[$part . 'Exists'] ? 'true' : 'false') . ';',
267+
$indentation . 'protected $' . $part . 'Enabled = ' . (!empty($result[$part . 'Exists']) ? 'true' : 'false') . ';',
268268
];
269269
if (trim($pieces[$pos + 1]) !== '{') {
270270
array_unshift($add, '');

src/Controller/Component/TestGeneratorComponent.php

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
use Cake\Controller\Component;
66
use Cake\Core\Plugin;
7-
use Shim\Filesystem\Folder;
7+
use DirectoryIterator;
88

99
/**
1010
* @property \Cake\Controller\Component\FlashComponent $Flash
@@ -107,19 +107,30 @@ public function generateFixture($name, $plugin, array $options = []) {
107107
public function getFiles(array $folders) {
108108
$names = [];
109109
foreach ($folders as $folder) {
110-
$folderContent = (new Folder($folder))->read(Folder::SORT_NAME, true);
111-
112-
foreach ($folderContent[1] as $file) {
113-
$name = pathinfo($file, PATHINFO_FILENAME);
114-
$names[] = $name;
110+
if (!is_dir($folder)) {
111+
continue;
115112
}
116113

117-
foreach ($folderContent[0] as $subFolder) {
118-
$folderContent = (new Folder($folder . $subFolder))->read(Folder::SORT_NAME, true);
114+
// Get files in the main folder
115+
$iterator = new DirectoryIterator($folder);
116+
foreach ($iterator as $fileInfo) {
117+
if ($fileInfo->isFile() && $fileInfo->getExtension() === 'php') {
118+
$name = $fileInfo->getBasename('.php');
119+
$names[] = $name;
120+
}
121+
}
119122

120-
foreach ($folderContent[1] as $file) {
121-
$name = pathinfo($file, PATHINFO_FILENAME);
122-
$names[] = $subFolder . '/' . $name;
123+
// Get files in subdirectories
124+
foreach ($iterator as $fileInfo) {
125+
if ($fileInfo->isDir() && !$fileInfo->isDot()) {
126+
$subFolder = $fileInfo->getFilename();
127+
$subIterator = new DirectoryIterator($folder . $subFolder);
128+
foreach ($subIterator as $subFileInfo) {
129+
if ($subFileInfo->isFile() && $subFileInfo->getExtension() === 'php') {
130+
$name = $subFileInfo->getBasename('.php');
131+
$names[] = $subFolder . '/' . $name;
132+
}
133+
}
123134
}
124135
}
125136
}

src/Controller/DemoController.php

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,7 @@
22

33
namespace TestHelper\Controller;
44

5-
use App\Controller\AppController;
6-
use Cake\Event\EventInterface;
7-
8-
class DemoController extends AppController {
9-
10-
/**
11-
* @param \Cake\Event\EventInterface $event
12-
* @return void
13-
*/
14-
public function beforeFilter(EventInterface $event): void {
15-
parent::beforeFilter($event);
16-
17-
if ($this->components()->has('Security')) {
18-
$this->components()->get('Security')->setConfig('validatePost', false);
19-
}
20-
21-
if ($this->components()->has('Auth') && method_exists($this->components()->get('Auth'), 'allow')) {
22-
$this->components()->get('Auth')->allow();
23-
} elseif ($this->components()->has('Authentication') && method_exists($this->components()->get('Authentication'), 'addUnauthenticatedActions')) {
24-
$this->components()->get('Authentication')->addUnauthenticatedActions(['index']);
25-
}
26-
}
5+
class DemoController extends TestHelperAppController {
276

287
/**
298
* @return \Cake\Http\Response|null|void

src/Controller/MigrationsController.php

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,15 @@
22

33
namespace TestHelper\Controller;
44

5-
use App\Controller\AppController;
65
use Cake\Datasource\ConnectionManager;
76
use Cake\Event\EventInterface;
87
use SebastianBergmann\Diff\Differ;
98
use SebastianBergmann\Diff\Output\DiffOnlyOutputBuilder;
10-
use Shim\Filesystem\Folder;
119

1210
/**
1311
* @property \TestHelper\Controller\Component\MigrationsComponent $Migrations
1412
*/
15-
class MigrationsController extends AppController {
13+
class MigrationsController extends TestHelperAppController {
1614

1715
protected ?string $defaultTable = '';
1816

@@ -32,16 +30,6 @@ public function initialize(): void {
3230
public function beforeFilter(EventInterface $event): void {
3331
parent::beforeFilter($event);
3432

35-
if ($this->components()->has('Security')) {
36-
$this->components()->get('Security')->setConfig('validatePost', false);
37-
}
38-
39-
if ($this->components()->has('Auth') && method_exists($this->components()->get('Auth'), 'allow')) {
40-
$this->components()->get('Auth')->allow();
41-
} elseif ($this->components()->has('Authentication') && method_exists($this->components()->get('Authentication'), 'addUnauthenticatedActions')) {
42-
$this->components()->get('Authentication')->addUnauthenticatedActions(['index']);
43-
}
44-
4533
if (!file_exists(ROOT . DS . 'vendor/cakephp/migrations/composer.json')) {
4634
$this->Flash->error('It seems the Migrations plugin is missing.');
4735

@@ -91,8 +79,13 @@ public function tmpDb() {
9179
* @return \Cake\Http\Response|null|void
9280
*/
9381
public function snapshot() {
94-
$x = (new Folder(CONFIG . 'MigrationsTmp'))->read();
95-
$files = $x[1] ?? [];
82+
$files = [];
83+
$migrationsTmpPath = CONFIG . 'MigrationsTmp';
84+
if (is_dir($migrationsTmpPath)) {
85+
$files = array_values(array_diff(scandir($migrationsTmpPath), ['.', '..']));
86+
$files = array_filter($files, fn ($file) => is_file($migrationsTmpPath . DS . $file));
87+
}
88+
9689
if ($this->request->is('post') && $this->request->getData('clear')) {
9790
foreach ($files as $file) {
9891
unlink(CONFIG . 'MigrationsTmp' . DS . $file);
@@ -131,8 +124,12 @@ public function snapshotTest() {
131124
$database = $dbConfig['database'] ?? [];
132125
$tmpDatabase = $database . '_tmp';
133126

134-
$x = (new Folder(CONFIG . 'MigrationsTmp'))->read();
135-
$files = $x[1] ?? [];
127+
$files = [];
128+
$migrationsTmpPath = CONFIG . 'MigrationsTmp';
129+
if (is_dir($migrationsTmpPath)) {
130+
$files = array_values(array_diff(scandir($migrationsTmpPath), ['.', '..']));
131+
$files = array_filter($files, fn ($file) => is_file($migrationsTmpPath . DS . $file));
132+
}
136133

137134
if ($this->request->is('post') && $this->request->getData('test')) {
138135
$connectionConfig = [
@@ -185,8 +182,12 @@ public function seedTest() {
185182
$database = $dbConfig['database'] ?? [];
186183
$tmpDatabase = $database . '_tmp';
187184

188-
$x = (new Folder(CONFIG . 'Seeds'))->read();
189-
$seeds = $x[1] ?? [];
185+
$seeds = [];
186+
$seedsPath = CONFIG . 'Seeds';
187+
if (is_dir($seedsPath)) {
188+
$seeds = array_values(array_diff(scandir($seedsPath), ['.', '..']));
189+
$seeds = array_filter($seeds, fn ($file) => is_file($seedsPath . DS . $file));
190+
}
190191

191192
if ($this->request->is('post') && $this->request->getData('test')) {
192193
$command = 'bin/cake migrations seed -c "mysql://[email protected]/' . $tmpDatabase . '"';
@@ -213,16 +214,25 @@ public function confirm() {
213214
$tmpDatabase = $database . '_tmp';
214215

215216
if ($this->request->is('post') && $this->request->getData('confirm')) {
216-
$folder = (new Folder(CONFIG . 'Migrations'))->read();
217-
$files = $folder[1] ?? [];
218-
foreach ($files as $file) {
219-
unlink(CONFIG . 'Migrations' . DS . $file);
217+
// Remove old migration files
218+
$migrationsPath = CONFIG . 'Migrations';
219+
if (is_dir($migrationsPath)) {
220+
$files = array_values(array_diff(scandir($migrationsPath), ['.', '..']));
221+
$files = array_filter($files, fn ($file) => is_file($migrationsPath . DS . $file));
222+
foreach ($files as $file) {
223+
unlink($migrationsPath . DS . $file);
224+
}
220225
}
221-
$folder = (new Folder(CONFIG . 'MigrationsTmp'))->read();
222-
$files = $folder[1] ?? [];
223-
foreach ($files as $file) {
224-
copy(CONFIG . 'MigrationsTmp' . DS . $file, CONFIG . 'Migrations' . DS . $file);
225-
unlink(CONFIG . 'MigrationsTmp' . DS . $file);
226+
227+
// Copy tmp migration files to Migrations folder
228+
$migrationsTmpPath = CONFIG . 'MigrationsTmp';
229+
if (is_dir($migrationsTmpPath)) {
230+
$files = array_values(array_diff(scandir($migrationsTmpPath), ['.', '..']));
231+
$files = array_filter($files, fn ($file) => is_file($migrationsTmpPath . DS . $file));
232+
foreach ($files as $file) {
233+
copy($migrationsTmpPath . DS . $file, $migrationsPath . DS . $file);
234+
unlink($migrationsTmpPath . DS . $file);
235+
}
226236
}
227237

228238
/** @var \Cake\Database\Connection $connection */

0 commit comments

Comments
 (0)