diff --git a/.gitattributes b/.gitattributes index d87cc8aa8cf2..02a23de3322d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -22,6 +22,7 @@ utils/ export-ignore .php-cs-fixer.no-header.php export-ignore .php-cs-fixer.tests.php export-ignore .php-cs-fixer.user-guide.php export-ignore +structarmed-baseline.php export-ignore structarmed.php export-ignore phpmetrics.json export-ignore phpstan-baseline.php export-ignore diff --git a/structarmed-baseline.php b/structarmed-baseline.php new file mode 100644 index 000000000000..eede90ce7048 --- /dev/null +++ b/structarmed-baseline.php @@ -0,0 +1,20 @@ + 'base_classes.must_be_abstract', + 'message' => 'Extended class [CodeIgniter\Config\BaseService] must be declared abstract or instantiated', + 'file' => 'system/Config/BaseService.php', + 'class' => 'CodeIgniter\Config\BaseService', + 'layer' => 'Source', + ], + [ + 'rule' => 'base_classes.must_be_abstract', + 'message' => 'Extended class [CodeIgniter\Debug\Toolbar\Collectors\BaseCollector] must be declared abstract or instantiated', + 'file' => 'system/Debug/Toolbar/Collectors/BaseCollector.php', + 'class' => 'CodeIgniter\Debug\Toolbar\Collectors\BaseCollector', + 'layer' => 'Source', + ], +]; diff --git a/structarmed.php b/structarmed.php index 88932d17cdd0..990f039601bc 100644 --- a/structarmed.php +++ b/structarmed.php @@ -10,35 +10,39 @@ * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ -use Boundwize\StructArmed\Rule\Rules\Function_\MustHaveReturnTypeFunctionRule; + +use Boundwize\StructArmed\Architecture; +use Boundwize\StructArmed\Preset\Preset; use Boundwize\StructArmed\Preset\Presets\CodeQualityPreset; +use Boundwize\StructArmed\Preset\Presets\Psr4Preset; +use Boundwize\StructArmed\Rule\Rules\Class_\ExtendedClassMustBeAbstractOrInstantiatedRule; +use Boundwize\StructArmed\Rule\Rules\Function_\MustHaveReturnTypeFunctionRule; use CodeIgniter\Cache\ResponseCache; +use CodeIgniter\Database\BaseResult; +use CodeIgniter\DataCaster\DataCaster; +use CodeIgniter\DataConverter\DataConverter; +use CodeIgniter\Entity\Cast\CastInterface; +use CodeIgniter\Entity\Cast\URICast; +use CodeIgniter\Entity\Entity; +use CodeIgniter\Entity\Exceptions\CastException; use CodeIgniter\HTTP\CLIRequest; +use CodeIgniter\HTTP\DownloadResponse; use CodeIgniter\HTTP\Header; use CodeIgniter\HTTP\IncomingRequest; +use CodeIgniter\HTTP\RedirectResponse; +use CodeIgniter\HTTP\Response; use CodeIgniter\HTTP\ResponseInterface; -use CodeIgniter\DataCaster\DataCaster; -use CodeIgniter\Entity\Cast\CastInterface; -use CodeIgniter\Entity\Exceptions\CastException; -use CodeIgniter\DataConverter\DataConverter; -use CodeIgniter\Entity\Entity; -use CodeIgniter\Entity\Cast\URICast; +use CodeIgniter\HTTP\ResponseTrait; +use CodeIgniter\HTTP\SSEResponse; +use CodeIgniter\HTTP\StreamResponse; use CodeIgniter\HTTP\URI; use CodeIgniter\Log\Handlers\ChromeLoggerHandler; -use CodeIgniter\Security\CheckPhpIni; -use CodeIgniter\View\Table; -use CodeIgniter\Database\BaseResult; -use CodeIgniter\View\Plugins; -use CodeIgniter\HTTP\ResponseTrait; use CodeIgniter\Pager\PagerInterface; -use CodeIgniter\HTTP\Response; -use CodeIgniter\HTTP\RedirectResponse; -use CodeIgniter\HTTP\DownloadResponse; +use CodeIgniter\Security\CheckPhpIni; use CodeIgniter\Validation\Validation; +use CodeIgniter\View\Plugins; use CodeIgniter\View\RendererInterface; -use Boundwize\StructArmed\Architecture; -use Boundwize\StructArmed\Preset\Preset; -use Boundwize\StructArmed\Preset\Presets\Psr4Preset; +use CodeIgniter\View\Table; return Architecture::define() ->skip([ @@ -50,12 +54,15 @@ __DIR__ . '/system/View/Cells/Cell.php', ], ]) + ->baseline(__DIR__ . '/structarmed-baseline.php') ->cacheDirectory(is_dir('/tmp') ? '/tmp/structarmed' : null) ->withPresets(Preset::PSR4(), Preset::CODEQUALITY()) ->layer('Helpers', __DIR__ . '/system/Helpers') ->rule('helpers.functions_must_have_return_type', new MustHaveReturnTypeFunctionRule('Helpers')) + ->rule('base_classes.must_be_abstract', new ExtendedClassMustBeAbstractOrInstantiatedRule('Source', '/^CodeIgniter\\\\.*Base.*$/')) + // Resolve CodeIgniter layers from class names because several layers share directories. ->layerPattern('API', '/^CodeIgniter\\\\API\\\\.*$/') ->layerPattern('Cache', '/^CodeIgniter\\\\Cache\\\\.*$/') @@ -72,11 +79,13 @@ ->layerPattern('Filters', '/^CodeIgniter\\\\Filters\\\\Filter.*$/') ->layerPattern('Format', '/^CodeIgniter\\\\Format\\\\.*$/') ->layerPattern('Honeypot', '/^CodeIgniter\\\\.*Honeypot.*$/') + ->layerPattern('Input', '/^CodeIgniter\\\\Input\\\\.*$/') ->layerPattern('URI', '/^CodeIgniter\\\\HTTP\\\\URI$/') ->layerPattern('HTTP', '/^CodeIgniter\\\\HTTP\\\\.*$/', '/(Exception|URI)/') ->layerPattern('I18n', '/^CodeIgniter\\\\I18n\\\\.*$/') ->layerPattern('Images', '/^CodeIgniter\\\\Images\\\\.*$/') ->layerPattern('Language', '/^CodeIgniter\\\\Language\\\\.*$/') + ->layerPattern('Lock', '/^CodeIgniter\\\\Lock\\\\.*$/') ->layerPattern('Log', '/^CodeIgniter\\\\Log\\\\.*$/') ->layerPattern('Model', '/^CodeIgniter\\\\.*Model$/') ->layerPattern('Modules', '/^CodeIgniter\\\\Modules\\\\.*$/') @@ -96,26 +105,28 @@ 'Controller' => ['HTTP', 'Validation'], 'Cookie' => ['I18n'], 'Database' => ['Entity', 'Events', 'I18n'], - 'DataCaster' => ['I18n', 'URI', 'Database'], + 'DataCaster' => ['I18n', 'URI', 'Database', 'Encryption'], 'DataConverter' => ['DataCaster'], 'Email' => ['I18n', 'Events'], 'Entity' => ['DataCaster', 'I18n'], 'Files' => ['I18n'], 'Filters' => ['HTTP'], 'Honeypot' => ['Filters', 'HTTP'], - 'HTTP' => ['Cookie', 'Files', 'I18n', 'Security', 'URI'], + 'HTTP' => ['Cookie', 'Files', 'I18n', 'Input', 'Security', 'URI'], + 'Input' => ['I18n'], 'Images' => ['Files', 'I18n'], + 'Lock' => ['Cache'], 'Model' => ['Database', 'DataCaster', 'DataConverter', 'Entity', 'I18n', 'Pager', 'Validation'], 'Pager' => ['URI', 'View'], 'Publisher' => ['Files', 'URI'], // +API = API + its allowed layers; +Controller = Controller + its allowed layers - 'RESTful' => ['+API', '+Controller'], - 'Router' => ['HTTP', 'I18n'], - 'Security' => ['Cookie', 'HTTP', 'I18n', 'Session'], - 'Session' => ['Cookie', 'Database', 'HTTP', 'I18n'], - 'Throttle' => ['Cache', 'I18n'], - 'Validation' => ['Database', 'HTTP', 'Helpers'], - 'View' => ['Cache'], + 'RESTful' => ['+API', '+Controller'], + 'Router' => ['HTTP', 'I18n'], + 'Security' => ['Cookie', 'HTTP', 'I18n', 'Session'], + 'Session' => ['Cookie', 'Database', 'HTTP', 'I18n'], + 'Throttle' => ['Cache', 'I18n'], + 'Validation' => ['Database', 'HTTP', 'Helpers', 'I18n', 'Input'], + 'View' => ['Cache'], ]) ->skipPathsForRuleset(['*test*']) // Skip violations for class-specific dependencies. @@ -129,7 +140,7 @@ CastInterface::class, CastException::class, ]) - ->skipClassViolation(\CodeIgniter\DataCaster\Exceptions\CastException::class, [ + ->skipClassViolation(CodeIgniter\DataCaster\Exceptions\CastException::class, [ CastException::class, ]) ->skipClassViolation(DataConverter::class, [ @@ -157,4 +168,6 @@ ->skipClassViolation(Response::class, [PagerInterface::class]) ->skipClassViolation(RedirectResponse::class, [PagerInterface::class]) ->skipClassViolation(DownloadResponse::class, [PagerInterface::class]) + ->skipClassViolation(SSEResponse::class, [PagerInterface::class]) + ->skipClassViolation(StreamResponse::class, [PagerInterface::class]) ->skipClassViolation(Validation::class, [RendererInterface::class]);