Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e40f3d4534 | |||
| 89b3f5844e |
File diff suppressed because one or more lines are too long
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Espo\Modules\SmartAssistant\Controllers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exposes the AssistantRule entity over the standard REST API
|
||||||
|
* (GET/POST/PUT/DELETE /api/v1/AssistantRule).
|
||||||
|
*
|
||||||
|
* Without this controller class EspoCRM responds 404 "Controller does not exist"
|
||||||
|
* even when the entity, object, and acl flags in scopes/AssistantRule.json are
|
||||||
|
* set. Inheriting from Record gives us the full CRUD surface — list/search,
|
||||||
|
* read, create, update, delete — with ACL enforcement.
|
||||||
|
*/
|
||||||
|
class AssistantRule extends \Espo\Core\Controllers\Record
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -533,20 +533,37 @@ class DocumentAnalyzer
|
|||||||
|
|
||||||
private function extractFromDocx(string $tmpFile): ?string
|
private function extractFromDocx(string $tmpFile): ?string
|
||||||
{
|
{
|
||||||
if (!class_exists(\PhpOffice\PhpWord\IOFactory::class)) return null;
|
// PHPWord (vendor/phpoffice/phpword) ships with the EspoCRM image but
|
||||||
$phpWord = \PhpOffice\PhpWord\IOFactory::load($tmpFile);
|
// is NOT in the composer PSR-4 autoload map — class_exists silently
|
||||||
$text = '';
|
// returns false. Rather than fix the autoloader (rebuild of the image)
|
||||||
foreach ($phpWord->getSections() as $section) {
|
// we parse word/document.xml directly. This is also more robust:
|
||||||
foreach ($section->getElements() as $element) {
|
// PHPWord's element walker only goes one level deep, missing text in
|
||||||
if (method_exists($element, 'getText')) $text .= $element->getText() . "\n";
|
// tables, hyperlinks, and footnotes.
|
||||||
elseif (method_exists($element, 'getElements')) {
|
$zip = new \ZipArchive();
|
||||||
foreach ($element->getElements() as $child) {
|
if ($zip->open($tmpFile) !== true) {
|
||||||
if (method_exists($child, 'getText')) $text .= $child->getText() . "\n";
|
$this->log->warning("SmartAssistant: extractFromDocx: not a valid zip: $tmpFile");
|
||||||
}
|
return null;
|
||||||
|
}
|
||||||
|
$xml = $zip->getFromName('word/document.xml');
|
||||||
|
$zip->close();
|
||||||
|
if ($xml === false || $xml === '') {
|
||||||
|
$this->log->warning("SmartAssistant: extractFromDocx: word/document.xml missing in $tmpFile");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each <w:p> is a paragraph; concatenate <w:t> runs inside it.
|
||||||
|
// `(?:\s[^>]*)?` keeps us from also matching <w:tab> / <w:tbl>.
|
||||||
|
$paragraphs = [];
|
||||||
|
if (preg_match_all('#<w:p(?:\s[^>]*)?>(.*?)</w:p>#s', $xml, $pMatches)) {
|
||||||
|
foreach ($pMatches[1] as $block) {
|
||||||
|
if (preg_match_all('#<w:t(?:\s[^>]*)?>(.*?)</w:t>#s', $block, $tMatches)) {
|
||||||
|
$line = trim(implode('', $tMatches[1]));
|
||||||
|
if ($line !== '') $paragraphs[] = html_entity_decode($line, ENT_XML1 | ENT_QUOTES, 'UTF-8');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $text ?: null;
|
$text = trim(implode("\n", $paragraphs));
|
||||||
|
return $text !== '' ? $text : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function updateDocumentEntity(string $oldPath, string $newPath): void
|
private function updateDocumentEntity(string $oldPath, string $newPath): void
|
||||||
|
|||||||
+2
-2
@@ -3,11 +3,11 @@
|
|||||||
"module": "SmartAssistant",
|
"module": "SmartAssistant",
|
||||||
"description": "Unified AI Assistant for Legal CRM — floating chat with case memory, office alerts, and AI Gateway integration",
|
"description": "Unified AI Assistant for Legal CRM — floating chat with case memory, office alerts, and AI Gateway integration",
|
||||||
"author": "klear",
|
"author": "klear",
|
||||||
"version": "2.9.0",
|
"version": "2.9.2",
|
||||||
"acceptableVersions": [
|
"acceptableVersions": [
|
||||||
">=8.0.0"
|
">=8.0.0"
|
||||||
],
|
],
|
||||||
"releaseDate": "2026-05-14",
|
"releaseDate": "2026-05-27",
|
||||||
"php": [
|
"php": [
|
||||||
">=8.1"
|
">=8.1"
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user