1d200fc3f6
The first prod install with v2.10.0 failed silently because saveEntity invokes beforeSave hooks that require a 'user' service which isn't bound during the script. Pass skipAll=true so the seed is purely a data insert. Verified on prod 2026-05-27: all 7 default prompts seeded successfully.
85 lines
2.9 KiB
PHP
85 lines
2.9 KiB
PHP
<?php
|
|
|
|
namespace Espo\Modules\SmartAssistant\Scripts;
|
|
|
|
use Espo\Core\Container;
|
|
|
|
/**
|
|
* Runs after the extension is installed/upgraded.
|
|
*
|
|
* Idempotent: only inserts AssistantPrompt rows whose `key` doesn't exist yet.
|
|
* If the row exists (even with edits), we leave it alone — the user's
|
|
* customizations win.
|
|
*/
|
|
class AfterInstall
|
|
{
|
|
public function run(Container $container, $params = null): void
|
|
{
|
|
$entityManager = $container->get('entityManager');
|
|
$log = $container->get('log');
|
|
|
|
$resourceFile = __DIR__ . '/../files/custom/Espo/Modules/SmartAssistant/Resources/data/default-prompts.json';
|
|
|
|
if (!is_file($resourceFile)) {
|
|
// Fall back to the module Resources path when the extension is
|
|
// installed (Resources/ is the canonical location at runtime).
|
|
$resourceFile = dirname(__DIR__) . '/files/custom/Espo/Modules/SmartAssistant/Resources/data/default-prompts.json';
|
|
}
|
|
|
|
if (!is_file($resourceFile)) {
|
|
// Final fallback: the module's installed Resources path.
|
|
$resourceFile = 'custom/Espo/Modules/SmartAssistant/Resources/data/default-prompts.json';
|
|
}
|
|
|
|
if (!is_file($resourceFile)) {
|
|
$log->warning("[SmartAssistant] AfterInstall: default-prompts.json not found, skipping seed");
|
|
return;
|
|
}
|
|
|
|
$json = file_get_contents($resourceFile);
|
|
$defaults = json_decode($json, true);
|
|
|
|
if (!is_array($defaults)) {
|
|
$log->warning("[SmartAssistant] AfterInstall: default-prompts.json invalid JSON");
|
|
return;
|
|
}
|
|
|
|
$created = 0;
|
|
$skipped = 0;
|
|
|
|
foreach ($defaults as $row) {
|
|
$key = $row['key'] ?? null;
|
|
if (!$key) {
|
|
continue;
|
|
}
|
|
|
|
$existing = $entityManager->getRDBRepository('AssistantPrompt')
|
|
->where(['key' => $key, 'deleted' => false])
|
|
->findOne();
|
|
|
|
if ($existing) {
|
|
$skipped++;
|
|
continue;
|
|
}
|
|
|
|
$entity = $entityManager->getNewEntity('AssistantPrompt');
|
|
$entity->set([
|
|
'key' => $key,
|
|
'name' => $row['name'] ?? $key,
|
|
'description' => $row['description'] ?? null,
|
|
'mode' => $row['mode'] ?? 'both',
|
|
'displayOrder' => $row['displayOrder'] ?? 100,
|
|
'content' => $row['content'] ?? '',
|
|
'isActive' => true,
|
|
]);
|
|
// skipAll bypasses beforeSave hooks that require a logged-in user
|
|
// service (install runs without a session) and ACL checks (we're
|
|
// seeding firm-wide defaults; no user is implicated).
|
|
$entityManager->saveEntity($entity, ['skipAll' => true]);
|
|
$created++;
|
|
}
|
|
|
|
$log->info("[SmartAssistant] AfterInstall: seeded $created AssistantPrompt rows, $skipped already existed");
|
|
}
|
|
}
|