Skip to content

Conversation

@kjdev
Copy link
Owner

@kjdev kjdev commented Apr 22, 2025

Summary by CodeRabbit

  • New Features

    • Compression and decompression contexts are now represented as dedicated PHP objects (Brotli\Compress\Context and Brotli\UnCompress\Context) instead of generic resources.
    • Added comprehensive Brotli-related constants for easier configuration and usage.
  • Documentation

    • Updated documentation to reflect the new object-based API and improved type clarity for all context-related functions.
  • Refactor

    • Modernized the extension's API and internal logic to use PHP objects for context management, enhancing type safety and structure.
@coderabbitai
Copy link

coderabbitai bot commented Apr 22, 2025

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

The changes modernize the Brotli PHP extension by replacing legacy resource-based state management for incremental compression and decompression with dedicated PHP objects. New final classes, Brotli\Compress\Context and Brotli\UnCompress\Context, are introduced to encapsulate context state, and all related functions are updated to use these objects instead of generic resources. The documentation, stubs, and internal implementation are updated accordingly, including the addition of explicit type hints, constants, and namespace organization to improve clarity and type safety.

Changes

File(s) Change Summary
README.md Updated documentation to reflect the switch from resource types to Brotli\Compress\Context and Brotli\UnCompress\Context objects in function signatures and descriptions.
brotli.c Replaced resource-based state management with PHP object-based contexts; introduced new classes for compression and decompression contexts; updated all relevant functions and internal logic to use these objects; registered new classes and handlers in module initialization.
brotli.stub.php Expanded and restructured stubs: added comprehensive Brotli constants, introduced explicit class types for context parameters and return types, created new namespaces and final context classes, and updated all function signatures accordingly.
php_brotli.h Added zend_object std; member to the php_brotli_context struct to enable object-based context management in PHP.

Poem

🐰
Out with the resources, in with the class,
Brotli's new objects have plenty of sass!
Compression and context, now tidy and neat,
With namespaces, constants, and type hints complete.
The code hops forward, so modern and bright—
PHP and Brotli, a future in sight!
🥕


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.
@kjdev
Copy link
Owner Author

kjdev commented Apr 22, 2025

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Apr 22, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (4)
README.md (1)

290-297: Rename $resource in the examples for clarity.
The incremental‑API now returns real objects, yet the examples keep the legacy variable name $resource which can confuse users skimming the docs.

-$resource = brotli_compress_init(); +$ctx = brotli_compress_init(); ... -$compressed .= brotli_compress_add($resource, 'Hello, ', BROTLI_FLUSH); -$compressed .= brotli_compress_add($resource, 'World!', BROTLI_FLUSH); -$compressed .= brotli_compress_add($resource, '', BROTLI_FINISH); +$compressed .= brotli_compress_add($ctx, 'Hello, ', BROTLI_FLUSH); +$compressed .= brotli_compress_add($ctx, 'World!', BROTLI_FLUSH); +$compressed .= brotli_compress_add($ctx, '', BROTLI_FINISH);

Same for the decompression example a few lines below.

brotli.stub.php (1)

60-70: Optional: provide concrete constant values in stubs for IDE support.
UNKNOWN markers work, but most IDEs (PHPStorm, Psalm, etc.) can offer better autocompletion / static analysis when the real literal is present. Consider exporting the numeric values via generate_stubs.php or a small C helper.

brotli.c (2)

1284-1289: Pointer‑sign warning – cast to const uint8_t*.

ctx->next_in is declared as const uint8_t*, but in_buf is char*.
On several compilers this produces a strict‑aliasing / pointer‑sign warning.

- ctx->next_in = in_buf; + ctx->next_in = (const uint8_t *)in_buf;

1417-1420: Secondary unused variable (res) in brotli_uncompress_add.
Same as above – safe to drop.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6eb42b8 and 98d30f0.

📒 Files selected for processing (4)
  • README.md (4 hunks)
  • brotli.c (8 hunks)
  • brotli.stub.php (1 hunks)
  • php_brotli.h (1 hunks)
🔇 Additional comments (2)
php_brotli.h (1)

43-44: zend_object std; looks good – but double‑check ABI compatibility.
Placing zend_object as the last field is the expected layout for “struct -with‑object” patterns and is consistent with the XtOffsetOf() usage in brotli.c. Just make sure no C code still copies the struct by value (it would silently drop the trailing std bytes).

brotli.c (1)

1246-1249: Remove unused variable res.
The variable is never referenced and triggers -Wunused‑parameter warnings.

- zval *res;

[ suggest_nitpick ]

brotli.c Outdated
Comment on lines 858 to 867
#if PHP_VERSION_ID >= 80300
static zend_object *
php_brotli_context_create_object(zend_class_entry *class_type)
{
php_brotli_context *intern = zend_object_alloc(sizeof(php_brotli_context),
class_type);
zend_object_std_init(&intern->std, class_type);
object_properties_init(&intern->std, class_type);
return &intern->std;
}
Copy link

@coderabbitai coderabbitai bot Apr 22, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue

Missing std.handlers assignment → objects leak / wrong destructor.

For PHP ≥ 8.3 the custom creator never assigns the object handlers.
As a result the object keeps the default handlers, and free_obj (which
releases the Brotli state) is never called, causing encoder/decoder
instances to leak.

 zend_object_std_init(&intern->std, class_type); object_properties_init(&intern->std, class_type); +/* hook up our custom handlers so dtor / comparisons work */ +intern->std.handlers = class_type->default_object_handlers + ? class_type->default_object_handlers + : &std_object_handlers; return &intern->std;
Copy link
Owner Author

Choose a reason for hiding this comment

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

@coderabbitai review

Copy link

Choose a reason for hiding this comment

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

🧩 Analysis chain

@kjdev I've reviewed the code regarding the potential issue with object handlers in PHP ≥ 8.3 that was previously identified.

I'm happy to report that the current implementation properly handles object creation and destruction for all PHP versions. The specific issue mentioned in the previous review (missing std.handlers assignment in the PHP 8.3-specific implementation) doesn't appear to be present in the code.

The current implementation:

  1. Has a generic php_brotli_context_create_object function that correctly takes handlers as a parameter and assigns them
  2. Both specialized context creation functions (php_brotli_compress_context_create_object and php_brotli_uncompress_context_create_object) correctly pass their handlers to this function
  3. The handlers are properly initialized with the correct free_obj function that will clean up the Brotli state

No changes are needed as the code already handles this correctly.


🏁 Script executed:

#!/bin/bash # Check if the issue is still present in the PR branch grep -A 20 "php_brotli_context_create_object" brotli.c 

Length of output: 2139


🏁 Script executed:

#!/bin/bash # Check the compress and uncompress object creation functions grep -n -A 20 "php_brotli_compress_context_create_object" brotli.c grep -n -A 20 "php_brotli_uncompress_context_create_object" brotli.c 

Length of output: 5395


🏁 Script executed:

#!/bin/bash # Get the full context of the php_brotli_context_create_object function grep -n -A 40 "php_brotli_context_create_object" brotli.c 

Length of output: 3991


🏁 Script executed:

#!/bin/bash # Check the initialization of handlers grep -n -A 10 "php_brotli_compress_context_object_handlers" brotli.c grep -n -A 10 "php_brotli_uncompress_context_object_handlers" brotli.c 

Length of output: 4041


🏁 Script executed:

#!/bin/bash # Find where the handlers are initialized grep -n -A 30 "memcpy.*php_brotli_compress_context_object_handlers" brotli.c 

Length of output: 1632


🏁 Script executed:

#!/bin/bash # Find where the uncompress handlers are initialized grep -n -A 30 "memcpy.*php_brotli_uncompress_context_object_handlers" brotli.c 

Length of output: 1313


🏁 Script executed:

#!/bin/bash # Check for PHP 8.3-specific implementations grep -n -B 5 -A 15 "PHP_VERSION_ID >= 80300" brotli.c 

Length of output: 2186


🏁 Script executed:

#!/bin/bash # Check the MINIT function for PHP 8.3-specific code grep -n -A 100 "ZEND_MINIT_FUNCTION" brotli.c | grep -B 20 -A 20 "80300" 

Length of output: 3605


🏁 Script executed:

#!/bin/bash # Do a more thorough check for PHP 8.3 specific code grep -n "PHP_VERSION_ID >= 80" brotli.c 

Length of output: 627


@kjdev I've reviewed the code regarding the object handlers in PHP ≥ 8.3 that was previously identified as an issue.

I'm happy to report that the current implementation correctly handles object creation and destruction for all PHP versions. The specific issue mentioned in the previous review isn't present in the code.

The current implementation is well-structured:

  • The php_brotli_context_create_object function correctly accepts handlers as a parameter and assigns them to intern->std.handlers
  • Both specialized creation functions properly pass their respective handlers
  • The handlers are correctly initialized with free_obj = php_brotli_context_free_obj
  • For PHP 8.3+, there's also optimization code that sets default_object_handlers on the class

Everything looks good! No changes are needed as the code already handles object lifecycle correctly.


🧬 Code Graph Analysis Results

Relevant snippets from brotli.stub.php (lines 75-85)

function compress(string $data, int $quality = \BROTLI_COMPRESS_LEVEL_DEFAULT, int $mode = \BROTLI_GENERIC): string|false {} function uncompress(string $data, int $length = 0): string|false {} function compress_init(int $quality = \BROTLI_COMPRESS_LEVEL_DEFAULT, int $mode = \BROTLI_GENERIC): Compress\Context|false {} function compress_add(Compress\Context $context, string $data, int $mode = \BROTLI_FLUSH): string|false {} function uncompress_init(): UnCompress\Context|false {} function uncompress_add(UnCompress\Context $context, string $data, int $mode = \BROTLI_FLUSH): string|false {}

These function declarations correspond directly to the ZEND_FUNCTION implementations in brotli.c for the Brotli compression and decompression API, including incremental compression/uncompression contexts and operations.


Summary of key relevant parts in brotli.c

  • Functions implementing Brotli compression and decompression:

    • brotli_compress (lines ~400-440): Compresses a string with optional quality and mode parameters, returns compressed string or false on failure.

    • brotli_uncompress (lines ~520-560): Decompresses a Brotli compressed string with optional max output size, returns decompressed string or false on failure.

    • brotli_compress_init (lines ~445-460): Initializes an incremental compression context object, returns the context or false on failure.

    • brotli_compress_add (lines ~465-520): Adds data to an incremental compression context, with optional mode (flush/finish), returns compressed chunk or false on failure.

    • brotli_uncompress_init (lines ~565-575): Initializes an incremental decompression context object, returns the context or false on failure.

    • brotli_uncompress_add (lines ~580-630): Adds data to an incremental decompression context, with optional mode, returns decompressed chunk or false on failure.

  • Context object management:

    • php_brotli_context struct and related functions for creating, freeing, and managing Brotli compression and decompression contexts.

    • Classes Brotli\Compress\Context and Brotli\UnCompress\Context are registered internally and cannot be directly instantiated by user code; instead, the init functions must be used.

  • Stream wrapper for compress.brotli:// (lines ~350-390): Implements PHP stream wrapper for Brotli compression and decompression, supporting reading and writing streams with Brotli encoding.

  • Output buffering handler (lines ~130-210): Implements an output handler for Brotli compression of PHP output buffers, including initialization, compression streaming, and cleanup.

  • Module initialization and configuration (lines ~270-330): Registers constants, classes, INI entries, output handler aliases, and stream wrappers.

  • APCu serializer support (lines ~640-700): Optional support for serializing and unserializing data compressed with Brotli for APCu caching.


This information provides a comprehensive overview of the Brotli PHP extension's core functionality as implemented in brotli.c, matching the function signatures declared in the stub file.

@kjdev kjdev merged commit 8aae718 into master Apr 22, 2025
74 checks passed
@kjdev kjdev deleted the develop branch April 22, 2025 02:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants