Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save cepheiVV/2e585eacfdc8a7f0682eb8522c25de59 to your computer and use it in GitHub Desktop.
Save cepheiVV/2e585eacfdc8a7f0682eb8522c25de59 to your computer and use it in GitHub Desktop.
ke_search custom indexer
<?php
declare(strict_types=1);
namespace Vendor\MyExt\Indexer;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Result;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Database\ConnectionPool;
/**
* Abstract class for custom indexers
*/
abstract class AbstractIndexer
{
/**
* require custom indexers to implement a registerIndexerConfiguration method
*/
abstract public function registerIndexerConfiguration(&$params, $pObj);
/**
* require custom indexers to implement a customIndexer method
*/
abstract public function customIndexer(&$indexerConfig, &$indexerObject);
/**
* get mm relation UID and add them as tags
* @param array $tags
* @param int $foreignUid
* @param string $tagName
* @param string $mmTable
* @return array $tags
* @throws DBALException
*/
public function addCategoryTags(array $tags, int $foreignUid, string $tagName, string $mmTable='sys_category_record_mm'): array
{
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($mmTable);
$relations = $queryBuilder
->select('uid_local')
->from($mmTable)
->where('uid_foreign=' . $foreignUid. ' AND tablenames LIKE "' . $this->table . '"')
->execute()
->fetchAll();
if ($relations) {
foreach ($relations as $relation) {
if ($relation['uid_local']) {
$tags[] = '#'. $tagName . '-' .$relation['uid_local'] . '#';
}
}
}
return $tags;
}
/**
* get all the entries to index
* don't index hidden or deleted elements, but
* get the elements with frontend user group access restrictions
* or time (start / stop) restrictions, in order to copy those restrictions to the index.
* @param string $table
* @param int $sysFolderUid
* @return Result|int
* @throws DBALException
*/
public function getIndexData(string $table, int $sysFolderUid): int|Result
{
$queryBuilder = GeneralUtility::makeInstance(
ConnectionPool::class
)->getQueryBuilderForTable($table);
$queryBuilder->select('*')
->from($table)
->where('pid IN (' . $sysFolderUid . ')');
return $queryBuilder->execute();
}
/**
* build response message that is displayed after the indexing is complete
*
* @param string $indexerTitle name of the indexer
* @param int $counter count of indexed records
* @return string response message
*/
public function createResponseMessage(string $indexerTitle, int $counter): string
{
return '<p><b>Indexer "' . $indexerTitle . '": ' . $counter . ' elements have been indexed.</b></p><br>';
}
/**
* validate the indexer configuration
*
* @param array $indexerConfig Configuration from TYPO3 Backend Indexer
* @throws \Exception
*/
protected function validateConfiguration(array $indexerConfig): void
{
if (!$indexerConfig['sysfolder'] ||
!$indexerConfig['targetpid'] ||
!$indexerConfig['storagepid']) {
throw new \Exception("Missing configuration for ke_search indexer: " . $this->indexerConfigurationKey);
}
}
/**
* check if page UID is not deleted
*
* @param int $pageUid
* @return bool
* @throws DBALException
*/
public function targetPageExists(int $pageUid): bool
{
$pageExists = true;
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
$queryBuilder->select('*')
->from('pages')
->where('uid='.$pageUid)
->setMaxResults(1);
$page = $queryBuilder->execute()->fetch();
if ($page) {
// page has been deleted or hidden
if ($page['deleted'] || $page['hidden']) {
$pageExists = false;
}
} else {
// no record found
$pageExists = false;
}
return $pageExists;
}
}
<?php
namespace Vendor\MyExt\Indexer;
use Vendor\MyExt\Indexer\AbstractIndexer;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
class CustomIndexer extends AbstractIndexer
{
protected $indexerConfigurationKey = 'customindexer';
protected $table = 'tx_myext_domain_model_custom';
/**
*
* @param array $params
* @param type $pObj
*/
public function registerIndexerConfiguration(&$params, $pObj)
{
$params['items'][] = [
'MyExt: Custom',
$this->indexerConfigurationKey,
ExtensionManagementUtility::extPath('myext') . 'Resources/Public/Icons/CustomIndexer.gif'
];
}
/**
* Custom indexer for ke_search
*
* @param array $indexerConfig Configuration from TYPO3 Backend
* @param array $indexerObject Reference to indexer class.
* @return string Message containing indexed elements
*/
public function customIndexer(&$indexerConfig, &$indexerObject)
{
$response = '';
if ($indexerConfig['type'] == $this->indexerConfigurationKey && $this->targetPageExists(intval($indexerConfig['targetpid']))) {
$result = $this->getIndexData(
$this->table,
$indexerConfig['sysfolder']
);
if ($result) {
$counter = 0;
while ($record = $result->fetch()) {
$title = strip_tags($record['title']);
$content = '';
if ($record['short_description']) {
$content .= strip_tags($record['short_description']) . ', ';
}
if ($record['description']) {
$content .= strip_tags($record['description']) . ', ';
}
$content = rtrim($content, ', '); // trim trailing commas
if ($record['short_description']) {
$abstract = substr($record['short_description'], 0, 160) . '...';
$fullContent = $title . "\n" . $record['short_description'] . "\n" . $content;
} else {
$abstract = substr($content, 0, 160) . '...';
$fullContent = $title . "\n" . $content;
}
// build target link
$params = '&tx_myext_pluginname[custom]=' . $record['uid']
. '&tx_myext_pluginname[controller]=Custom&tx_myext_pluginname[action]=show';
// add faceted search tags
$tags = [];
$tags[] = '#search-result#';
$tags[] = '#custom#';
$tags[] = '#custom-type-'.$record['type'].'#';
$tags = $this->addCategoryTags(
$tags,
'sys_category_record_mm',
$record['uid'],
'category'
);
$tags = implode(',', $tags);
// additional information
$additionalFields = [
'orig_uid' => $record['uid'],
'orig_pid' => $record['pid'],
'sortdate' => $record['start'],
];
// write to index
$indexerObject->storeInIndex(
$indexerConfig['storagepid'], // storage PID
$title, // record title
$this->indexerConfigurationKey, // content type
$indexerConfig['targetpid'], // target PID
$fullContent, // indexed content, includes the title
$tags, // tags for faceted search
$params, // typolink params for singleview
$abstract, // abstract; shown in result list if not empty
$record['sys_language_uid'], // language uid
$record['starttime'], // starttime
$record['endtime'], // endtime
$record['fe_group'], // fe_group
false, // debug only
$additionalFields // additionalFields
);
$counter++;
}
$response = $this->createResponseMessage($indexerConfig['title'], $counter);
}
}
return $response;
}
}
<?php
defined('TYPO3_MODE') or die();
// enable field sysfolder in Indexer Configuration
$enableField = 'sysfolder';
$indexers = [
'customindexer'
];
foreach ($indexers as $indexer) {
$GLOBALS['TCA']['tx_kesearch_indexerconfig']['columns'][$enableField]['displayCond'] .= ','.$indexer;
}
<?php
defined('TYPO3_MODE') or die();
/**
* register custom search indexers
*/
$customIndexers = [
\Vensor\MyExt\Indexer\CustomIndexer::class,
];
foreach ($customIndexers as $customIndexerClassName) {
$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['ke_search']['registerIndexerConfiguration'][] = $customIndexerClassName;
$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['ke_search']['customIndexer'][] = $customIndexerClassName;
}
@cepheiVV
Copy link
Author

cepheiVV commented Jul 28, 2020

You'll need to

  • change the Namespace according to your extension
  • change the $tags[] to your needs
  • replace all the demo fields in $record like e.g. $record['type'] or $record['short_description']
  • build the link to the target page in $params = '&tx_myext_pluginname[custom] ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment