Skip to content

feat: move log directory to uploads folder for persistence on plugin updates#103

Merged
joaquimds merged 7 commits into
masterfrom
feat/persistant-logs
May 21, 2026
Merged

feat: move log directory to uploads folder for persistence on plugin updates#103
joaquimds merged 7 commits into
masterfrom
feat/persistant-logs

Conversation

@commonknowledge-bot
Copy link
Copy Markdown

No description provided.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR moves Join Block’s Monolog file logging from the plugin directory into wp-content/uploads so logs persist across plugin updates, and updates the admin “Logging” settings tab to read from the new location.

Changes:

  • Introduces Logging::getLogDirectory() to resolve (and create) an uploads-based log directory and attempt legacy log migration.
  • Switches both Logging::init() and the Settings log viewer to use the new log directory.
  • Removes the in-repo placeholder log file and updates .gitignore log rules.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 3 comments.

File Description
packages/join-block/src/Settings.php Reads displayed log contents from the new uploads-based log directory.
packages/join-block/src/Logging.php Adds uploads-based log directory resolution/creation + uses it for Monolog initialization.
packages/join-block/logs/an_empty_log.txt Removes the placeholder file that previously kept packages/join-block/logs/ present.
.gitignore Removes repo-root logs/ ignore exceptions, leaving only *.log patterns.
Comments suppressed due to low confidence (2)

packages/join-block/src/Settings.php:249

  • The log viewer assumes the first entry from scandir() is a readable log file. When the directory is empty, scandir() returns only '.' and '..', so file_get_contents() will target '..' and fall back to the generic error message. Consider filtering out '.'/'..' (and any non-regular files) and showing a clearer 'No logs yet' message when no log files exist.
            $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
            $log = $logfiles ? @file_get_contents($joinBlockLogLocation . '/' . $logfiles[0]) : "";
            if (!$log) {
                $log = 'Could not load error log. Please contact Common Knowledge support.';
            }

packages/join-block/logs/an_empty_log.txt:1

  • Removing the only tracked file in packages/join-block/logs/ deletes the directory from the repo, but PHPUnit’s SessionLockTestProcess writes to tests/../logs/tests.log without creating the directory. This will make fopen() fail and can break the CI PHP test workflow. Either keep the directory (e.g., a .gitkeep) or update the tests to write into a temp dir and mkdir as needed.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/join-block/src/Logging.php
Comment thread packages/join-block/src/Logging.php Outdated
Comment thread packages/join-block/src/Logging.php Outdated
joaquimds and others added 3 commits May 21, 2026 13:17
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 6 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

packages/join-block/src/Settings.php:250

  • The log contents are interpolated directly into HTML (<pre>...</pre>) without escaping. Because logs include user-supplied values (emails, payloads), this can enable stored XSS in the WP admin when viewing the log tab. Escape the log output (e.g., esc_html($log)) before rendering.
            $log = $logfiles ? @file_get_contents($joinBlockLogLocation . '/' . $logfiles[0]) : "";
            if (!$log) {
                $log = 'Could not load error log. Please contact Common Knowledge support.';
            }
            return "<pre style=\"max-width:150ch\">$log</pre>";

Comment thread packages/join-block/src/Logging.php
Comment thread packages/join-block/src/Logging.php
Comment thread packages/join-block/src/Settings.php Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 6 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (1)

packages/join-block/tests/SessionLockTest.php:34

  • The test now writes to a fixed filename in the shared system temp dir (/tmp/join-block-tests.log). This can cause flaky tests if multiple test runs/processes execute on the same machine concurrently. Consider generating a unique temp filename (e.g. via tempnam() / PID) and passing it to the child process (argv/env) so each run is isolated.
        $logFile = sys_get_temp_dir() . "/join-block-tests.log";
        // Ensure clean log file output
        // phpcs:ignore WordPress.WP.AlternativeFunctions.unlink_unlink
        @unlink($logFile);

        $shellKey = escapeshellarg($lockKey);

        // Start two processes in parallel
        // Each script takes 1 second to complete. Therefore, if
        // they run in parallel, they should both complete in a little
        // over 1 second. However, if they run in series, they will not
        // both be complete until after 2 seconds.
        exec("php $scriptPath $shellKey > /dev/null 2>&1 &");
        exec("php $scriptPath $shellKey > /dev/null 2>&1 &");

Comment thread packages/join-block/src/Settings.php Outdated
Comment thread packages/join-block/src/Logging.php
Comment thread packages/join-block/src/Logging.php
Comment thread packages/join-block/tests/SessionLockTestProcess.php
Comment thread packages/join-block/src/Logging.php
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 6 changed files in this pull request and generated 4 comments.

Comment on lines +18 to +31
// 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;

$candidates = [];
if ($basedir) {
$candidates[] = $basedir . '/join-block-logs';
}
if (defined('WP_CONTENT_DIR')) {
$candidates[] = WP_CONTENT_DIR . '/join-block-logs';
}
Comment on lines +49 to +53
error_log(
'join-block: unable to create a writable log directory (tried: '
. implode(', ', $candidates ?: ['<none>']) . '); '
. 'file-based logging disabled for this request'
);
Comment on lines +59 to +72
if ($created) {
$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);
}
}
Comment on lines +242 to 246
$joinBlockLogLocation = Logging::getLogDirectory();
$logfiles = $joinBlockLogLocation ? scandir($joinBlockLogLocation, SCANDIR_SORT_DESCENDING) : [];
$logfiles = array_values(array_filter($logfiles, function ($file) use ($joinBlockLogLocation) {
return str_starts_with($file, 'debug-') && is_file($joinBlockLogLocation . '/' . $file);
}));
@joaquimds joaquimds merged commit a31311d into master May 21, 2026
4 checks passed
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.

3 participants