Skip to content

Add support for logging of WordPress Automatic Updates#16

Open
phuochoit wants to merge 4 commits intomainfrom
phuochoit/mwp-1178
Open

Add support for logging of WordPress Automatic Updates#16
phuochoit wants to merge 4 commits intomainfrom
phuochoit/mwp-1178

Conversation

@phuochoit
Copy link
Copy Markdown

@phuochoit phuochoit commented Mar 24, 2026

Summary by CodeRabbit

  • Bug Fixes

    • WP Cron logging now respects the primary tracking setting with fallback to the legacy option.
    • Automatic-updates logging validates input more strictly and processes all core, plugin, and theme entries to avoid missed logs.
    • Version-change checks now log only forward upgrades, preventing false-positive update records.
  • Improvements

    • Captures pre-update WordPress version to improve accuracy of core update reports.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 24, 2026

Walkthrough

WP Cron tracking now prefers settings->options['wp_cron_tracking'] with fallback to advanced_wp_cron_tracking. Automatic-update logging was refactored to handle array results, capture pre-update WP version, iterate core/plugin/theme entries with stricter validation, include auto_updated in contexts, and log only forward upgrades.

Changes

Cohort / File(s) Summary
WP Cron Tracking Setting Prioritization
classes/class-log.php
Log::log() resolves WP Cron tracking from settings->options['wp_cron_tracking'] first, falling back to advanced_wp_cron_tracking when unset; suppression of agent === 'wp_cron' logging remains but is driven by this new resolution order.
Automatic Update Logging Refactor
connectors/class-connector-installer.php
Added public $current_wordpress_version and callback_pre_auto_update($type) to capture pre-update WP version; added callback_load_update_core_php() hook handling. callback_automatic_updates_complete($update_results) now validates array input, early-returns on invalid data, delegates plugin/theme processing, iterates all update_results['core'] entries (skipping invalid ones), uses captured old version for comparisons, logs only forward upgrades, clears captured version after processing, and marks plugin/theme logs with auto_updated => true.

Sequence Diagram(s)

sequenceDiagram
    participant WP as WordPress Updater
    participant CI as Connector_Installer
    participant LOG as Log

    WP->>CI: do_action('pre_auto_update', $type)
    CI->>CI: if $type == 'core' set current_wordpress_version
    WP->>CI: do_action('automatic_updates_complete', $update_results)
    CI->>CI: validate $update_results is array & non-empty
    alt plugin/theme entries present
        CI->>CI: loop plugin/theme entries, validate fields, add auto_updated:true
        CI->>LOG: emit plugin/theme logs (forced)
    end
    alt core entries present
        CI->>CI: iterate core entries, skip invalid, use current_wordpress_version as old, item->version as new
        CI->>LOG: emit core logs only for forward upgrades
        CI->>CI: clear current_wordpress_version
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add support for logging of WordPress Automatic Updates' accurately describes the primary changes in the pull request, which focus on implementing logging for WordPress automatic updates.
Docstring Coverage ✅ Passed Docstring coverage is 87.50% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch phuochoit/mwp-1178

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@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: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@connectors/class-connector-installer.php`:
- Around line 602-605: The theme update loop over $update_results['theme']
accesses $result->item->theme without ensuring $result->item exists; update the
defensive check in the foreach handling $update_results['theme'] to verify
isset($result->item) (or ! empty($result->item)) before checking ->theme so you
don't trigger notices or errors when $result->item is missing; modify the
condition currently using isset($result->result) / true !== $result->result /
empty($result->item->theme) to include a check for $result->item first.
- Around line 574-577: The plugin update loop is accessing $result->item->plugin
without ensuring $result->item exists; update the conditional inside the foreach
over $update_results['plugin'] (the block handling $result) to first check
isset($result->item) (e.g. add ! isset($result->item) to the existing guard) or
reorder checks so isset($result->item) is verified before accessing ->plugin,
and then continue when the item or plugin is missing to avoid PHP warnings.
- Around line 532-543: The loop over $update_results['core'] accesses
$info->item->current without ensuring $info->item exists; add a defensive check
inside the foreach (before reading ->current or ->version) to skip when
$info->item is empty or not an object (e.g. if ( empty($info->item) || !
is_object($info->item) ) continue;), then proceed to set $old_version,
$new_version and $auto_updated as currently done in the foreach body.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e315c785-4202-4d93-8be8-9c19164bdc92

📥 Commits

Reviewing files that changed from the base of the PR and between badb8ed and 5960ba2.

📒 Files selected for processing (2)
  • classes/class-log.php
  • connectors/class-connector-installer.php

Copy link
Copy Markdown

@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.

🧹 Nitpick comments (1)
connectors/class-connector-installer.php (1)

573-599: Defensive check properly added; consider optional file existence validation.

The guard for $result->item on line 575 correctly prevents PHP warnings when accessing $result->item->plugin. This addresses the previous review feedback.

Minor edge case: get_plugin_data() on line 591 may generate a PHP warning if the plugin file doesn't exist (e.g., removed between update completion and logging). While line 595's check prevents invalid log entries, the warning would still occur.

🛡️ Optional: Add file existence check
 $slug        = $result->item->plugin;
 $old_version = isset( $result->item->current_version ) ? $result->item->current_version : '';
+$plugin_file = WP_PLUGIN_DIR . '/' . $slug;
+if ( ! file_exists( $plugin_file ) ) {
+    continue;
+}
-$plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $slug );
+$plugin_data = get_plugin_data( $plugin_file );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@connectors/class-connector-installer.php` around lines 573 - 599, The code
may call get_plugin_data( WP_PLUGIN_DIR . '/' . $slug ) even if the plugin file
no longer exists, causing a PHP warning; before calling get_plugin_data in the
block that processes $result->item->plugin (use $slug from
$result->item->plugin), check that the computed file path (WP_PLUGIN_DIR . '/' .
$slug) exists/is a file (e.g., file_exists() or is_file()) and only call
get_plugin_data and populate $name/$version if the file is present; if the file
is missing, skip adding the log entry (or set $name/$version to empty) so the
later conditional prevents a log and no warning is emitted.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@connectors/class-connector-installer.php`:
- Around line 573-599: The code may call get_plugin_data( WP_PLUGIN_DIR . '/' .
$slug ) even if the plugin file no longer exists, causing a PHP warning; before
calling get_plugin_data in the block that processes $result->item->plugin (use
$slug from $result->item->plugin), check that the computed file path
(WP_PLUGIN_DIR . '/' . $slug) exists/is a file (e.g., file_exists() or
is_file()) and only call get_plugin_data and populate $name/$version if the file
is present; if the file is missing, skip adding the log entry (or set
$name/$version to empty) so the later conditional prevents a log and no warning
is emitted.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8312d3a9-b576-40f2-9f20-9c4ca8471a6b

📥 Commits

Reviewing files that changed from the base of the PR and between 5960ba2 and a183530.

📒 Files selected for processing (1)
  • connectors/class-connector-installer.php

Copy link
Copy Markdown

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@connectors/class-connector-installer.php`:
- Around line 705-713: The call to $this->log(...) is not forcing core-update
logs when wp_cron tracking is disabled; update the $this->log invocation (in the
same block that sets $this->current_wordpress_version = '') to pass
$auto_updated as the forced_log parameter (i.e. add $auto_updated as the final
argument) so core auto-update events are always logged the same way as in
callback_automatic_updates_complete(); leave the subsequent
$this->current_wordpress_version = '' line unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b6baad8b-14b3-44d2-8a41-baf13537f4c6

📥 Commits

Reviewing files that changed from the base of the PR and between a183530 and 27fa893.

📒 Files selected for processing (1)
  • connectors/class-connector-installer.php

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 6, 2026

Copy link
Copy Markdown

@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.

♻️ Duplicate comments (2)
connectors/class-connector-installer.php (2)

731-737: ⚠️ Potential issue | 🟠 Major

Force logging for auto core updates in _core_updated_successfully.

When $auto_updated is true, this call still relies on default forced_log = false. If cron tracking suppresses normal logs, the core-update event can be dropped. Pass $auto_updated as the final argument.

🛠️ Proposed fix
 		$this->log(
 			$message,
 			compact( 'old_version', 'new_version', 'auto_updated' ),
 			null,
 			'wordpress', // phpcs:ignore -- fix format text.
-			'updated'
+			'updated',
+			null,
+			$auto_updated
 		);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@connectors/class-connector-installer.php` around lines 731 - 737, The call to
$this->log in _core_updated_successfully currently omits the $forced_log
parameter so auto core updates can be suppressed by cron tracking; update the
$this->log invocation inside _core_updated_successfully to pass the
$auto_updated boolean as the final argument (forced_log) so when $auto_updated
is true the event is always forced to be logged, leaving the existing message,
context (compact('old_version','new_version','auto_updated')), level/null and
category ('wordpress','updated') arguments unchanged.

572-575: ⚠️ Potential issue | 🟡 Minor

Guard $info->item before accessing ->version.

Line 573 dereferences $info->item->version before confirming item exists and is an object, which can emit notices on malformed update payloads.

🛠️ Proposed fix
-		foreach ( $update_results['core'] as $info ) {
-			if ( ! is_object( $info ) || empty( $info->item->version ) ) {
+		foreach ( $update_results['core'] as $info ) {
+			if ( ! is_object( $info ) || ! isset( $info->item ) || ! is_object( $info->item ) || empty( $info->item->version ) ) {
 				continue;
 			}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@connectors/class-connector-installer.php` around lines 572 - 575, The loop
over $update_results['core'] dereferences $info->item->version without ensuring
$info->item exists or is an object; update the guard in the foreach (
$update_results['core'] as $info ) to verify $info is an object and that
$info->item exists and is an object (or at least non-empty) before accessing
->version (e.g., check isset/empty and is_object on $info->item), and skip the
iteration if those checks fail so $info->item->version is only accessed when
safe.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@connectors/class-connector-installer.php`:
- Around line 731-737: The call to $this->log in _core_updated_successfully
currently omits the $forced_log parameter so auto core updates can be suppressed
by cron tracking; update the $this->log invocation inside
_core_updated_successfully to pass the $auto_updated boolean as the final
argument (forced_log) so when $auto_updated is true the event is always forced
to be logged, leaving the existing message, context
(compact('old_version','new_version','auto_updated')), level/null and category
('wordpress','updated') arguments unchanged.
- Around line 572-575: The loop over $update_results['core'] dereferences
$info->item->version without ensuring $info->item exists or is an object; update
the guard in the foreach ( $update_results['core'] as $info ) to verify $info is
an object and that $info->item exists and is an object (or at least non-empty)
before accessing ->version (e.g., check isset/empty and is_object on
$info->item), and skip the iteration if those checks fail so
$info->item->version is only accessed when safe.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9da87136-4e88-4334-8427-13df2c92130a

📥 Commits

Reviewing files that changed from the base of the PR and between 27fa893 and 064f9ed.

📒 Files selected for processing (1)
  • connectors/class-connector-installer.php

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants