diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml new file mode 100644 index 0000000..27d9052 --- /dev/null +++ b/.github/workflows/benchmark.yml @@ -0,0 +1,35 @@ +on: [ pull_request, push ] + +name: "Benchmark" + +permissions: + contents: read + +jobs: + tests: + name: Benchmark + + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + php-version: + - 8.1 + - 8.2 + - 8.3 + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: "${{ matrix.php-version }}" + + - name: Install dependencies + uses: php-actions/composer@v6 + + - name: Run benchmark + run: vendor/bin/phpbench run tests/bench --report=aggregate diff --git a/composer.json b/composer.json index 11f72b5..d861d92 100644 --- a/composer.json +++ b/composer.json @@ -29,6 +29,7 @@ "php": "^8.1" }, "require-dev": { - "phpunit/phpunit": "^10.3" + "phpunit/phpunit": "^10.3", + "phpbench/phpbench": "^1.2" } } diff --git a/phpbench.json b/phpbench.json new file mode 100644 index 0000000..98f2de4 --- /dev/null +++ b/phpbench.json @@ -0,0 +1,5 @@ +{ + "$schema": "./vendor/phpbench/phpbench/phpbench.schema.json", + "runner.bootstrap": "vendor/autoload.php", + "runner.file_pattern": "*Bench.php" +} diff --git a/src/Pathfinder.php b/src/Pathfinder.php index 84c2362..a30d8c0 100644 --- a/src/Pathfinder.php +++ b/src/Pathfinder.php @@ -128,12 +128,13 @@ public function delete(string $pattern, string $handler): void public function match(string $method, string $path): array { + $method = strtoupper($method); if (isset($this->static[$path])) { if (!isset($this->static[$path][self::HANDLERS][$method])) { - return self::result(self::METHOD_NOT_ALLOWED); + return [self::METHOD_NOT_ALLOWED, []]; } - return self::result($this->static[$path][self::HANDLERS][$method]); + return [$this->static[$path][self::HANDLERS][$method], []]; } $params = []; @@ -176,22 +177,22 @@ public function match(string $method, string $path): array } if (!$found) { - return self::result(self::NOT_FOUND); + return [self::NOT_FOUND, []]; } } if ($node[self::HANDLERS]) { if (!isset($node[self::HANDLERS][$method])) { - return self::result(self::METHOD_NOT_ALLOWED); + return [self::METHOD_NOT_ALLOWED, []]; } - return self::result( + return [ $node[self::HANDLERS][$method], $params, - ); + ]; } - return self::result(self::NOT_FOUND); + return [self::NOT_FOUND, []]; } public function tree(): array @@ -202,11 +203,6 @@ public function tree(): array ]; } - private static function result(string|int $handler, array $params = []): array - { - return [$handler, $params]; - } - private static function static(): array { return [ diff --git a/tests/Bench/ColdBench.php b/tests/Bench/ColdBench.php new file mode 100644 index 0000000..60227f7 --- /dev/null +++ b/tests/Bench/ColdBench.php @@ -0,0 +1,42 @@ +match('GET', '/users'); + } + + public function benchLastRoute(): void + { + $router = new Pathfinder(); + $routing = require __DIR__ . '/../routes/routes.php'; + $routing($router); + $router->match('POST', '/api/workflow/9999/stages/6666/tasks/3333/subtasks/1111/complete'); + } + + public function bench404(): void + { + $router = new Pathfinder(); + $routing = require __DIR__ . '/../routes/routes.php'; + $routing($router); + $router->match('GET', '/api/workflow/9999/stages/6666/tasks/3333/subtasks/1111/complete!'); + } +} diff --git a/tests/Bench/InstantiatedBench.php b/tests/Bench/InstantiatedBench.php new file mode 100644 index 0000000..3d6bf37 --- /dev/null +++ b/tests/Bench/InstantiatedBench.php @@ -0,0 +1,49 @@ +pathfinder = new Pathfinder(); + $routing = require __DIR__ . '/../routes/routes.php'; + $routing($this->pathfinder); + + $tree = $this->pathfinder->tree(); + (new Cache(__DIR__ . '/../../var/pathfinder_cache'))->write($tree); + + $tree = (new Cache(__DIR__ . '/../../var/pathfinder_cache'))->read(); + $this->pathfinder = new Pathfinder($tree); + } + + public function benchFirstRoute(): void + { + $this->pathfinder->match('GET', '/users'); + } + + public function benchLastRoute(): void + { + $this->pathfinder->match('POST', '/api/workflow/9999/stages/6666/tasks/3333/subtasks/1111/complete'); + } + + public function bench404(): void + { + $this->pathfinder->match('GET', '/api/workflow/9999/stages/6666/tasks/3333/subtasks/1111/complete!'); + } +} diff --git a/tests/Bench/WarmBench.php b/tests/Bench/WarmBench.php new file mode 100644 index 0000000..2e34ecd --- /dev/null +++ b/tests/Bench/WarmBench.php @@ -0,0 +1,53 @@ +tree(); + (new Cache(__DIR__ . '/../../var/pathfinder_cache'))->write($tree); + } + + public function benchFirstRoute(): void + { + $tree = (new Cache(__DIR__ . '/../../var/pathfinder_cache'))->read(); + $router = new Pathfinder($tree); + + $router->match('GET', '/users'); + } + + public function benchLastRoute(): void + { + $tree = (new Cache(__DIR__ . '/../../var/pathfinder_cache'))->read(); + $router = new Pathfinder($tree); + + $router->match('POST', '/api/workflow/9999/stages/6666/tasks/3333/subtasks/1111/complete'); + } + + public function bench404(): void + { + $tree = (new Cache(__DIR__ . '/../../var/pathfinder_cache'))->read(); + $router = new Pathfinder($tree); + + $router->match('GET', '/api/workflow/9999/stages/6666/tasks/3333/subtasks/1111/complete!'); + } +} diff --git a/tests/profile.php b/tests/profile.php new file mode 100644 index 0000000..1359f72 --- /dev/null +++ b/tests/profile.php @@ -0,0 +1,27 @@ +match('POST', '/api/workflow/9999/stages/6666/tasks/3333/subtasks/1111/complete'); +} + +function setup(): Pathfinder +{ + $pathfinder = new Pathfinder(); + $routing = require __DIR__ . '/routes/routes.php'; + $routing($pathfinder); + + $tree = $pathfinder->tree(); + (new Cache(__DIR__ . '/../var/pathfinder_cache'))->write($tree); + + $tree = (new Cache(__DIR__ . '/../var/pathfinder_cache'))->read(); + return new Pathfinder($tree); +} diff --git a/tests/routes/routes.php b/tests/routes/routes.php new file mode 100644 index 0000000..0b2071f --- /dev/null +++ b/tests/routes/routes.php @@ -0,0 +1,242 @@ +route('GET', '/users', 'r_0'); + $routes->route('GET', '/users/{username:[a-zA-Z0-9-_]+}', 'r_1'); + $routes->route('PATCH', '/user', 'r_2'); + $routes->route('GET', '/user/repos', 'r_3'); + $routes->route('GET', '/users/{username:[a-zA-Z0-9-_]+}/repos', 'r_4'); + $routes->route('GET', '/repos/{owner:[a-zA-Z0-9-_]+}/{repo:[a-zA-Z0-9-_]+}', 'r_5'); + $routes->route('POST', '/user/repos', 'r_6'); + $routes->route('PATCH', '/repos/{owner:[a-zA-Z0-9-_]+}/{repo:[a-zA-Z0-9-_]+}', 'r_7'); + $routes->route('DELETE', '/repos/{owner:[a-zA-Z0-9-_]+}/{repo:[a-zA-Z0-9-_]+}', 'r_8'); + $routes->route('GET', '/repos/{owner:[a-zA-Z0-9-_]+}/{repo:[a-zA-Z0-9-_]+}/issues', 'r_9'); + $routes->route('GET', '/repos/{owner:[a-zA-Z0-9-_]+}/{repo:[a-zA-Z0-9-_]+}/issues/{number:\d+}', 'r_10'); + $routes->route('POST', '/repos/{owner:[a-zA-Z0-9-_]+}/{repo:[a-zA-Z0-9-_]+}/issues', 'r_11'); + $routes->route('PATCH', '/repos/{owner:[a-zA-Z0-9-_]+}/{repo:[a-zA-Z0-9-_]+}/issues/{number:\d+}', 'r_12'); + $routes->route('DELETE', '/repos/{owner:[a-zA-Z0-9-_]+}/{repo:[a-zA-Z0-9-_]+}/issues/{number:\d+}', 'r_13'); + $routes->route('GET', '/repos/{owner:[a-zA-Z0-9-_]+}/{repo:[a-zA-Z0-9-_]+}/pulls', 'r_14'); + $routes->route('GET', '/repos/{owner:[a-zA-Z0-9-_]+}/{repo:[a-zA-Z0-9-_]+}/pulls/{number:\d+}', 'r_15'); + $routes->route('POST', '/repos/{owner:[a-zA-Z0-9-_]+}/{repo:[a-zA-Z0-9-_]+}/pulls', 'r_16'); + $routes->route('PATCH', '/repos/{owner:[a-zA-Z0-9-_]+}/{repo:[a-zA-Z0-9-_]+}/pulls/{number:\d+}', 'r_17'); + $routes->route('GET', '/repos/{owner:[a-zA-Z0-9-_]+}/{repo:[a-zA-Z0-9-_]+}/commits', 'r_18'); + $routes->route('GET', '/repos/{owner:[a-zA-Z0-9-_]+}/{repo:[a-zA-Z0-9-_]+}/commits/{sha:[a-zA-Z0-9]+}', 'r_19'); + $routes->route('GET', '/gists', 'r_20'); + $routes->route('GET', '/gists/{gist_id:[a-zA-Z0-9]+}', 'r_21'); + $routes->route('POST', '/gists', 'r_22'); + $routes->route('PATCH', '/gists/{gist_id:[a-zA-Z0-9]+}', 'r_23'); + $routes->route('DELETE', '/gists/{gist_id:[a-zA-Z0-9]+}', 'r_24'); + $routes->route('GET', '/s3/buckets', 'r_25'); + $routes->route('POST', '/s3/buckets', 'r_26'); + $routes->route('DELETE', '/s3/buckets/{bucketName:[a-zA-Z0-9-_]+}', 'r_27'); + $routes->route('GET', '/s3/buckets/{bucketName:[a-zA-Z0-9-_]+}/objects', 'r_28'); + $routes->route('POST', '/s3/buckets/{bucketName:[a-zA-Z0-9-_]+}/objects', 'r_29'); + $routes->route('GET', '/ec2/instances', 'r_30'); + $routes->route('POST', '/ec2/instances', 'r_31'); + $routes->route('DELETE', '/ec2/instances/{instanceId:i-\d+}', 'r_32'); + $routes->route('GET', '/ec2/volumes', 'r_33'); + $routes->route('POST', '/ec2/volumes', 'r_34'); + $routes->route('DELETE', '/ec2/volumes/{volumeId:vol-\d+}', 'r_35'); + $routes->route('GET', '/lambda/functions', 'r_36'); + $routes->route('POST', '/lambda/functions', 'r_37'); + $routes->route('DELETE', '/lambda/functions/{functionName:[a-zA-Z0-9-_]+}', 'r_38'); + $routes->route('POST', '/lambda/functions/{functionName:[a-zA-Z0-9-_]+}/invoke', 'r_39'); + $routes->route('GET', '/customers', 'r_40'); + $routes->route('POST', '/customers', 'r_41'); + $routes->route('GET', '/customers/{customerId:\d+}', 'r_42'); + $routes->route('PUT', '/customers/{customerId:\d+}', 'r_43'); + $routes->route('DELETE', '/customers/{customerId:\d+}', 'r_44'); + $routes->route('GET', '/products', 'r_45'); + $routes->route('POST', '/products', 'r_46'); + $routes->route('GET', '/products/{productId:\d+}', 'r_47'); + $routes->route('PUT', '/products/{productId:\d+}', 'r_48'); + $routes->route('DELETE', '/products/{productId:\d+}', 'r_49'); + $routes->route('GET', '/products/{productId:\d+}/reviews', 'r_50'); + $routes->route('GET', '/customers/{customerId:\d+}/orders', 'r_51'); + $routes->route('POST', '/customers/{customerId:\d+}/orders', 'r_52'); + $routes->route('GET', '/customers/{customerId:\d+}/orders/{orderId:\d+}', 'r_53'); + $routes->route('PUT', '/customers/{customerId:\d+}/orders/{orderId:\d+}', 'r_54'); + $routes->route('DELETE', '/customers/{customerId:\d+}/orders/{orderId:\d+}', 'r_55'); + $routes->route('GET', '/customers/{customerId:\d+}/orders/{orderId:\d+}/items', 'r_56'); + $routes->route('GET', '/customers/{customerId:\d+}/orders/{orderId:\d+}/items/{itemId:\d+}', 'r_57'); + $routes->route('POST', '/customers/{customerId:\d+}/orders/{orderId:\d+}/items', 'r_58'); + $routes->route('PUT', '/customers/{customerId:\d+}/orders/{orderId:\d+}/items/{itemId:\d+}', 'r_59'); + $routes->route('DELETE', '/customers/{customerId:\d+}/orders/{orderId:\d+}/items/{itemId:\d+}', 'r_60'); + $routes->route('GET', '/customers/{customerId:\d+}/cart', 'r_61'); + $routes->route('POST', '/customers/{customerId:\d+}/cart/items', 'r_62'); + $routes->route('PUT', '/customers/{customerId:\d+}/cart/items/{itemId:\d+}', 'r_63'); + $routes->route('DELETE', '/customers/{customerId:\d+}/cart/items/{itemId:\d+}', 'r_64'); + $routes->route('GET', '/coupons', 'r_65'); + $routes->route('POST', '/coupons', 'r_66'); + $routes->route('GET', '/coupons/{couponCode:[a-zA-Z0-9-_]+}', 'r_67'); + $routes->route('PUT', '/coupons/{couponCode:[a-zA-Z0-9-_]+}', 'r_68'); + $routes->route('DELETE', '/coupons/{couponCode:[a-zA-Z0-9-_]+}', 'r_69'); + $routes->route('GET', '/categories', 'r_70'); + $routes->route('POST', '/categories', 'r_71'); + $routes->route('GET', '/categories/{categoryId:\d+}', 'r_72'); + $routes->route('PUT', '/categories/{categoryId:\d+}', 'r_73'); + $routes->route('DELETE', '/categories/{categoryId:\d+}', 'r_74'); + $routes->route('GET', '/categories/{categoryId:\d+}/products', 'r_75'); + $routes->route('POST', '/api/auth/login', 'r_76'); + $routes->route('POST', '/api/auth/logout', 'r_77'); + $routes->route('GET', '/api/users/{userId:\d+}/profile', 'r_78'); + $routes->route('GET', '/api/users/{userId:\d+}/accounts', 'r_79'); + $routes->route('POST', '/api/users/{userId:\d+}/accounts', 'r_80'); + $routes->route('GET', '/api/users/{userId:\d+}/accounts/{accountId:\d+}', 'r_81'); + $routes->route('PUT', '/api/users/{userId:\d+}/accounts/{accountId:\d+}', 'r_82'); + $routes->route('DELETE', '/api/users/{userId:\d+}/accounts/{accountId:\d+}', 'r_83'); + $routes->route('GET', '/api/users/{userId:\d+}/accounts/{accountId:\d+}/transactions', 'r_84'); + $routes->route('POST', '/api/users/{userId:\d+}/accounts/{accountId:\d+}/transactions', 'r_85'); + $routes->route('GET', '/api/users/{userId:\d+}/accounts/{accountId:\d+}/transactions/{transactionId:\d+}', 'r_86'); + $routes->route('PUT', '/api/users/{userId:\d+}/accounts/{accountId:\d+}/transactions/{transactionId:\d+}', 'r_87'); + $routes->route('DELETE', '/api/users/{userId:\d+}/accounts/{accountId:\d+}/transactions/{transactionId:\d+}', 'r_88'); + $routes->route('GET', '/api/users/{userId:\d+}/investments', 'r_89'); + $routes->route('POST', '/api/users/{userId:\d+}/investments', 'r_90'); + $routes->route('GET', '/api/users/{userId:\d+}/investments/{investmentId:\d+}', 'r_91'); + $routes->route('PUT', '/api/users/{userId:\d+}/investments/{investmentId:\d+}', 'r_92'); + $routes->route('DELETE', '/api/users/{userId:\d+}/investments/{investmentId:\d+}', 'r_93'); + $routes->route('GET', '/api/users/{userId:\d+}/loans', 'r_94'); + $routes->route('POST', '/api/users/{userId:\d+}/loans', 'r_95'); + $routes->route('GET', '/api/users/{userId:\d+}/loans/{loanId:\d+}', 'r_96'); + $routes->route('PUT', '/api/users/{userId:\d+}/loans/{loanId:\d+}', 'r_97'); + $routes->route('DELETE', '/api/users/{userId:\d+}/loans/{loanId:\d+}', 'r_98'); + $routes->route('GET', '/api/business/{businessId:\d+}/audit_trail', 'r_99'); + $routes->route('GET', '/api/business/{businessId:\d+}/employees/{employeeId:\d+}/payroll', 'r_100'); + $routes->route('POST', '/api/business/{businessId:\d+}/invoices', 'r_101'); + $routes->route('GET', '/api/business/{businessId:\d+}/invoices/{invoiceId:\d+}', 'r_102'); + $routes->route('PUT', '/api/business/{businessId:\d+}/invoices/{invoiceId:\d+}', 'r_103'); + $routes->route('GET', '/api/compliance/reports/{year:\d{4}}/{quarter:Q[1-4]}', 'r_104'); + $routes->route('GET', '/internal/fraud_detection/patterns', 'r_105'); + $routes->route('POST', '/internal/alerts/system', 'r_106'); + $routes->route('GET', '/payment_intents', 'r_107'); + $routes->route('POST', '/payment_intents', 'r_108'); + $routes->route('GET', '/payment_intents/{paymentIntentId:[a-z_]+}', 'r_109'); + $routes->route('PUT', '/payment_intents/{paymentIntentId:[a-z_]+}', 'r_110'); + $routes->route('DELETE', '/payment_intents/{paymentIntentId:[a-z_]+}', 'r_111'); + $routes->route('GET', '/charges', 'r_112'); + $routes->route('POST', '/charges', 'r_113'); + $routes->route('GET', '/charges/{chargeId:[a-z_]+}', 'r_114'); + $routes->route('PUT', '/charges/{chargeId:[a-z_]+}', 'r_115'); + $routes->route('GET', '/subscriptions', 'r_116'); + $routes->route('POST', '/subscriptions', 'r_117'); + $routes->route('GET', '/subscriptions/{subscriptionId:[a-z_]+}', 'r_118'); + $routes->route('DELETE', '/subscriptions/{subscriptionId:[a-z_]+}', 'r_119'); + $routes->route('PUT', '/subscriptions/{subscriptionId:[a-z_]+}', 'r_120'); + $routes->route('GET', '/invoices', 'r_121'); + $routes->route('POST', '/invoices', 'r_122'); + $routes->route('GET', '/invoices/{invoiceId:[a-z_]+}', 'r_123'); + $routes->route('PUT', '/invoices/{invoiceId:[a-z_]+}', 'r_124'); + $routes->route('DELETE', '/invoices/{invoiceId:[a-z_]+}', 'r_125'); + $routes->route('GET', '/products', 'r_126'); + $routes->route('POST', '/products', 'r_127'); + $routes->route('GET', '/products/{productId:[a-z_]+}', 'r_128'); + $routes->route('PUT', '/products/{productId:[a-z_]+}', 'r_129'); + $routes->route('DELETE', '/products/{productId:[a-z_]+}', 'r_130'); + $routes->route('GET', '/plans', 'r_131'); + $routes->route('POST', '/plans', 'r_132'); + $routes->route('GET', '/plans/{planId:[a-z_]+}', 'r_133'); + $routes->route('PUT', '/plans/{planId:[a-z_]+}', 'r_134'); + $routes->route('DELETE', '/plans/{planId:[a-z_]+}', 'r_135'); + $routes->route('GET', '/refunds', 'r_136'); + $routes->route('POST', '/refunds', 'r_137'); + $routes->route('GET', '/refunds/{refundId:[a-z_]+}', 'r_138'); + $routes->route('GET', '/events', 'r_139'); + $routes->route('GET', '/events/{eventId:[a-z_]+}', 'r_140'); + $routes->route('GET', '/coupons', 'r_141'); + $routes->route('POST', '/coupons', 'r_142'); + $routes->route('GET', '/coupons/{couponId:[a-z_]+}', 'r_143'); + $routes->route('PUT', '/coupons/{couponId:[a-z_]+}', 'r_144'); + $routes->route('DELETE', '/coupons/{couponId:[a-z_]+}', 'r_145'); + $routes->route('GET', '/boards', 'r_146'); + $routes->route('POST', '/boards', 'r_147'); + $routes->route('GET', '/boards/{boardId:[0-9a-f]{24}}', 'r_148'); + $routes->route('PUT', '/boards/{boardId:[0-9a-f]{24}}', 'r_149'); + $routes->route('DELETE', '/boards/{boardId:[0-9a-f]{24}}', 'r_150'); + $routes->route('GET', '/boards/{boardId:[0-9a-f]{24}}/elements', 'r_151'); + $routes->route('POST', '/boards/{boardId:[0-9a-f]{24}}/elements', 'r_152'); + $routes->route('GET', '/boards/{boardId:[0-9a-f]{24}}/elements/{elementId:[0-9a-f]{24}}', 'r_153'); + $routes->route('PUT', '/boards/{boardId:[0-9a-f]{24}}/elements/{elementId:[0-9a-f]{24}}', 'r_154'); + $routes->route('DELETE', '/boards/{boardId:[0-9a-f]{24}}/elements/{elementId:[0-9a-f]{24}}', 'r_155'); + $routes->route('GET', '/teams', 'r_156'); + $routes->route('POST', '/teams', 'r_157'); + $routes->route('GET', '/teams/{teamId:[0-9a-f]{24}}', 'r_158'); + $routes->route('PUT', '/teams/{teamId:[0-9a-f]{24}}', 'r_159'); + $routes->route('DELETE', '/teams/{teamId:[0-9a-f]{24}}', 'r_160'); + $routes->route('GET', '/teams/{teamId:[0-9a-f]{24}}/boards', 'r_161'); + $routes->route('GET', '/boards/{boardId:[0-9a-f]{24}}/comments', 'r_162'); + $routes->route('POST', '/boards/{boardId:[0-9a-f]{24}}/comments', 'r_163'); + $routes->route('GET', '/boards/{boardId:[0-9a-f]{24}}/comments/{commentId:[0-9a-f]{24}}', 'r_164'); + $routes->route('PUT', '/boards/{boardId:[0-9a-f]{24}}/comments/{commentId:[0-9a-f]{24}}', 'r_165'); + $routes->route('DELETE', '/boards/{boardId:[0-9a-f]{24}}/comments/{commentId:[0-9a-f]{24}}', 'r_166'); + $routes->route('GET', '/boards/{boardId:[0-9a-f]{24}}/export', 'r_167'); + $routes->route('POST', '/boards/{boardId:[0-9a-f]{24}}/import', 'r_168'); + $routes->route('GET', '/api/users/{userId:\d+}/devices', 'r_169'); + $routes->route('POST', '/api/users/{userId:\d+}/devices', 'r_170'); + $routes->route('GET', '/api/users/{userId:\d+}/devices/{deviceId:\d+}', 'r_171'); + $routes->route('PUT', '/api/users/{userId:\d+}/devices/{deviceId:\d+}', 'r_172'); + $routes->route('DELETE', '/api/users/{userId:\d+}/devices/{deviceId:\d+}', 'r_173'); + $routes->route('GET', '/api/users/{userId:\d+}/rooms', 'r_174'); + $routes->route('POST', '/api/users/{userId:\d+}/rooms', 'r_175'); + $routes->route('GET', '/api/users/{userId:\d+}/rooms/{roomId:\d+}', 'r_176'); + $routes->route('PUT', '/api/users/{userId:\d+}/rooms/{roomId:\d+}', 'r_177'); + $routes->route('DELETE', '/api/users/{userId:\d+}/rooms/{roomId:\d+}', 'r_178'); + $routes->route('GET', '/api/users/{userId:\d+}/rooms/{roomId:\d+}/devices', 'r_179'); + $routes->route('POST', '/api/users/{userId:\d+}/rooms/{roomId:\d+}/devices', 'r_180'); + $routes->route('PUT', '/api/users/{userId:\d+}/rooms/{roomId:\d+}/devices/{deviceId:\d+}/status', 'r_181'); + $routes->route('GET', '/api/users/{userId:\d+}/devices/{deviceId:\d+}/metrics', 'r_182'); + $routes->route('GET', '/api/users/{userId:\d+}/devices/{deviceId:\d+}/reports/{reportType:daily|monthly|yearly}', 'r_183'); + $routes->route('GET', '/api/users/{userId:\d+}/notifications', 'r_184'); + $routes->route('POST', '/api/users/{userId:\d+}/notifications', 'r_185'); + $routes->route('GET', '/api/users/{userId:\d+}/notifications/{notificationId:\d+}', 'r_186'); + $routes->route('DELETE', '/api/users/{userId:\d+}/notifications/{notificationId:\d+}', 'r_187'); + $routes->route('GET', '/api/users/{userId:\d+}/scenarios', 'r_188'); + $routes->route('POST', '/api/users/{userId:\d+}/scenarios', 'r_189'); + $routes->route('GET', '/api/users/{userId:\d+}/scenarios/{scenarioId:\d+}', 'r_190'); + $routes->route('PUT', '/api/users/{userId:\d+}/scenarios/{scenarioId:\d+}', 'r_191'); + $routes->route('DELETE', '/api/users/{userId:\d+}/scenarios/{scenarioId:\d+}', 'r_192'); + $routes->route('POST', '/api/users/{userId:\d+}/voice_commands', 'r_193'); + $routes->route('GET', '/api/properties', 'r_194'); + $routes->route('POST', '/api/properties', 'r_195'); + $routes->route('GET', '/api/properties/{propertyId:\d+}', 'r_196'); + $routes->route('PUT', '/api/properties/{propertyId:\d+}', 'r_197'); + $routes->route('DELETE', '/api/properties/{propertyId:\d+}', 'r_198'); + $routes->route('GET', '/api/properties/{propertyId:\d+}/rooms', 'r_199'); + $routes->route('POST', '/api/properties/{propertyId:\d+}/rooms', 'r_200'); + $routes->route('GET', '/api/properties/{propertyId:\d+}/rooms/{roomId:\d+}', 'r_201'); + $routes->route('PUT', '/api/properties/{propertyId:\d+}/rooms/{roomId:\d+}', 'r_202'); + $routes->route('DELETE', '/api/properties/{propertyId:\d+}/rooms/{roomId:\d+}', 'r_203'); + $routes->route('GET', '/api/properties/{propertyId:\d+}/rooms/{roomId:\d+}/bookings', 'r_204'); + $routes->route('POST', '/api/properties/{propertyId:\d+}/rooms/{roomId:\d+}/bookings', 'r_205'); + $routes->route('GET', '/api/properties/{propertyId:\d+}/rooms/{roomId:\d+}/bookings/{bookingId:\d+}', 'r_206'); + $routes->route('PUT', '/api/properties/{propertyId:\d+}/rooms/{roomId:\d+}/bookings/{bookingId:\d+}', 'r_207'); + $routes->route('DELETE', '/api/properties/{propertyId:\d+}/rooms/{roomId:\d+}/bookings/{bookingId:\d+}', 'r_208'); + $routes->route('GET', '/api/properties/{propertyId:\d+}/reviews', 'r_209'); + $routes->route('POST', '/api/properties/{propertyId:\d+}/reviews', 'r_210'); + $routes->route('GET', '/api/properties/{propertyId:\d+}/reviews/{reviewId:\d+}', 'r_211'); + $routes->route('PUT', '/api/properties/{propertyId:\d+}/reviews/{reviewId:\d+}', 'r_212'); + $routes->route('DELETE', '/api/properties/{propertyId:\d+}/reviews/{reviewId:\d+}', 'r_213'); + $routes->route('GET', '/api/properties/{propertyId:\d+}/amenities', 'r_214'); + $routes->route('POST', '/api/properties/{propertyId:\d+}/amenities', 'r_215'); + $routes->route('GET', '/api/properties/{propertyId:\d+}/amenities/{amenityId:\d+}', 'r_216'); + $routes->route('PUT', '/api/properties/{propertyId:\d+}/amenities/{amenityId:\d+}', 'r_217'); + $routes->route('DELETE', '/api/properties/{propertyId:\d+}/amenities/{amenityId:\d+}', 'r_218'); + $routes->route('GET', '/api/users/{userId:\d+}/payments', 'r_219'); + $routes->route('POST', '/api/users/{userId:\d+}/payments', 'r_220'); + $routes->route('GET', '/api/users/{userId:\d+}/payments/{paymentId:\d+}', 'r_221'); + $routes->route('GET', '/api/v1/{lang:en|de}/schools/{schoolId:\d+}/classes/{classId:\d+}/students/{studentId:\d+}/grades/{subjectId:\d+}', 'r_222'); + $routes->route('POST', '/api/v2/{lang:en|de}/manufacturers/{manufacturerId:\d+}/products/{productId:\d+}/variants/{variantId:\d+}/reviews', 'r_223'); + $routes->route('GET', '/api/v1/hotels/{hotelId:\d+}/rooms/{type:single|double|suite}/{view:sea|mountain|city}', 'r_224'); + $routes->route('GET', '/api/locations/{latitude:-?\d+.\d+}/{longitude:-?\d+.\d+}/nearby_stores', 'r_225'); + $routes->route('GET', '/api/users/{userId:\d+}/feed/{year:\d{4}}/{month:\d{2}}/{day:\d{2}}', 'r_226'); + $routes->route('GET', '/api/reports/{reportId:\d+}/{startDate:\d{4}-\d{2}-\d{2}}/{endDate:\d{4}-\d{2}-\d{2}}', 'r_227'); + $routes->route('POST', '/api/users/{userId:\d+}/albums/{albumId:\d+}/photos/upload', 'r_228'); + $routes->route('POST', '/api/orders/{orderId:\d+}/payments/{paymentId:\d+}/confirmation', 'r_229'); + $routes->route('GET', '/admin/dashboard/{filter:daily|weekly|monthly}', 'r_230'); + $routes->route('POST', '/admin/products/{productId:\d+}/bulk-update', 'r_231'); + $routes->route('POST', '/api/workflow/{workflowId:\d+}/stages/{stageId:\d+}/tasks/{taskId:\d+}/subtasks/{subtaskId:\d+}/complete', 'r_232'); + +}; diff --git a/var/.gitignore b/var/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/var/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore