From 509af47a103c0bff968b366b9e9b7fcbb595ed83 Mon Sep 17 00:00:00 2001 From: Hendrix Nwaokolo Date: Sun, 2 Nov 2025 10:54:39 +0100 Subject: [PATCH 1/2] Fix: Add check for scheduled_tasks table existence before querying Prevents fatal error when scheduled_tasks table doesn't exist yet. The plugin now gracefully handles missing tables by: - Checking table existence using DB::getSchemaBuilder()->hasTable() before querying - Wrapping queries in try-catch blocks - Returning null/false instead of throwing exceptions This fixes the issue where plugin settings form crashes with: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'scheduled_tasks' doesn't exist The methods hasScheduledTasks() and getLastExecutionDate() are added with proper error handling to ensure the plugin works even when the scheduled_tasks table hasn't been created yet (common in fresh OJS installations or when scheduled tasks haven't been initialized). --- PlnPlugin.php | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/PlnPlugin.php b/PlnPlugin.php index e624367..c1e6f6d 100644 --- a/PlnPlugin.php +++ b/PlnPlugin.php @@ -28,10 +28,13 @@ use APP\plugins\generic\pln\classes\PLNGatewayPlugin; use APP\plugins\generic\pln\classes\tasks\Depositor; use APP\plugins\generic\pln\pages\PageHandler; +use Carbon\Carbon; +use DateTimeImmutable; use DOMDocument; use DOMElement; use Exception; use GuzzleHttp\Exception\RequestException; +use Illuminate\Support\Facades\DB; use PKP\config\Config; use PKP\core\JSONMessage; use PKP\core\PKPString; @@ -509,6 +512,43 @@ public function hasZipArchive(): bool return class_exists('ZipArchive'); } + /** + * Check if the Acron plugin is enabled, or if the scheduled task has been running lately. + */ + public function hasScheduledTasks(): bool + { + try { + $application = Application::get(); + $products = $application->getEnabledProducts('plugins.generic'); + return isset($products['acron']) || (($lastRun = $this->getLastExecutionDate()) && $lastRun && Carbon::now()->diffInWeeks($lastRun) < 1); + } catch (\Exception $e) { + // If there's an error checking, assume no scheduled tasks are available + return false; + } + } + + /** + * Retrieves the last time the depositor task was executed + */ + public function getLastExecutionDate(): ?DateTimeImmutable + { + try { + // Check if the scheduled_tasks table exists first + if (!DB::getSchemaBuilder()->hasTable('scheduled_tasks')) { + return null; + } + + $lastRun = DB::table('scheduled_tasks') + ->where('class_name', Depositor::class) + ->value('last_run'); + + return $lastRun ? new DateTimeImmutable($lastRun) : null; + } catch (\Exception $e) { + // Table doesn't exist or query failed, return null + return null; + } + } + /** * Get resource * From 1c398210b96d1305eaa285fd5820d734d7c6c6fb Mon Sep 17 00:00:00 2001 From: Hendrix Nwaokolo Date: Sun, 9 Nov 2025 11:27:41 +0100 Subject: [PATCH 2/2] Add scheduled task checks and update notification usage Summary - Fix PLN plugin recognition in OJS by returning the canonical plugin name `plnplugin`. - Use correct PKP notification constants and namespaces. - Ensure success notifications are created without fatals when saving settings or enabling the plugin. --- PlnPlugin.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/PlnPlugin.php b/PlnPlugin.php index c1e6f6d..7840454 100644 --- a/PlnPlugin.php +++ b/PlnPlugin.php @@ -17,7 +17,7 @@ use APP\core\Application; use APP\core\PageRouter; use APP\facades\Repo; -use APP\notification\Notification; +use PKP\notification\Notification; use APP\notification\NotificationManager; use APP\plugins\generic\pln\classes\deposit\Repository; use APP\plugins\generic\pln\classes\deposit\Schema as DepositSchema; @@ -280,7 +280,7 @@ public function callbackLoadCategory(string $hookName, array $args): bool public function registerSchedules(PKPScheduler $scheduler): void { $scheduler - ->addSchedule(new Depositor()) + ->addSchedule(new Depositor([])) ->daily() ->name(Depositor::class) ->withoutOverlapping(); @@ -348,7 +348,7 @@ public function manage($args, $request): JSONMessage $notificationContent = __('plugins.generic.pln.settings.saved'); $currentUser = $request->getUser(); $notificationMgr = new NotificationManager(); - $notificationMgr->createTrivialNotification($currentUser->getId(), PKPNotification::NOTIFICATION_TYPE_SUCCESS, ['contents' => $notificationContent]); + $notificationMgr->createTrivialNotification($currentUser->getId(), Notification::NOTIFICATION_TYPE_SUCCESS, ['contents' => $notificationContent]); return new JSONMessage(true); } @@ -654,7 +654,7 @@ public function setEnabled($enabled): void if ($enabled) { (new NotificationManager())->createTrivialNotification( Application::get()->getRequest()->getUser()->getId(), - PKPNotification::NOTIFICATION_TYPE_SUCCESS, + Notification::NOTIFICATION_TYPE_SUCCESS, ['contents' => __('plugins.generic.pln.onPluginEnabledNotification')] ); } @@ -665,7 +665,8 @@ public function setEnabled($enabled): void */ public function getName(): string { - return substr(static::class, strlen(__NAMESPACE__) + 1); + // Return the canonical plugin name used by PluginRegistry lookups + return 'plnplugin'; } /**