diff --git a/.editorconfig b/.editorconfig
index 382eeefd..d26a83c1 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -11,6 +11,12 @@ indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true
+[*.neon]
+indent_style = tab
+
+[*.neon.dist]
+indent_style = tab
+
[*.yml]
indent_size = 2
diff --git a/.phive/phars.xml b/.phive/phars.xml
index 4d447d1a..40973f75 100644
--- a/.phive/phars.xml
+++ b/.phive/phars.xml
@@ -1,4 +1,4 @@
-
+
diff --git a/phpstan.neon b/phpstan.neon
index 7f9e3084..49655075 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -2,12 +2,10 @@ includes:
- phpstan-baseline.neon
parameters:
- level: 6
- paths:
- - src/
- bootstrapFiles:
- - tests/bootstrap.php
- ignoreErrors:
- - identifier: missingType.iterableValue
- - identifier: missingType.generics
- - identifier: method.childReturnType
+ level: 8
+ paths:
+ - src/
+ bootstrapFiles:
+ - tests/bootstrap.php
+ ignoreErrors:
+ - identifier: missingType.iterableValue
diff --git a/src/BakePlugin.php b/src/BakePlugin.php
index 0b02eaad..d4d225f6 100644
--- a/src/BakePlugin.php
+++ b/src/BakePlugin.php
@@ -26,7 +26,6 @@
use Cake\Http\BaseApplication;
use DirectoryIterator;
use ReflectionClass;
-use ReflectionException;
/**
* Plugin class for bake
@@ -140,11 +139,11 @@ protected function findInPath(string $namespace, string $path): array
$class = $namespace . $item->getBasename('.php');
if (!$hasSubfolder) {
- try {
- $reflection = new ReflectionClass($class);
- } catch (ReflectionException) {
+ if (!class_exists($class)) {
continue;
}
+
+ $reflection = new ReflectionClass($class);
if (!$reflection->isInstantiable() || !$reflection->isSubclassOf(BakeCommand::class)) {
continue;
}
diff --git a/src/CodeGen/CodeParser.php b/src/CodeGen/CodeParser.php
index c48c8eec..9042f1bf 100644
--- a/src/CodeGen/CodeParser.php
+++ b/src/CodeGen/CodeParser.php
@@ -81,7 +81,11 @@ public function parseFile(string $code): ?ParsedFile
{
$this->fileText = $code;
try {
- $this->traverser->traverse($this->parser->parse($code));
+ $ast = $this->parser->parse($code);
+ if ($ast === null) {
+ return null;
+ }
+ $this->traverser->traverse($ast);
} catch (Error $e) {
throw new ParseException($e->getMessage(), null, $e);
}
@@ -172,7 +176,11 @@ public function enterNode(Node $node)
throw new ParseException('Multiple constants per line are not supported, update your file');
}
- $name = (string)current($constant->consts)->name;
+ $const = current($constant->consts);
+ if ($const === false) {
+ continue;
+ }
+ $name = (string)$const->name;
$constants[$name] = $this->getNodeCode($constant);
}
@@ -182,7 +190,11 @@ public function enterNode(Node $node)
throw new ParseException('Multiple properties per line are not supported, update your file');
}
- $name = (string)current($property->props)->name;
+ $prop = current($property->props);
+ if ($prop === false) {
+ continue;
+ }
+ $name = (string)$prop->name;
$properties[$name] = $this->getNodeCode($property);
}
diff --git a/src/CodeGen/ColumnTypeExtractor.php b/src/CodeGen/ColumnTypeExtractor.php
index 0c504cef..9df1df08 100644
--- a/src/CodeGen/ColumnTypeExtractor.php
+++ b/src/CodeGen/ColumnTypeExtractor.php
@@ -73,6 +73,9 @@ public function extract(string $code): array
// Wrap code in a dummy class if needed for parsing
$wrappedCode = "parser->parse($wrappedCode);
+ if ($ast === null) {
+ return [];
+ }
$traverser = new NodeTraverser();
$traverser->addVisitor($this);
@@ -144,8 +147,13 @@ protected function processMethodCall(MethodCall $methodCall): void
) {
// Extract the column name and type expression
if (count($methodCall->args) >= 2) {
- $columnArg = $methodCall->args[0]->value;
- $typeArg = $methodCall->args[1]->value;
+ $columnArgNode = $methodCall->args[0];
+ $typeArgNode = $methodCall->args[1];
+ if (!$columnArgNode instanceof Node\Arg || !$typeArgNode instanceof Node\Arg) {
+ return;
+ }
+ $columnArg = $columnArgNode->value;
+ $typeArg = $typeArgNode->value;
// Get column name
$columnName = $this->getStringValue($columnArg);
@@ -199,7 +207,11 @@ protected function getTypeExpression(Node $node): ?string
if ($className === 'EnumType' || str_ends_with($className, '\\EnumType')) {
if ($methodName === 'from' && count($node->args) > 0) {
// Extract the enum class name
- $arg = $node->args[0]->value;
+ $argNode = $node->args[0];
+ if (!$argNode instanceof Node\Arg) {
+ return null;
+ }
+ $arg = $argNode->value;
if ($arg instanceof Node\Expr\ClassConstFetch) {
if (
$arg->class instanceof Node\Name &&
diff --git a/src/Command/BakeCommand.php b/src/Command/BakeCommand.php
index 482e16c7..f5ade6a2 100644
--- a/src/Command/BakeCommand.php
+++ b/src/Command/BakeCommand.php
@@ -112,6 +112,7 @@ protected function _getName(string $name): string
*/
protected function getPrefix(Arguments $args): string
{
+ /** @var string|null $prefix */
$prefix = $args->getOption('prefix');
if (!$prefix) {
return '';
@@ -225,7 +226,12 @@ protected function isValidColumnName(string $name): bool
protected function parseFile(string $path): ?ParsedFile
{
if (file_exists($path)) {
- return (new CodeParser())->parseFile(file_get_contents($path));
+ $contents = file_get_contents($path);
+ if ($contents === false) {
+ return null;
+ }
+
+ return (new CodeParser())->parseFile($contents);
}
return null;
diff --git a/src/Command/CommandCommand.php b/src/Command/CommandCommand.php
index 580508e1..54cc7ae5 100644
--- a/src/Command/CommandCommand.php
+++ b/src/Command/CommandCommand.php
@@ -69,7 +69,7 @@ public function templateData(Arguments $arguments): array
$data['command_name'] = Inflector::underscore(str_replace(
'.',
' ',
- $arguments->getArgument('name'),
+ $arguments->getArgument('name') ?? '',
));
return $data;
diff --git a/src/Command/ControllerCommand.php b/src/Command/ControllerCommand.php
index c78bc5df..2b88cf0f 100644
--- a/src/Command/ControllerCommand.php
+++ b/src/Command/ControllerCommand.php
@@ -84,7 +84,7 @@ public function bake(string $controllerName, Arguments $args, ConsoleIo $io): vo
$actions = ['index', 'view', 'add', 'edit', 'delete'];
}
if ($args->getOption('actions')) {
- $actions = array_map('trim', explode(',', $args->getOption('actions')));
+ $actions = array_map('trim', explode(',', (string)$args->getOption('actions')));
$actions = array_filter($actions);
}
if (!$args->getOption('actions') && Plugin::isLoaded('Authentication') && $controllerName === 'Users') {
@@ -221,7 +221,7 @@ public function getComponents(Arguments $args): array
{
$components = [];
if ($args->getOption('components')) {
- $components = explode(',', $args->getOption('components'));
+ $components = explode(',', (string)$args->getOption('components'));
$components = array_values(array_filter(array_map('trim', $components)));
} else {
if (Plugin::isLoaded('Authorization')) {
@@ -242,7 +242,7 @@ public function getHelpers(Arguments $args): array
{
$helpers = [];
if ($args->getOption('helpers')) {
- $helpers = explode(',', $args->getOption('helpers'));
+ $helpers = explode(',', (string)$args->getOption('helpers'));
$helpers = array_values(array_filter(array_map('trim', $helpers)));
}
diff --git a/src/Command/FixtureAllCommand.php b/src/Command/FixtureAllCommand.php
index 83de359c..0b9b594d 100644
--- a/src/Command/FixtureAllCommand.php
+++ b/src/Command/FixtureAllCommand.php
@@ -83,7 +83,7 @@ public function execute(Arguments $args, ConsoleIo $io): ?int
$this->extractCommonProperties($args);
/** @var \Cake\Database\Connection $connection */
- $connection = ConnectionManager::get($args->getOption('connection') ?? 'default');
+ $connection = ConnectionManager::get((string)($args->getOption('connection') ?: 'default'));
$scanner = new TableScanner($connection);
$fixture = new FixtureCommand();
diff --git a/src/Command/FixtureCommand.php b/src/Command/FixtureCommand.php
index 94908eea..5ccdec22 100644
--- a/src/Command/FixtureCommand.php
+++ b/src/Command/FixtureCommand.php
@@ -122,7 +122,7 @@ public function execute(Arguments $args, ConsoleIo $io): ?int
return static::CODE_SUCCESS;
}
- $table = $args->getOption('table') ?? '';
+ $table = (string)$args->getOption('table');
$model = $this->_camelize($name);
$this->bake($model, $table, $args, $io);
@@ -285,16 +285,19 @@ protected function _generateSchema(TableSchemaInterface $table): string
{
$cols = $indexes = $constraints = [];
foreach ($table->columns() as $field) {
+ /** @var array $fieldData */
$fieldData = $table->getColumn($field);
$properties = implode(', ', $this->_values($fieldData));
$cols[] = " '$field' => [$properties],";
}
foreach ($table->indexes() as $index) {
+ /** @var array $fieldData */
$fieldData = $table->getIndex($index);
$properties = implode(', ', $this->_values($fieldData));
$indexes[] = " '$index' => [$properties],";
}
foreach ($table->constraints() as $index) {
+ /** @var array $fieldData */
$fieldData = $table->getConstraint($index);
$properties = implode(', ', $this->_values($fieldData));
$constraints[] = " '$index' => [$properties],";
@@ -360,6 +363,7 @@ protected function _generateRecords(TableSchemaInterface $table, int $recordCoun
for ($i = 0; $i < $recordCount; $i++) {
$record = [];
foreach ($table->columns() as $field) {
+ /** @var array $fieldInfo */
$fieldInfo = $table->getColumn($field);
$insert = '';
switch ($fieldInfo['type']) {
diff --git a/src/Command/ModelCommand.php b/src/Command/ModelCommand.php
index 1fb504d4..33ec59f5 100644
--- a/src/Command/ModelCommand.php
+++ b/src/Command/ModelCommand.php
@@ -392,7 +392,8 @@ public function findBelongsTo(Table $model, array $associations, ?Arguments $arg
if ($className && $className !== $tmpModelName) {
$assoc['className'] = $className;
}
- if ($schema->getColumn($fieldName)['null'] === false) {
+ $columnInfo = $schema->getColumn($fieldName);
+ if ($columnInfo !== null && ($columnInfo['null'] ?? true) === false) {
$assoc['joinType'] = 'INNER';
}
}
@@ -484,8 +485,9 @@ public function hasUniqueConstraintFor(TableSchemaInterface $schema, string $key
foreach ($schema->constraints() as $constraint) {
$constraintInfo = $schema->getConstraint($constraint);
if (
- $constraintInfo['type'] === TableSchema::CONSTRAINT_UNIQUE &&
- $constraintInfo['columns'] === [$keyField]
+ $constraintInfo !== null &&
+ ($constraintInfo['type'] ?? null) === TableSchema::CONSTRAINT_UNIQUE &&
+ ($constraintInfo['columns'] ?? []) === [$keyField]
) {
return true;
}
@@ -663,7 +665,7 @@ public function getDisplayField(Table $model, Arguments $args): array|string
public function getPrimaryKey(Table $model, Arguments $args): array
{
if ($args->getOption('primary-key')) {
- $fields = explode(',', $args->getOption('primary-key'));
+ $fields = explode(',', (string)$args->getOption('primary-key'));
return array_values(array_filter(array_map('trim', $fields)));
}
@@ -702,6 +704,7 @@ public function getEntityPropertySchema(Table $model): array
$schema = $model->getSchema();
foreach ($schema->columns() as $column) {
+ /** @var array $columnSchema */
$columnSchema = $schema->getColumn($column);
$properties[$column] = [
@@ -757,7 +760,7 @@ public function getFields(Table $table, Arguments $args): array|false|null
return false;
}
if ($args->getOption('fields')) {
- $fields = explode(',', $args->getOption('fields'));
+ $fields = explode(',', (string)$args->getOption('fields'));
return array_values(array_filter(array_map('trim', $fields)));
}
@@ -786,7 +789,7 @@ public function getHiddenFields(Table $model, Arguments $args): array
return [];
}
if ($args->getOption('hidden')) {
- $fields = explode(',', $args->getOption('hidden'));
+ $fields = explode(',', (string)$args->getOption('hidden'));
return array_values(array_filter(array_map('trim', $fields)));
}
@@ -932,6 +935,7 @@ public function fieldValidation(
}
foreach ($schema->constraints() as $constraint) {
+ /** @var array $constraint */
$constraint = $schema->getConstraint($constraint);
if (!in_array($fieldName, $constraint['columns'] ?? [], true) || count($constraint['columns']) > 1) {
continue;
@@ -1010,6 +1014,7 @@ public function getRules(Table $model, array $associations, Arguments $args): ar
$uniqueConstraintsColumns = [];
foreach ($schema->constraints() as $name) {
+ /** @var array $constraint */
$constraint = $schema->getConstraint($name);
if ($constraint['type'] !== TableSchema::CONSTRAINT_UNIQUE) {
continue;
@@ -1476,6 +1481,7 @@ protected function possibleEnumFields(TableSchemaInterface $schema): array
$fields = [];
foreach ($schema->columns() as $column) {
+ /** @var array $columnSchema */
$columnSchema = $schema->getColumn($column);
if (str_starts_with($columnSchema['type'], 'enum-')) {
$fields[] = $column;
@@ -1502,6 +1508,7 @@ protected function getEnumDefinitions(TableSchemaInterface $schema): array
$enums = [];
foreach ($schema->columns() as $column) {
+ /** @var array $columnSchema */
$columnSchema = $schema->getColumn($column);
if (
!in_array($columnSchema['type'], ['string', 'integer', 'tinyinteger', 'smallinteger'], true)
diff --git a/src/Command/PluginCommand.php b/src/Command/PluginCommand.php
index 10b1b84d..551d10de 100644
--- a/src/Command/PluginCommand.php
+++ b/src/Command/PluginCommand.php
@@ -65,7 +65,7 @@ public function execute(Arguments $args, ConsoleIo $io): ?int
$plugin = implode('/', array_map([Inflector::class, 'camelize'], $parts));
if ($args->getOption('standalone-path')) {
- $this->path = $args->getOption('standalone-path');
+ $this->path = (string)$args->getOption('standalone-path');
$this->path = rtrim($this->path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
$this->isVendor = true;
@@ -105,7 +105,8 @@ public function bake(string $plugin, Arguments $args, ConsoleIo $io): ?bool
{
if (!$this->isVendor) {
$pathOptions = App::path('plugins');
- $this->path = current($pathOptions);
+ $currentPath = current($pathOptions);
+ $this->path = $currentPath !== false ? $currentPath : '';
if (count($pathOptions) > 1) {
$this->findPath($pathOptions, $io);
@@ -130,8 +131,13 @@ public function bake(string $plugin, Arguments $args, ConsoleIo $io): ?bool
}
$composer = $this->findComposer($args, $io);
+ if ($composer === false) {
+ $io->error('Could not find composer executable.');
+ $this->abort();
+ }
try {
+ /** @var non-empty-string $cwd */
$cwd = getcwd();
// Windows makes running multiple commands at once hard.
@@ -200,7 +206,7 @@ protected function _generateFiles(
$package = Inflector::dasherize($vendor) . '/' . Inflector::dasherize($name);
$composerConfig = json_decode(
- file_get_contents(ROOT . DS . 'composer.json'),
+ (string)file_get_contents(ROOT . DS . 'composer.json'),
true,
);
@@ -221,7 +227,7 @@ protected function _generateFiles(
$paths = [];
if ($args->hasOption('theme')) {
- $paths[] = Plugin::templatePath($args->getOption('theme'));
+ $paths[] = Plugin::templatePath((string)$args->getOption('theme'));
}
$paths = array_merge($paths, Configure::read('App.paths.templates'));
@@ -392,7 +398,7 @@ public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionPar
*
* @param \Cake\Console\Arguments $args The command arguments.
* @param \Cake\Console\ConsoleIo $io The console io
- * @return string|bool Either the path to composer or false if it cannot be found.
+ * @return string|false Either the path to composer or false if it cannot be found.
*/
public function findComposer(Arguments $args, ConsoleIo $io): string|bool
{
@@ -404,7 +410,7 @@ public function findComposer(Arguments $args, ConsoleIo $io): string|bool
}
}
$composer = false;
- $path = env('PATH');
+ $path = (string)env('PATH');
if (!empty($path)) {
$paths = explode(PATH_SEPARATOR, $path);
$composer = $this->_searchPath($paths, $io);
@@ -418,7 +424,7 @@ public function findComposer(Arguments $args, ConsoleIo $io): string|bool
*
* @param array $path The paths to search.
* @param \Cake\Console\ConsoleIo $io The console io
- * @return string|bool
+ * @return string|false
*/
protected function _searchPath(array $path, ConsoleIo $io): string|bool
{
diff --git a/src/Command/TemplateCommand.php b/src/Command/TemplateCommand.php
index f467c1aa..239eb576 100644
--- a/src/Command/TemplateCommand.php
+++ b/src/Command/TemplateCommand.php
@@ -102,7 +102,15 @@ public function initialize(): void
{
parent::initialize();
- $this->path = current(App::path('templates'));
+ $templatePaths = App::path('templates');
+ if ($templatePaths === []) {
+ throw new RuntimeException(
+ 'Could not read template paths. ' .
+ 'Ensure `App.paths.templates` is defined in your application configuration.',
+ );
+ }
+
+ $this->path = current($templatePaths);
}
/**
@@ -132,8 +140,7 @@ public function execute(Arguments $args, ConsoleIo $io): ?int
$template = $args->getArgument('template');
$action = $args->getArgument('action');
- $controller = $args->getOption('controller');
- $this->controller($args, $name, $controller);
+ $this->controller($args, $name, (string)$args->getOption('controller'));
$this->model($name);
if ($template && $action === null) {
diff --git a/src/Command/TestCommand.php b/src/Command/TestCommand.php
index f48e99e2..0231bf88 100644
--- a/src/Command/TestCommand.php
+++ b/src/Command/TestCommand.php
@@ -110,7 +110,7 @@ public function execute(Arguments $args, ConsoleIo $io): ?int
return null;
}
- $type = $this->normalize($args->getArgument('type'));
+ $type = $this->normalize((string)$args->getArgument('type'));
if ($args->getOption('all')) {
$this->_bakeAll($type, $args, $io);
@@ -122,7 +122,7 @@ public function execute(Arguments $args, ConsoleIo $io): ?int
return null;
}
- $name = $args->getArgument('name');
+ $name = (string)$args->getArgument('name');
$name = $this->_getName($name);
$result = $this->bake($type, $name, $args, $io);
@@ -225,8 +225,9 @@ protected function _getClassOptions(string $namespace): array
foreach ($files as $fileObj) {
if ($fileObj->isFile() && $fileObj->getFileName() !== 'Application.php') {
// Build the namespace path relative to App directory
+ /** @var string $relativePath */
$relativePath = str_replace($base, '', $fileObj->getPath());
- $relativePath = trim(str_replace(DS, '\\', $relativePath), '\\');
+ $relativePath = trim(str_replace(DIRECTORY_SEPARATOR, '\\', $relativePath), '\\');
$className = substr($fileObj->getFileName(), 0, -4) ?: '';
if ($relativePath) {
$classes[] = $relativePath . '\\' . $className;
@@ -272,7 +273,7 @@ public function bake(string $type, string $className, Arguments $args, ConsoleIo
$io->out(" bin/cake bake test class '{$className}'");
$io->out('');
$io->out('Or specify without the base namespace:');
- $io->out(' bin/cake bake test class YourNamespace\\ClassName');
+ $io->out(' bin/cake bake test class YourNamespace\ClassName');
return static::CODE_ERROR;
}
@@ -299,12 +300,14 @@ public function bake(string $type, string $className, Arguments $args, ConsoleIo
if ($hasFixtureFactories) {
$io->info('Fixture Factories plugin detected - skipping fixture property generation.');
} elseif ($args->getOption('fixtures')) {
- $fixtures = array_map('trim', explode(',', $args->getOption('fixtures')));
+ $fixtures = array_map('trim', explode(',', (string)$args->getOption('fixtures')));
$this->_fixtures = array_filter($fixtures);
} elseif ($this->typeCanDetectFixtures($type) && class_exists($fullClassName)) {
$io->out('Bake is detecting possible fixtures...');
$testSubject = $this->buildTestSubject($type, $fullClassName);
- $this->generateFixtureList($testSubject);
+ if ($testSubject instanceof Table || $testSubject instanceof Controller) {
+ $this->generateFixtureList($testSubject);
+ }
}
}
@@ -493,7 +496,7 @@ public function mapType(string $type): string
* Get methods declared in the class given.
* No parent methods will be returned
*
- * @param string $className Name of class to look at.
+ * @param class-string $className Name of class to look at.
* @return array Array of method names.
* @throws \ReflectionException
*/
diff --git a/src/Utility/CommonOptionsTrait.php b/src/Utility/CommonOptionsTrait.php
index fde67f95..b2a379f9 100644
--- a/src/Utility/CommonOptionsTrait.php
+++ b/src/Utility/CommonOptionsTrait.php
@@ -62,7 +62,7 @@ protected function extractCommonProperties(Arguments $args): void
// These properties should ideally not exist, but until ConsoleOptionParser
// gets validation and transform logic they will have to stay.
if ($args->hasOption('plugin')) {
- $plugin = $args->getOption('plugin');
+ $plugin = (string)$args->getOption('plugin');
$parts = explode('/', $plugin);
$this->plugin = implode('/', array_map([$this, '_camelize'], $parts));
@@ -73,9 +73,11 @@ protected function extractCommonProperties(Arguments $args): void
}
}
- $this->theme = $args->getOption('theme');
- $this->connection = $args->getOption('connection');
- $this->force = $args->getOption('force');
+ $theme = $args->getOption('theme');
+ $this->theme = is_string($theme) ? $theme : null;
+ $connection = $args->getOption('connection');
+ $this->connection = is_string($connection) ? $connection : 'default';
+ $this->force = (bool)$args->getOption('force');
}
/**
diff --git a/src/Utility/Model/EnumParser.php b/src/Utility/Model/EnumParser.php
index e559fe03..3cf32999 100644
--- a/src/Utility/Model/EnumParser.php
+++ b/src/Utility/Model/EnumParser.php
@@ -23,9 +23,10 @@ public static function parseCases(?string $casesString, bool $int): array
$definition = [];
foreach ($enumCases as $k => $enumCase) {
$case = $value = trim($enumCase);
- if (str_contains($case, ':')) {
- $value = trim(mb_substr($case, strpos($case, ':') + 1));
- $case = mb_substr($case, 0, strpos($case, ':'));
+ $pos = strpos($case, ':');
+ if ($pos !== false) {
+ $value = trim(mb_substr($case, $pos + 1));
+ $case = mb_substr($case, 0, $pos);
} elseif ($int) {
$value = $k;
}
@@ -52,8 +53,9 @@ public static function parseCases(?string $casesString, bool $int): array
public static function parseDefinitionString(string $comment): string
{
$string = trim(mb_substr($comment, strpos($comment, '[enum]') + 6));
- if (str_contains($string, ';')) {
- $string = trim(mb_substr($string, 0, strpos($string, ';')));
+ $pos = strpos($string, ';');
+ if ($pos !== false) {
+ $string = trim(mb_substr($string, 0, $pos));
}
return $string;
diff --git a/src/Utility/SubsetSchemaCollection.php b/src/Utility/SubsetSchemaCollection.php
index ca1b8352..6f202c08 100644
--- a/src/Utility/SubsetSchemaCollection.php
+++ b/src/Utility/SubsetSchemaCollection.php
@@ -60,7 +60,7 @@ public function getInnerCollection(): CollectionInterface
/**
* Get the list of tables in this schema collection.
*
- * @return list
+ * @return array
*/
public function listTables(): array
{
diff --git a/src/Utility/TemplateRenderer.php b/src/Utility/TemplateRenderer.php
index d3f8eb63..42996b97 100644
--- a/src/Utility/TemplateRenderer.php
+++ b/src/Utility/TemplateRenderer.php
@@ -59,7 +59,7 @@ public function __construct(?string $theme = null)
/**
* Get view instance
*
- * @return \Cake\View\View
+ * @return \Bake\View\BakeView
* @triggers Bake.initialize $view
*/
public function getView(): View
diff --git a/src/View/BakeView.php b/src/View/BakeView.php
index 84186543..78928f10 100644
--- a/src/View/BakeView.php
+++ b/src/View/BakeView.php
@@ -18,17 +18,12 @@
use Cake\Core\Configure;
use Cake\Core\ConventionsTrait;
-use Cake\Event\EventDispatcherTrait;
use Cake\Event\EventInterface;
use Cake\TwigView\View\TwigView;
use function Cake\Core\pluginSplit;
class BakeView extends TwigView
{
- /**
- * @use \Cake\Event\EventDispatcherTrait<\Cake\View\View>
- */
- use EventDispatcherTrait;
use ConventionsTrait;
/**
@@ -81,6 +76,8 @@ public function initialize(): void
*/
public function render(?string $template = null, string|false|null $layout = null): string
{
+ assert($template !== null, 'Template name must be provided.');
+
$viewFileName = $this->_getTemplateFileName($template);
[, $templateEventName] = pluginSplit($template);
$templateEventName = str_replace(['/', '\\'], '.', $templateEventName);
@@ -107,19 +104,19 @@ public function render(?string $template = null, string|false|null $layout = nul
*
* Use the Bake prefix for bake related view events
*
- * @template TSubject of \Cake\View\View
* @param string $name Name of the event.
* @param array $data Any value you wish to be transported with this event to
* it can be read by listeners.
- *
- * @param TSubject|null $subject The object that this event applies to
+ * @param object|null $subject The object that this event applies to
* ($this by default).
- * @return \Cake\Event\EventInterface<\Cake\View\View>
+ * @return \Cake\Event\EventInterface
+ * @phpstan-ignore missingType.generics
*/
public function dispatchEvent(string $name, array $data = [], ?object $subject = null): EventInterface
{
- $name = preg_replace('/^View\./', 'Bake.', $name);
+ $name = (string)preg_replace('/^View\./', 'Bake.', $name);
+ /** @phpstan-ignore-next-line missingType.generics */
return parent::dispatchEvent($name, $data, $subject);
}
@@ -128,7 +125,7 @@ public function dispatchEvent(string $name, array $data = [], ?object $subject =
*
* @param ?string $plugin Optional plugin name to scan for view files.
* @param bool $cached Set to false to force a refresh of view paths. Default true.
- * @return list paths
+ * @return array paths
*/
protected function _paths(?string $plugin = null, bool $cached = true): array
{
diff --git a/tests/TestCase/Command/ModelCommandTest.php b/tests/TestCase/Command/ModelCommandTest.php
index 74ff6510..0afceb9a 100644
--- a/tests/TestCase/Command/ModelCommandTest.php
+++ b/tests/TestCase/Command/ModelCommandTest.php
@@ -295,7 +295,7 @@ public function testGetAssociations()
$command->connection = 'test';
$args = new Arguments([], [], []);
- $io = $this->createMock(ConsoleIo::class);
+ $io = $this->createStub(ConsoleIo::class);
$result = $command->getAssociations($items, $args, $io);
$expected = [
@@ -341,7 +341,7 @@ public function testGetAssociationsNoFlag()
$command->connection = 'test';
$arguments = new Arguments([], ['no-associations' => true], []);
- $io = $this->createMock(ConsoleIo::class);
+ $io = $this->createStub(ConsoleIo::class);
$articles = $this->getTableLocator()->get('BakeArticle');
$this->assertEquals([], $command->getAssociations($articles, $arguments, $io));
}
@@ -359,7 +359,7 @@ public function testGetAssociationsPlugin()
$command->connection = 'test';
$args = new Arguments([], [], []);
- $io = $this->createMock(ConsoleIo::class);
+ $io = $this->createStub(ConsoleIo::class);
$result = $command->getAssociations($items, $args, $io);
$expected = [
'belongsTo' => [
@@ -412,7 +412,7 @@ public function testGetAssociationsIgnoreUnderscoreIdIfNoDbTable()
$command->connection = 'test';
$args = new Arguments([], [], []);
- $io = $this->createMock(ConsoleIo::class);
+ $io = $this->createStub(ConsoleIo::class);
$result = $command->getAssociations($items, $args, $io);
$expected = [
'belongsTo' => [
@@ -461,7 +461,7 @@ public function testGetAssociationsAddAssociationIfTableExist()
$command->connection = 'test';
$args = new Arguments([], [], []);
- $io = $this->createMock(ConsoleIo::class);
+ $io = $this->createStub(ConsoleIo::class);
$result = $command->getAssociations($items, $args, $io);
$expected = [
'belongsTo' => [
@@ -514,7 +514,7 @@ public function testGetAssociationsAddAssociationIfNoTableExistButAliasIsAllowed
$command->connection = 'test';
$args = new Arguments([], ['skip-relation-check' => true], []);
- $io = $this->createMock(ConsoleIo::class);
+ $io = $this->createStub(ConsoleIo::class);
$result = $command->getAssociations($items, $args, $io);
$expected = [
'belongsTo' => [
@@ -566,7 +566,7 @@ public function testGetAssociationsIgnoreUnderscoreId()
]);
$args = new Arguments([], [], []);
- $io = $this->createMock(ConsoleIo::class);
+ $io = $this->createStub(ConsoleIo::class);
$command = new ModelCommand();
$command->connection = 'test';
@@ -592,7 +592,7 @@ public function testGetAssociationsConstraints()
$command->connection = 'test';
$args = new Arguments([], [], []);
- $io = $this->createMock(ConsoleIo::class);
+ $io = $this->createStub(ConsoleIo::class);
$result = $command->getAssociations($model, $args, $io);
$expected = [
diff --git a/tests/TestCase/Command/PluginCommandTest.php b/tests/TestCase/Command/PluginCommandTest.php
index 03498fe2..0c6efcf3 100644
--- a/tests/TestCase/Command/PluginCommandTest.php
+++ b/tests/TestCase/Command/PluginCommandTest.php
@@ -201,7 +201,7 @@ public function testMainUpdateComposer()
*/
public function testFindPathNonExistent()
{
- $io = $this->createMock(ConsoleIo::class);
+ $io = $this->createStub(ConsoleIo::class);
$paths = App::path('plugins');
array_unshift($paths, '/fake/path');
@@ -224,7 +224,7 @@ public function testFindPathNonExistent()
public function testFindPathEmpty()
{
$this->expectException(StopException::class);
- $io = $this->createMock(ConsoleIo::class);
+ $io = $this->createStub(ConsoleIo::class);
$paths = ['/fake/path', '/fake/path2'];
$command = new PluginCommand();
diff --git a/tests/TestCase/Command/TemplateCommandTest.php b/tests/TestCase/Command/TemplateCommandTest.php
index e730bf0d..846386e7 100644
--- a/tests/TestCase/Command/TemplateCommandTest.php
+++ b/tests/TestCase/Command/TemplateCommandTest.php
@@ -310,7 +310,7 @@ public function testGetContent()
];
$command = new TemplateCommand();
$args = new Arguments([], [], []);
- $io = $this->createMock(ConsoleIo::class);
+ $io = $this->createStub(ConsoleIo::class);
$result = $command->getContent($args, $io, 'view', $vars);
$this->assertSameAsFile(__FUNCTION__ . '.php', $result);
}
@@ -355,7 +355,7 @@ public function testGetContentAssociations()
$command = new TemplateCommand();
$args = new Arguments([], [], []);
- $io = $this->createMock(ConsoleIo::class);
+ $io = $this->createStub(ConsoleIo::class);
$result = $command->getContent($args, $io, 'view', $vars);
$this->assertSameAsFile(__FUNCTION__ . '.php', $result);
}
@@ -428,7 +428,7 @@ public function testGetContentWithRoutingPrefix()
];
$command = new TemplateCommand();
$args = new Arguments([], ['prefix' => 'Admin'], []);
- $io = $this->createMock(ConsoleIo::class);
+ $io = $this->createStub(ConsoleIo::class);
$result = $command->getContent($args, $io, 'view', $vars);
$this->assertSameAsFile(__FUNCTION__ . '-view.php', $result);