From 2699e96dff2f93be2c06743d0818f65642401d25 Mon Sep 17 00:00:00 2001 From: Joaquim d'Souza Date: Thu, 21 May 2026 12:57:55 +0200 Subject: [PATCH 1/5] feat: move log directory to uploads folder for persistance on plugin updates --- .gitignore | 2 -- packages/join-block/logs/an_empty_log.txt | 1 - packages/join-block/src/Logging.php | 32 ++++++++++++++++++++++- packages/join-block/src/Settings.php | 2 +- 4 files changed, 32 insertions(+), 5 deletions(-) delete mode 100644 packages/join-block/logs/an_empty_log.txt diff --git a/.gitignore b/.gitignore index 1ac84db1..69df9537 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,4 @@ # Logs -logs/**/* -!logs/an_empty_log.txt *.log npm-debug.log* yarn-debug.log* diff --git a/packages/join-block/logs/an_empty_log.txt b/packages/join-block/logs/an_empty_log.txt deleted file mode 100644 index 427dd28b..00000000 --- a/packages/join-block/logs/an_empty_log.txt +++ /dev/null @@ -1 +0,0 @@ -No logs yet! \ No newline at end of file diff --git a/packages/join-block/src/Logging.php b/packages/join-block/src/Logging.php index 60df8094..da212347 100644 --- a/packages/join-block/src/Logging.php +++ b/packages/join-block/src/Logging.php @@ -13,12 +13,42 @@ class Logging { + public static function getLogDirectory() + { + $uploads = wp_upload_dir(); + $logLocation = $uploads['basedir'] . '/join-block-logs'; + + if (!is_dir($logLocation)) { + wp_mkdir_p($logLocation); + + // Migrate any pre-existing logs from the old in-plugin location. + // Pre-1.4.26 the plugin wrote logs to packages/join-block/logs/, + // which WordPress wipes on plugin update. + $legacyLocation = __DIR__ . '/../logs'; + if (is_dir($legacyLocation)) { + $legacyFiles = scandir($legacyLocation) ?: []; + foreach ($legacyFiles as $file) { + if ($file === '.' || $file === '..') { + continue; + } + $src = $legacyLocation . '/' . $file; + $dst = $logLocation . '/' . $file; + if (is_file($src) && !file_exists($dst)) { + @copy($src, $dst); + } + } + } + } + + return $logLocation; + } + public static function init() { global $joinBlockLog; $joinBlockLog = new Logger('join-block'); $logFilenameHash = null; - $logLocation = __DIR__ . "/../logs"; + $logLocation = self::getLogDirectory(); $logFiles = scandir($logLocation); foreach ($logFiles as $logFile) { if (str_starts_with($logFile, "debug-")) { diff --git a/packages/join-block/src/Settings.php b/packages/join-block/src/Settings.php index fd3d682a..e605f6cd 100644 --- a/packages/join-block/src/Settings.php +++ b/packages/join-block/src/Settings.php @@ -239,7 +239,7 @@ public static function init() /** @var Html_Field $logField */ $logField = Field::make('html', 'ck_join_flow_log_contents'); $logField->set_html(function () { - $joinBlockLogLocation = __DIR__ . "/../logs"; + $joinBlockLogLocation = Logging::getLogDirectory(); $logfiles = scandir($joinBlockLogLocation, SCANDIR_SORT_DESCENDING); // Ignore file_get_contents error because this will always be a local file // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents From c52fa56011b686338f0b2c2eef4f27cb7c793299 Mon Sep 17 00:00:00 2001 From: Joaquim d'Souza Date: Thu, 21 May 2026 13:06:27 +0200 Subject: [PATCH 2/5] fix: tests --- packages/join-block/tests/SessionLockTest.php | 2 +- packages/join-block/tests/SessionLockTestProcess.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/join-block/tests/SessionLockTest.php b/packages/join-block/tests/SessionLockTest.php index 8cf21a81..0651a239 100644 --- a/packages/join-block/tests/SessionLockTest.php +++ b/packages/join-block/tests/SessionLockTest.php @@ -18,7 +18,7 @@ public function testLockSerializesByKey(): void $scriptPath = __DIR__ . "/SessionLockTestProcess.php"; // Use an email-shaped key to cover the typical webhook/join lock-key form. $lockKey = "test+" . microtime(true) . "@example.com"; - $logFile = __DIR__ . "/../logs/tests.log"; + $logFile = sys_get_temp_dir() . "/join-block-tests.log"; // Ensure clean log file output // phpcs:ignore WordPress.WP.AlternativeFunctions.unlink_unlink @unlink($logFile); diff --git a/packages/join-block/tests/SessionLockTestProcess.php b/packages/join-block/tests/SessionLockTestProcess.php index 04c89862..bc9a14e6 100644 --- a/packages/join-block/tests/SessionLockTestProcess.php +++ b/packages/join-block/tests/SessionLockTestProcess.php @@ -23,7 +23,7 @@ // Set up log file so SessionLockTest can monitor progress of this script global $joinBlockLog; $joinBlockLog = new Logger('join-block-test'); -$joinBlockLogLocation = __DIR__ . '/../logs/tests.log'; +$joinBlockLogLocation = sys_get_temp_dir() . '/join-block-tests.log'; // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen $joinBlockLogFile = fopen($joinBlockLogLocation, 'a'); $joinBlockLog->pushHandler(new StreamHandler($joinBlockLogFile, Level::Info)); From 0c8f35da60435d96f15005ea43226fceeadd271b Mon Sep 17 00:00:00 2001 From: joaquimds Date: Thu, 21 May 2026 13:17:38 +0200 Subject: [PATCH 3/5] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- packages/join-block/src/Logging.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/join-block/src/Logging.php b/packages/join-block/src/Logging.php index da212347..be0b0f2b 100644 --- a/packages/join-block/src/Logging.php +++ b/packages/join-block/src/Logging.php @@ -49,7 +49,10 @@ public static function init() $joinBlockLog = new Logger('join-block'); $logFilenameHash = null; $logLocation = self::getLogDirectory(); - $logFiles = scandir($logLocation); + $logFiles = []; + if (is_dir($logLocation) && is_readable($logLocation)) { + $logFiles = scandir($logLocation) ?: []; + } foreach ($logFiles as $logFile) { if (str_starts_with($logFile, "debug-")) { $parts = explode("-", $logFile); From ccea5b0a0a1eadd037ef15c2126fb87e1bf34e3e Mon Sep 17 00:00:00 2001 From: Joaquim d'Souza Date: Thu, 21 May 2026 13:18:07 +0200 Subject: [PATCH 4/5] fix: better handling of log dir failures --- packages/join-block/src/Logging.php | 73 ++++++++++++++++++++-------- packages/join-block/src/Settings.php | 2 +- 2 files changed, 55 insertions(+), 20 deletions(-) diff --git a/packages/join-block/src/Logging.php b/packages/join-block/src/Logging.php index da212347..6a94ec2d 100644 --- a/packages/join-block/src/Logging.php +++ b/packages/join-block/src/Logging.php @@ -15,15 +15,48 @@ class Logging { public static function getLogDirectory() { - $uploads = wp_upload_dir(); - $logLocation = $uploads['basedir'] . '/join-block-logs'; + // Prefer the uploads dir (survives plugin updates), but fall back to + // WP_CONTENT_DIR if uploads is misconfigured or unwritable. + $uploads = wp_upload_dir(null, false); + $basedir = (is_array($uploads) && empty($uploads['error']) && !empty($uploads['basedir'])) + ? $uploads['basedir'] + : null; - if (!is_dir($logLocation)) { - wp_mkdir_p($logLocation); + $candidates = []; + if ($basedir) { + $candidates[] = $basedir . '/join-block-logs'; + } + if (defined('WP_CONTENT_DIR')) { + $candidates[] = WP_CONTENT_DIR . '/join-block-logs'; + } + + $logLocation = null; + $created = false; + foreach ($candidates as $candidate) { + $existed = is_dir($candidate); + if (!$existed && !wp_mkdir_p($candidate)) { + continue; + } + if (!is_writable($candidate)) { + continue; + } + $logLocation = $candidate; + $created = !$existed; + break; + } - // Migrate any pre-existing logs from the old in-plugin location. - // Pre-1.4.26 the plugin wrote logs to packages/join-block/logs/, - // which WordPress wipes on plugin update. + if ($logLocation === null) { + error_log( + 'join-block: unable to create a writable log directory (tried: ' + . implode(', ', $candidates ?: ['']) . '); ' + . 'file-based logging disabled for this request' + ); + return null; + } + + // On first creation, migrate any pre-existing logs from the old + // in-plugin location, which WordPress wipes on plugin update. + if ($created) { $legacyLocation = __DIR__ . '/../logs'; if (is_dir($legacyLocation)) { $legacyFiles = scandir($legacyLocation) ?: []; @@ -47,21 +80,23 @@ public static function init() { global $joinBlockLog; $joinBlockLog = new Logger('join-block'); - $logFilenameHash = null; $logLocation = self::getLogDirectory(); - $logFiles = scandir($logLocation); - foreach ($logFiles as $logFile) { - if (str_starts_with($logFile, "debug-")) { - $parts = explode("-", $logFile); - $logFilenameHash = $parts[1]; - break; + if ($logLocation !== null) { + $logFilenameHash = null; + $logFiles = scandir($logLocation) ?: []; + foreach ($logFiles as $logFile) { + if (str_starts_with($logFile, "debug-")) { + $parts = explode("-", $logFile); + $logFilenameHash = $parts[1]; + break; + } } + if (!$logFilenameHash) { + $logFilenameHash = bin2hex(random_bytes(18)); + } + $logFilename = "debug-$logFilenameHash.log"; + $joinBlockLog->pushHandler(new RotatingFileHandler("$logLocation/$logFilename", 10, Level::Info)); } - if (!$logFilenameHash) { - $logFilenameHash = bin2hex(random_bytes(18)); - } - $logFilename = "debug-$logFilenameHash.log"; - $joinBlockLog->pushHandler(new RotatingFileHandler("$logLocation/$logFilename", 10, Level::Info)); $joinBlockLog->pushProcessor(new WebProcessor()); } diff --git a/packages/join-block/src/Settings.php b/packages/join-block/src/Settings.php index e605f6cd..b5381db1 100644 --- a/packages/join-block/src/Settings.php +++ b/packages/join-block/src/Settings.php @@ -240,7 +240,7 @@ public static function init() $logField = Field::make('html', 'ck_join_flow_log_contents'); $logField->set_html(function () { $joinBlockLogLocation = Logging::getLogDirectory(); - $logfiles = scandir($joinBlockLogLocation, SCANDIR_SORT_DESCENDING); + $logfiles = $joinBlockLogLocation ? scandir($joinBlockLogLocation, SCANDIR_SORT_DESCENDING) : false; // Ignore file_get_contents error because this will always be a local file // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents $log = $logfiles ? @file_get_contents($joinBlockLogLocation . '/' . $logfiles[0]) : ""; From 4d0e3b4092c4876c7070cef398bfeff0c4e0d8ee Mon Sep 17 00:00:00 2001 From: Joaquim d'Souza Date: Thu, 21 May 2026 13:55:18 +0200 Subject: [PATCH 5/5] fix: bug when log file directory empty --- packages/join-block/src/Settings.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/join-block/src/Settings.php b/packages/join-block/src/Settings.php index b5381db1..90d72469 100644 --- a/packages/join-block/src/Settings.php +++ b/packages/join-block/src/Settings.php @@ -241,6 +241,9 @@ public static function init() $logField->set_html(function () { $joinBlockLogLocation = Logging::getLogDirectory(); $logfiles = $joinBlockLogLocation ? scandir($joinBlockLogLocation, SCANDIR_SORT_DESCENDING) : false; + $logfiles = array_values(array_filter($logfiles, function ($file) use ($joinBlockLogLocation) { + return str_starts_with($file, 'debug-') && is_file($joinBlockLogLocation . '/' . $file); + })); // Ignore file_get_contents error because this will always be a local file // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents $log = $logfiles ? @file_get_contents($joinBlockLogLocation . '/' . $logfiles[0]) : "";