Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
/coverage.xml
/tests/tmp/*
/.phpunit.cache/
/src-sa/.phpunit.cache/
/.claude/
/.qodo/
/web-query/
17 changes: 16 additions & 1 deletion composer-require-checker.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,22 @@
"array", "string", "int", "float", "bool", "iterable", "callable", "void", "object", "mixed", "never",
"Roave\\BetterReflection\\Reflector\\DefaultReflector",
"Roave\\BetterReflection\\Reflector\\ClassReflector",
"json_decode", "json_encode", "JSON_THROW_ON_ERROR"
"json_decode", "json_encode", "JSON_THROW_ON_ERROR",
"ctype_alnum",
"ctype_alpha",
"PhpParser\\Node",
"PhpParser\\Node\\Attribute",
"PhpParser\\Node\\Expr",
"PhpParser\\Node\\Expr\\ClassConstFetch",
"PhpParser\\Node\\Identifier",
"PhpParser\\Node\\Name",
"PhpParser\\Node\\Scalar\\String_",
"PhpParser\\Node\\Stmt\\ClassMethod",
"PHPStan\\Analyser\\Scope",
"PHPStan\\Reflection\\ReflectionProvider",
"PHPStan\\Rules\\Rule",
"PHPStan\\Rules\\RuleErrorBuilder",
"PHPStan\\Type\\ObjectType"
],
"php-core-extensions" : [
"Core",
Expand Down
21 changes: 14 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8",
"phpstan/phpstan": "^2.1",
"phpunit/phpunit": "^11.5"
},
"autoload": {
"psr-4": {
"Ray\\MediaQuery\\PHPStan\\": "src-sa/src/",
"Ray\\MediaQuery\\": [
"src/",
"src-deprecated/"
Expand All @@ -38,6 +40,7 @@
},
"autoload-dev": {
"psr-4": {
"Ray\\MediaQuery\\PHPStan\\Tests\\": "src-sa/tests/",
"Ray\\MediaQuery\\": [
"tests/",
"tests/Fake"
Expand All @@ -48,21 +51,23 @@
"scripts": {
"coverage": "php -dzend_extension=xdebug.so -dxdebug.mode=coverage ./vendor/bin/phpunit --coverage-text --coverage-html=build/coverage",
"pcov": "php -dextension=pcov.so -d pcov.enabled=1 ./vendor/bin/phpunit --coverage-text --coverage-html=build/coverage --coverage-clover=coverage.xml",
"cs": "./vendor/bin/phpcs",
"cs-fix": "./vendor/bin/phpcbf src tests docs/tutorial/src/Blog",
"metrics": "./vendor/bin/phpmetrics --report-html=build/metrics --exclude=Exception src",
"cs": "vendor-bin/tools/vendor/bin/phpcs",
"cs-fix": "vendor-bin/tools/vendor/bin/phpcbf src tests docs/tutorial/src/Blog src-sa/src src-sa/tests",
"metrics": "vendor-bin/tools/vendor/bin/phpmetrics --report-html=build/metrics --exclude=Exception src",
"clean": [
"./vendor/bin/phpstan clear-result-cache",
"./vendor/bin/psalm --clear-cache"
"vendor/bin/phpstan clear-result-cache",
"php -d error_reporting=8191 vendor-bin/tools/vendor/bin/psalm --clear-cache"
],
"sa": [
"./vendor/bin/psalm --monochrome --show-info=true",
"./vendor/bin/phpstan analyse -c phpstan.neon"
"php -d error_reporting=8191 vendor-bin/tools/vendor/bin/psalm --monochrome --show-info=true --no-cache",
"vendor/bin/phpstan analyse -c phpstan.neon --memory-limit=1G"
],
"test:phpstan": "vendor/bin/phpunit -c src-sa/phpunit.xml.dist",
"test": "./vendor/bin/phpunit",
"tutorial": "php -d zend.assertions=1 -d assert.exception=1 docs/tutorial/src/run.php",
"tests": [
"@cs",
"@test:phpstan",
"@sa",
"@test",
"@tutorial"
Expand All @@ -78,6 +83,7 @@
"scripts-descriptions": {
"test": "Run unit tests",
"tutorial": "Run the tutorial answer code end-to-end as an integration check",
"test:phpstan": "Run PHPStan extension rule tests",
"coverage": "Generate test coverage report",
"pcov": "Generate test coverage report (pcov)",
"cs": "Check the coding style",
Expand All @@ -103,6 +109,7 @@
},
"suggest": {
"koriym/csv-entities": "Provides one-to-many entity relation",
"phpstan/phpstan": "Required to use the optional Ray.MediaQuery PHPStan extension.",
"ray/web-query": "For Web API query support"
},
"extra": {
Expand Down
3 changes: 3 additions & 0 deletions phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
<!-- Directories to be checked -->
<file>src</file>
<file>tests</file>
<file>src-sa/src</file>
<file>src-sa/tests</file>
<!-- Tutorial "answer key" classes are held to the same standard as the library.
run.php is intentionally excluded: it is an executable script that mixes a
namespace declaration with side effects (PSR1.Files.SideEffects). -->
Expand Down Expand Up @@ -83,4 +85,5 @@

<exclude-pattern>*/Fake/*</exclude-pattern>
<exclude-pattern>*/tmp/*</exclude-pattern>
<exclude-pattern>*/src-sa/tests/Rules/Data/*</exclude-pattern>
</ruleset>
12 changes: 12 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
includes:
- src-sa/extension.neon

parameters:
level: max
parallel:
maximumNumberOfProcesses: 1
paths:
- src
- src-sa/src
- tests
- docs/tutorial/src
excludePaths:
- tests/Fake/*
- tests/tmp/*
- src/MediaQueryModule.php
rayMediaQuery:
sqlDirectories:
- docs/tutorial/src/sql
factoryMethod: factory
strict: false
strictPlaceholderCheck: false
39 changes: 39 additions & 0 deletions src-sa/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Ray.MediaQuery PHPStan Extension

Static analysis rules for Ray.MediaQuery query contracts.

The extension is bundled with `ray/media-query` as an optional development
feature. It is not a runtime dependency. Projects that want to enable it should
install PHPStan separately:

```bash
composer require --dev phpstan/phpstan
```

## Configuration

Include the extension from `phpstan.neon` and configure SQL directories:

```neon
includes:
- vendor/ray/media-query/src-sa/extension.neon

parameters:
rayMediaQuery:
sqlDirectories:
- docs/tutorial/src/sql
```

When developing this repository itself, include `src-sa/extension.neon` instead.

The MVP rules verify that `#[DbQuery]` SQL files exist and are non-empty,
that `#[Pager]` methods return `PagesInterface`, that `PagesInterface` return
methods declare `#[Pager]`, and that `factory:` classes define the configured
factory method.

## PHPStan result cache

The rules read `.sql` files from disk. PHPStan's result cache does not always
track non-PHP file changes, so local runs may keep stale diagnostics after only
SQL files change. Clear the cache with `composer clean` or
`vendor/bin/phpstan clear-result-cache` when validating SQL-only edits.
23 changes: 23 additions & 0 deletions src-sa/extension.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
parameters:
rayMediaQuery:
sqlDirectories: []
factoryMethod: factory
strict: false
strictPlaceholderCheck: false

parametersSchema:
rayMediaQuery: structure([
sqlDirectories: listOf(string())
factoryMethod: string()
strict: bool()
strictPlaceholderCheck: bool()
])

services:
-
class: Ray\MediaQuery\PHPStan\Rules\DbQueryContractRule
arguments:
sqlDirectories: %rayMediaQuery.sqlDirectories%
factoryMethod: %rayMediaQuery.factoryMethod%
tags:
- phpstan.rules.rule
14 changes: 14 additions & 0 deletions src-sa/phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/11.5/phpunit.xsd"
bootstrap="tests/bootstrap.php"
cacheDirectory=".phpunit.cache">
<testsuites>
<testsuite name="Ray.MediaQuery PHPStan extension">
<directory>tests</directory>
</testsuite>
</testsuites>
<php>
<ini name="error_reporting" value="-1"/>
</php>
</phpunit>
Loading
Loading