Skip to content

feat: add CodeIgniter detector & analyzer#1335

Merged
hahwul merged 3 commits intomainfrom
feat/codeigniter-detector-analyzer
Apr 29, 2026
Merged

feat: add CodeIgniter detector & analyzer#1335
hahwul merged 3 commits intomainfrom
feat/codeigniter-detector-analyzer

Conversation

@hahwul
Copy link
Copy Markdown
Member

@hahwul hahwul commented Apr 29, 2026

Summary

  • Closes Add CodeIgniter detector & analyzer (php web framework) #1204. Adds a php_codeigniter detector and analyzer covering CodeIgniter 4 (app/Config/Routes.php) and CodeIgniter 3 (application/config/routes.php).
  • Detects via composer.json (codeigniter4/framework), the spark CLI, the routes config files, and CodeIgniter\ namespace usage. Generic markers like extends BaseController are intentionally avoided (Laravel uses the same alias).
  • Analyzer parses CI4 router DSL: $routes->get/post/put/patch/delete/options/head, match, add, resource, presenter, group(prefix, [opts]?, fn), environment. CI3 entries ($route['products/(:num)'] = '...') are also supported.
  • Path placeholders (:num) (:any) (:segment) (:alpha) (:alphanum) (:hash) are normalized to {name} braces and emitted as path params. Group bodies are stripped before sibling-level scans to avoid double-counting.
  • Wires Php::CodeIgniter into src/detector/detector.cr, src/analyzer/analyzer.cr, and src/techs/techs.cr (php_codeigniter).

Test plan

  • crystal spec spec/unit_test/detector/php/codeigniter_detector_spec.cr (6 examples)
  • crystal spec spec/functional_test/testers/php/codeigniter_spec.cr (96 examples — fixture covers verbs, match/add, resource, presenter, group with/without options, environment)
  • crystal spec — full suite, 7119 examples, 0 failures

CodeIgniter 4 router DSL ($routes->get/post/match/add/resource/presenter/
group/environment) plus CI3 $route['…'] config parsing. Path placeholders
((:num), (:any), (:segment), (:alpha), (:alphanum), (:hash)) are normalized
to {name} braces.
@github-actions github-actions Bot added 🔎 detector Issue for Detector 🔬 analyzer Issue for Analyzer 💊 spec Issue for test codes labels Apr 29, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for the CodeIgniter framework (versions 3 and 4) by adding a new detector and analyzer. The implementation includes logic for parsing routes, groups, resources, and presenters, along with corresponding functional and unit tests. Feedback focuses on ensuring that group prefixes and resource names are normalized to handle placeholders correctly and that CodeIgniter 3 routes without explicit method qualifiers are expanded to include all standard HTTP verbs.

working_content.scan(group_pattern).each do |match|
group_prefix = match[1]
group_content = match[2]
new_prefix = build_full_path(prefix, group_prefix)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The group_prefix should be normalized before being used to build the full path. CodeIgniter 4 allows placeholders like (:segment) or (:any) in group prefixes. Without normalization, these placeholders will remain in the final endpoint path in their raw format (e.g., /api/(:segment)/users) instead of the standard brace format (e.g., /api/{segment}/users), which may affect parameter detection.

        new_prefix = build_full_path(prefix, normalize_route(group_prefix))

resource_pattern = /\$routes->resource\s*\(\s*['"]([^'"]+)['"][^)]*\)/mi
working_content.scan(resource_pattern).each do |match|
resource_name = match[1]
full_resource_path = build_full_path(prefix, resource_name)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to group prefixes, the resource_name should be normalized. While typically a simple string, CodeIgniter allows more complex paths in resource definitions which might include placeholders. Normalizing ensures consistency in the emitted endpoint paths.

        full_resource_path = build_full_path(prefix, normalize_route(resource_name))

presenter_pattern = /\$routes->presenter\s*\(\s*['"]([^'"]+)['"][^)]*\)/mi
working_content.scan(presenter_pattern).each do |match|
resource_name = match[1]
full_resource_path = build_full_path(prefix, resource_name)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The resource_name for presenters should also be normalized to handle any potential placeholders or path segments correctly.

        full_resource_path = build_full_path(prefix, normalize_route(resource_name))

Comment on lines +132 to +135
method = method_qualifier ? method_qualifier.to_s.upcase : "GET"
normalized = normalize_route(route_path)
params = extract_ci_path_params(normalized)
endpoints << Endpoint.new(normalized, method, params, details.dup)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

In CodeIgniter 3, if a route is defined without an explicit HTTP verb qualifier (e.g., $route['products'] = '...'), it matches all HTTP methods. The current implementation defaults to GET, which significantly underestimates the attack surface. It should instead emit all standard HTTP verbs, similar to how $routes->add() is handled in the CI4 analyzer.

        normalized = normalize_route(route_path)
        params = extract_ci_path_params(normalized)

        if method_qualifier
          endpoints << Endpoint.new(normalized, method_qualifier.to_s.upcase, params, details.dup)
        else
          ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"].each do |method|
            endpoints << Endpoint.new(normalized, method, params, details.dup)
          end
        end

hahwul added 2 commits April 29, 2026 14:43
…routes

- Pass group/resource/presenter names through normalize_route so routes
  like group('tenant/(:num)', ...) emit /tenant/{num}/... instead of a
  literal placeholder URL.
- CI3 $route['x'] = '...' now expands to all HTTP verbs (CI3 default);
  the second [...] index is only treated as a verb when it is one of the
  known CI3 verbs, avoiding misreading config keys like ['namespace'].
- Parenthesize the ResourceController + RESTful detector clause for clarity.
- Extend the fixture with a nested group and a placeholder-prefixed group.
@hahwul hahwul merged commit 94f1beb into main Apr 29, 2026
10 checks passed
@hahwul hahwul deleted the feat/codeigniter-detector-analyzer branch April 29, 2026 09:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔬 analyzer Issue for Analyzer 🔎 detector Issue for Detector 💊 spec Issue for test codes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add CodeIgniter detector & analyzer (php web framework)

1 participant