diff --git a/src/Extensions/ElementalPageExtension.php b/src/Extensions/ElementalPageExtension.php index 3df01a97..92df975a 100644 --- a/src/Extensions/ElementalPageExtension.php +++ b/src/Extensions/ElementalPageExtension.php @@ -98,19 +98,50 @@ public function MetaTags(&$tags) } } + /** + * @internal + */ + private static ?array $cachedElementalAreaDataLists = null; + /** * Call some function over all elements belonging to this page */ private function loopThroughElements(callable $callback): void { - foreach ($this->owner->hasOne() as $key => $class) { - if ($class !== ElementalArea::class) { - continue; + // would delete all the legacy stuff when doing proper PR, it's just here + // so that it's easy for me to benchmark old performance compared to new + $legacy = false; + if ($legacy) { + foreach ($this->owner->hasOne() as $key => $class) { + if ($class !== ElementalArea::class) { + continue; + } + /** @var ElementalArea $area */ + $area = $this->owner->$key(); + if ($area) { + foreach ($area->Elements() as $element) { + $callback($element); + } + } + } + } else { + if (is_null(self::$cachedElementalAreaDataLists)) { + self::$cachedElementalAreaDataLists = []; + foreach (ElementalArea::get()->eagerLoad('Elements') as $elementalArea) { + self::$cachedElementalAreaDataLists[$elementalArea->ID] = $elementalArea; + } } - /** @var ElementalArea $area */ - $area = $this->owner->$key(); - if ($area) { - foreach ($area->Elements() as $element) { + foreach ($this->owner->hasOne() as $relation => $class) { + if (!is_a($class, ElementalArea::class, true)) { + continue; + } + $elementalAreaID = $this->owner->{"{$relation}ID"}; + if ($elementalAreaID && array_key_exists($elementalAreaID, self::$cachedElementalAreaDataLists)) { + $elementalArea = self::$cachedElementalAreaDataLists[$elementalAreaID]; + } else { + $elementalArea = $this->owner->$relation(); + } + foreach ($elementalArea->Elements() as $element) { $callback($element); } } diff --git a/src/Models/BaseElement.php b/src/Models/BaseElement.php index 44925ad8..69fcf2cd 100644 --- a/src/Models/BaseElement.php +++ b/src/Models/BaseElement.php @@ -522,7 +522,39 @@ public function getSearchIndexable(): bool public function getContentForSearchIndex(): string { // Strips tags but be sure there's a space between words. - $content = trim(strip_tags(str_replace('<', ' <', $this->forTemplate() ?? '') ?? '')); + // $content = trim(strip_tags(str_replace('<', ' <', $this->forTemplate() ?? '') ?? '')); + + $contents = []; + foreach ($this->config()->get('db') as $fieldName => $fieldType) { + // https://docs.silverstripe.org/en/developer_guides/model/data_types_and_casting/ + // probably won't actually get things like 'CanViewType' in db config + if ($fieldName === 'LastEdited' + || $fieldName === 'Created' + || $fieldName === 'CanViewType' + || $fieldName === 'CanEditType' + || $fieldName === 'Version' + || $fieldName === 'ShowInMenus' + || $fieldName === 'ShowInSearch' + || $fieldName === 'Sort' + || $fieldName === 'HasBrokenFile' + || $fieldName === 'HasBrokenLink' + || $fieldName === 'ReportClass' + || substr($fieldType, -2) === 'ID' + || substr($fieldType, -3) === 'Key' + || substr($fieldName, -9) === 'ClassName' + || substr($fieldType, -4) === 'Hash' + ) { + continue; + } + $contents[] = $this->$fieldName; + } + // use a pipes to delimite different fields rather than space so that you don't + // accidentally join results of two columns that are next to each other in a table + $content = implode('||', $contents); + + // Strips tags and be sure there's a space between words. + $content = trim(strip_tags(str_replace('<', ' <', $content))); + // Allow projects to update indexable content of third-party elements. $this->extend('updateContentForSearchIndex', $content); return $content;