Skip to content

Commit da68a19

Browse files
chore: add support for 'themeisle_log_event'
1 parent c80d5b8 commit da68a19

File tree

2 files changed

+74
-23
lines changed

2 files changed

+74
-23
lines changed

includes/admin/feedzy-rss-feeds-log.php

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ public function set_context( array $context ) {
269269
*/
270270
public static function log( $level, $message, array $context = array() ) {
271271
$instance = self::get_instance();
272-
$instance->write_log( $level, $message, $context );
272+
$instance->add_log_record( $level, $message, $context );
273273
}
274274

275275
/**
@@ -281,15 +281,11 @@ public static function log( $level, $message, array $context = array() ) {
281281
* @param array<string, mixed> $context The log context.
282282
* @return void
283283
*/
284-
private function write_log( $level, $message, array $context = array() ) {
284+
private function add_log_record( $level, $message, array $context = array() ) {
285285
if ( self::ERROR === $level ) {
286286
$this->increment_log_stat( 'error_count' );
287287
$this->try_accumulate_error_message( $message );
288288
}
289-
290-
if ( ! $this->filesystem ) {
291-
return;
292-
}
293289

294290
if ( $this->level_threshold > $level ) {
295291
return;
@@ -307,33 +303,65 @@ private function write_log( $level, $message, array $context = array() ) {
307303
}
308304
}
309305

310-
$record = array(
306+
$log_entry = array(
311307
'timestamp' => gmdate( 'c' ),
312308
'level' => isset( self::$levels[ $level ] ) ? self::$levels[ $level ] : 'UNKNOWN',
313309
'message' => $message,
314310
'context' => $merged_context,
315311
);
316312

317313
if ( wp_doing_ajax() ) {
318-
$record['doing_ajax'] = true;
314+
$log_entry['doing_ajax'] = true;
319315
}
320316

321317
if ( wp_doing_cron() ) {
322-
$record['doing_cron'] = true;
318+
$log_entry['doing_cron'] = true;
319+
}
320+
321+
$this->append_log_to_file( $log_entry );
322+
}
323+
324+
/**
325+
* Append the log to the log file.
326+
*
327+
* @param array<string, mixed> $log_entry The log entry to append.
328+
* @return void
329+
*/
330+
public function append_log_to_file( $log_entry ) {
331+
if ( ! $this->filesystem ) {
332+
return;
323333
}
324-
325-
// Write log entry
326-
$formatted = wp_json_encode( $record, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) . PHP_EOL;
327334

328335
// Ensure the directory exists before writing.
329336
$log_dir = dirname( $this->filepath );
330337
if ( ! $this->filesystem->is_dir( $log_dir ) ) {
331338
$this->setup_log_directory();
332339
}
333340

341+
$formatted = wp_json_encode( $log_entry, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) . PHP_EOL;
342+
334343
error_log( $formatted, 3, $this->filepath );
335344
}
336345

346+
/**
347+
* Fallback method to append log to ThemeIsle's logging system.
348+
*
349+
* @param array<string, mixed> $log_entry Log entry to append.
350+
* @return void
351+
*/
352+
public function append_to_themeisle_log( $log_entry ) {
353+
354+
$formatted_message = $log_entry['message'];
355+
if ( ! empty( $log_entry['context'] ) ) {
356+
$formatted_message .= ' ' . wp_json_encode( $log_entry['context'], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
357+
}
358+
359+
$function_signature = isset( $log_entry['context']['function'] ) ? $log_entry['context']['function'] : 'unknown';
360+
$line_number = isset( $log_entry['context']['line'] ) ? $log_entry['context']['line'] : null;
361+
362+
do_action( 'themeisle_log_event', FEEDZY_NAME, $formatted_message, $log_entry['level'], $function_signature, $line_number );
363+
}
364+
337365
/**
338366
* Determine the caller origin (Class::method() or function()) for the current log entry,
339367
* returning both the function signature and source line number.

tests/test-log.php

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,32 @@ private function assertIsType( $type, $value, $message = '' ) {
5454
}
5555
}
5656

57+
/**
58+
* Reset the logger singleton to ensure fresh state per test.
59+
*/
60+
private function reset_logger_singleton() {
61+
if ( class_exists( 'Feedzy_Rss_Feeds_Log' ) ) {
62+
$ref = new ReflectionClass( 'Feedzy_Rss_Feeds_Log' );
63+
if ( $ref->hasProperty( 'instance' ) ) {
64+
$prop = $ref->getProperty( 'instance' );
65+
$prop->setAccessible( true );
66+
$prop->setValue( null, null );
67+
}
68+
}
69+
}
70+
5771
/**
5872
* Set up test environment.
5973
*/
6074
public function setUp(): void {
6175
parent::setUp();
6276

63-
// Create a fresh logger instance for each test
77+
// Ensure fresh singleton for each test.
78+
$this->reset_logger_singleton();
6479
$this->logger = Feedzy_Rss_Feeds_Log::get_instance();
6580

66-
// Set up test log directory
67-
$upload_dir = wp_upload_dir();
68-
$test_log_dir = $upload_dir['basedir'] . '/feedzy-logs';
69-
$this->test_log_path = $test_log_dir . '/feedzy.jsonl';
81+
// Use the class API to determine the log path.
82+
$this->test_log_path = $this->logger->get_log_file_path();
7083

7184
// Clean up any existing log files
7285
if ( file_exists( $this->test_log_path ) ) {
@@ -92,6 +105,9 @@ public function tearDown(): void {
92105
// Reset options
93106
delete_option( Feedzy_Rss_Feeds_Log::STATS_OPTION_KEY );
94107
delete_option( 'feedzy-settings' );
108+
109+
// Reset the singleton to avoid side effects between tests.
110+
$this->reset_logger_singleton();
95111

96112
parent::tearDown();
97113
}
@@ -219,6 +235,10 @@ public function test_context_setting() {
219235
$logs = $this->logger->get_recent_logs( 1 );
220236
$this->assertEquals( 123, $logs[0]['context']['import_id'] );
221237
$this->assertEquals( 'https://example.com/feed.xml', $logs[0]['context']['feed_url'] );
238+
239+
// New: origin should be auto-injected.
240+
$this->assertArrayHasKey( 'function', $logs[0]['context'] );
241+
$this->assertArrayHasKey( 'line', $logs[0]['context'] );
222242
}
223243

224244
/**
@@ -237,8 +257,8 @@ public function test_log_entry_structure() {
237257
$this->assertArrayHasKey( 'message', $log );
238258
$this->assertArrayHasKey( 'context', $log );
239259

240-
// Validate timestamp format (ISO 8601)
241-
$this->assertMatchesRegularExpression( '/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+\d{2}:\d{2}$/', $log['timestamp'] );
260+
// Validate timestamp format (ISO 8601, allow Z or explicit offset)
261+
$this->assertMatchesRegularExpression( '/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\+\d{2}:\d{2}|Z)$/', $log['timestamp'] );
242262
}
243263

244264
/**
@@ -376,8 +396,9 @@ public function test_email_configuration() {
376396
);
377397
update_option( 'feedzy-settings', $settings );
378398

379-
// Recreate logger to pick up new settings
380-
$this->logger = new Feedzy_Rss_Feeds_Log();
399+
// Recreate logger singleton to pick up new settings
400+
$this->reset_logger_singleton();
401+
$this->logger = Feedzy_Rss_Feeds_Log::get_instance();
381402

382403
$this->assertTrue( $this->logger->can_send_email() );
383404
$this->assertEquals( '[email protected]', $this->logger->get_email_address() );
@@ -428,7 +449,8 @@ public function test_settings_initialization() {
428449
update_option( 'feedzy-settings', $settings );
429450

430451
// Create new logger instance to test initialization
431-
$logger = new Feedzy_Rss_Feeds_Log();
452+
$this->reset_logger_singleton();
453+
$logger = Feedzy_Rss_Feeds_Log::get_instance();
432454

433455
$this->assertEquals( Feedzy_Rss_Feeds_Log::DEBUG, $logger->level_threshold );
434456
$this->assertTrue( $logger->can_send_email );
@@ -447,7 +469,8 @@ public function test_invalid_settings_values() {
447469
);
448470
update_option( 'feedzy-settings', $settings );
449471

450-
$logger = new Feedzy_Rss_Feeds_Log();
472+
$this->reset_logger_singleton();
473+
$logger = Feedzy_Rss_Feeds_Log::get_instance();
451474

452475
// Should fallback to default ERROR level
453476
$this->assertEquals( Feedzy_Rss_Feeds_Log::ERROR, $logger->level_threshold );

0 commit comments

Comments
 (0)