diff --git a/docs/en/README.md b/docs/en/README.md index 6caa679..52a2b8f 100644 --- a/docs/en/README.md +++ b/docs/en/README.md @@ -67,6 +67,8 @@ The index is stored in the root directory of your project: `/search/site.index` The index is initially created on a `dev/build`. Additional `dev/build`'s will update the index for all objects with the extension. +Alternatively, you can run `dev/tasks/Werkbot-Search-Tasks-SearchIndex` to build the index. Here, you can add `?debug` to the task URL to catch any potentially invalid index queries. + For all objects that have the extension applied, the index is updated on creation, edits/updates and delete/removals. So the index is always up to date. diff --git a/src/SearchableExtension.php b/src/SearchableExtension.php index afb96d3..cad8a86 100644 --- a/src/SearchableExtension.php +++ b/src/SearchableExtension.php @@ -3,6 +3,7 @@ namespace Werkbot\Search; use SilverStripe\Core\ClassInfo; +use SilverStripe\Core\Config\Config; use SilverStripe\Forms\CheckboxField; use SilverStripe\Forms\FieldGroup; use SilverStripe\Forms\FieldList; @@ -256,8 +257,28 @@ public function getSearchableSummaryColumnName() */ public function getIndexQueryDeclaringClass() { - $definesGetIndexQuery = new \ReflectionMethod($this->owner, 'getIndexQuery'); - return $definesGetIndexQuery->getDeclaringClass()->getName(); + try { + $definesGetIndexQuery = new \ReflectionMethod($this->owner, 'getIndexQuery'); + return $definesGetIndexQuery->getDeclaringClass()->getName(); + } catch (\ReflectionException $e) { + // If the base class does not define getIndexQuery, it may be defined in an Extension + return $this->getUpdateQueryDeclaringClass($this->owner->ClassName); + } + } + + /** + * Recursively check extensions for the class with the extension that defines the updateIndexQuery method + * @param string $class - The DataOject class name to check for the method + * @return string|null - The class name with an extension that defines the updateIndexQuery method + */ + public function getUpdateQueryDeclaringClass($class) + { + if (!$class) return; + $extensions = Config::inst()->get($class, 'extensions', Config::UNINHERITED) ?: []; + foreach (array_reverse($extensions) as $extensionClass) { + if (method_exists($extensionClass, 'updateIndexQuery')) return $class; + } + return $this->getUpdateQueryDeclaringClass(get_parent_class($class)); } /** @@ -279,6 +300,7 @@ public function getIndexDocument() { $id = $this->getSearchableID(); $classQuery = rtrim($this->owner->getIndexQuery(), ';'); + $classQuery = str_replace('"', "'", $classQuery); $query = <<record(); } diff --git a/src/Tasks/SearchIndex.php b/src/Tasks/SearchIndex.php index 8b022e2..8dfc122 100644 --- a/src/Tasks/SearchIndex.php +++ b/src/Tasks/SearchIndex.php @@ -21,6 +21,8 @@ public function run($request) echo "Created search folder

"; } + $debugMode = $request->getVar('debug') !== null; + $indexer = TNTSearchHelper::Instance()->getTNTSearchIndex(true); $classes = ClassInfo::classesWithExtension(SearchableExtension::class); @@ -30,6 +32,17 @@ public function run($request) if ($classQuery = $searchableClass->getIndexQuery()) { // Remove semi-colon if it exists $classQuery = rtrim($classQuery, ';'); + $classQuery = str_replace('"', "'", $classQuery); + + if ($debugMode) { + // Ensure this query is valid by running it before adding it to the indexer + try { + DB::query($classQuery); + } catch (\SilverStripe\ORM\Connect\DatabaseException $e) { + echo "
Error in query for class $className: " . $e->getMessage() . '
'; + return; + } + } $query .= $classQuery . ' UNION ALL ';