diff --git a/.phan/config.php b/.phan/config.php new file mode 100644 index 0000000..11a17af --- /dev/null +++ b/.phan/config.php @@ -0,0 +1,96 @@ + '7.0', + + // Override to hardcode existence and types of (non-builtin) globals. + // Class names should be prefixed with '\\'. + // (E.g. ['_FOO' => '\\FooClass', 'page' => '\\PageClass', 'userId' => 'int']) + 'globals_type_map' => [ + '_EXTKEY' => 'string', + 'EM_CONF' => 'array', + ], + + // A list of directories that should be parsed for class and + // method information. After excluding the directories + // defined in exclude_analysis_directory_list, the remaining + // files will be statically analyzed for errors. + // + // Thus, both first-party and third-party code being used by + // your application should be included in this list. + 'directory_list' => [ + 'Classes', + '.Build/vendor', + ], + + // A list of files to include in analysis + 'file_list' => [ + 'ext_emconf.php', + 'ext_tables.php', + 'ext_localconf.php', + ], + + // A directory list that defines files that will be excluded + // from static analysis, but whose class and method + // information should be included. + // + // Generally, you'll want to include the directories for + // third-party code (such as "vendor/") in this list. + // + // n.b.: If you'd like to parse but not analyze 3rd + // party code, directories containing that code + // should be added to the `directory_list` as + // to `exclude_analysis_directory_list`. + "exclude_analysis_directory_list" => [ + '.Build/vendor' + ], + + // A list of directories that should be parsed for class and + // method information. After excluding the directories + // defined in exclude_analysis_directory_list, the remaining + // files will be statically analyzed for errors. + // + // Thus, both first-party and third-party code being used by + // your application should be included in this list. + 'directory_list' => [ + 'Classes', + // 'Tests', + '.Build/vendor', + ], + + // The number of processes to fork off during the analysis phase. + 'processes' => 3, + + // Add any issue types (such as 'PhanUndeclaredMethod') + // here to inhibit them from being reported + 'suppress_issue_types' => [ + 'PhanDeprecatedFunction', // For now + 'PhanParamTooMany', // For now, due to ObjectManager->get() + ], + + // A list of plugin files to execute. + // See https://github.com/phan/phan/tree/master/.phan/plugins for even more. + // (Pass these in as relative paths. + // The 0.10.2 release will allow passing 'AlwaysReturnPlugin' if referring to a plugin that is bundled with Phan) + 'plugins' => [ + // checks if a function, closure or method unconditionally returns. + 'AlwaysReturnPlugin', // can also be written as 'vendor/phan/phan/.phan/plugins/AlwaysReturnPlugin.php' + // Checks for syntactically unreachable statements in + // the global scope or function bodies. + 'UnreachableCodePlugin', + 'DollarDollarPlugin', + 'DuplicateArrayKeyPlugin', + 'PregRegexCheckerPlugin', + 'PrintfCheckerPlugin', + ], +]; diff --git a/.scrutinizer.yml b/.scrutinizer.yml index ca92884..3122a2f 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -1,3 +1,11 @@ +build: + nodes: + analysis: + project_setup: + override: true + tests: + override: [php-scrutinizer-run] + filter: excluded_paths: - 'Configuration/*' @@ -19,7 +27,7 @@ tools: php_hhvm: enabled: true config: - use_undeclared_constant: false + use_undeclared_constant: false php_mess_detector: enabled: true @@ -34,5 +42,5 @@ tools: enabled: true # We generate code coverage during tests at travis and will send them here external_code_coverage: - runs: 2 - timeout: 1200 + runs: 2 + timeout: 1200 diff --git a/Classes/Command/IndexCommandController.php b/Classes/Command/IndexCommandController.php index 70816ed..e0bdeb9 100644 --- a/Classes/Command/IndexCommandController.php +++ b/Classes/Command/IndexCommandController.php @@ -22,7 +22,6 @@ namespace Codappix\SearchCore\Command; use Codappix\SearchCore\Domain\Index\IndexerFactory; use Codappix\SearchCore\Domain\Index\NoMatchingIndexerException; -use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Mvc\Controller\CommandController; /** @@ -48,7 +47,7 @@ class IndexCommandController extends CommandController * * @param string $identifier */ - public function indexCommand($identifier) + public function indexCommand(string $identifier) { try { $this->indexerFactory->getIndexer($identifier)->indexAllDocuments(); @@ -63,7 +62,7 @@ class IndexCommandController extends CommandController * * @param string $identifier */ - public function deleteCommand($identifier) + public function deleteCommand(string $identifier) { try { $this->indexerFactory->getIndexer($identifier)->delete(); diff --git a/Classes/Configuration/ConfigurationContainer.php b/Classes/Configuration/ConfigurationContainer.php index 7481692..eab76e0 100644 --- a/Classes/Configuration/ConfigurationContainer.php +++ b/Classes/Configuration/ConfigurationContainer.php @@ -39,7 +39,6 @@ class ConfigurationContainer implements ConfigurationContainerInterface /** * Inject settings via ConfigurationManager. * - * @param ConfigurationManagerInterface $configurationManager * @throws NoConfigurationException */ public function injectConfigurationManager(ConfigurationManagerInterface $configurationManager) @@ -59,7 +58,7 @@ class ConfigurationContainer implements ConfigurationContainerInterface * @return mixed * @throws InvalidArgumentException */ - public function get($path) + public function get(string $path) { $value = ArrayUtility::getValueByPath($this->settings, $path); @@ -77,7 +76,7 @@ class ConfigurationContainer implements ConfigurationContainerInterface * @param string $path In dot notation. * @return mixed */ - public function getIfExists($path) + public function getIfExists(string $path) { return ArrayUtility::getValueByPath($this->settings, $path); } diff --git a/Classes/Configuration/ConfigurationContainerInterface.php b/Classes/Configuration/ConfigurationContainerInterface.php index 9429535..1978453 100644 --- a/Classes/Configuration/ConfigurationContainerInterface.php +++ b/Classes/Configuration/ConfigurationContainerInterface.php @@ -37,7 +37,7 @@ interface ConfigurationContainerInterface extends Singleton * * @throws InvalidArgumentException */ - public function get($path); + public function get(string $path); /** * Same as get but will not throw an exception but return null. @@ -45,5 +45,5 @@ interface ConfigurationContainerInterface extends Singleton * @param string $path In dot notation. * @return mixed|null */ - public function getIfExists($path); + public function getIfExists(string $path); } diff --git a/Classes/Connection/ConnectionInterface.php b/Classes/Connection/ConnectionInterface.php index 59cf9f8..a336793 100644 --- a/Classes/Connection/ConnectionInterface.php +++ b/Classes/Connection/ConnectionInterface.php @@ -28,62 +28,44 @@ interface ConnectionInterface /** * Will add a new document. * - * @param string $documentType - * @param array $document - * * @return void */ - public function addDocument($documentType, array $document); + public function addDocument(string $documentType, array $document); /** * Add the given documents. * - * @param string $documentType - * @param array $documents - * * @return void */ - public function addDocuments($documentType, array $documents); + public function addDocuments(string $documentType, array $documents); /** * Will update an existing document. * * NOTE: Batch updating is not yet supported. * - * @param string $documentType - * @param array $document - * * @return void */ - public function updateDocument($documentType, array $document); + public function updateDocument(string $documentType, array $document); /** * Will remove an existing document. * * NOTE: Batch deleting is not yet supported. * - * @param string $documentType - * @param int $identifier - * * @return void */ - public function deleteDocument($documentType, $identifier); + public function deleteDocument(string $documentType, string $identifier); /** * Search by given request and return result. - * - * @param SearchRequestInterface $searchRequest - * - * @return SearchResultInterface */ - public function search(SearchRequestInterface $searchRequest); + public function search(SearchRequestInterface $searchRequest) : SearchResultInterface; /** * Will delete the whole index / db. * - * @param string $documentType - * * @return void */ - public function deleteIndex($documentType); + public function deleteIndex(string $documentType); } diff --git a/Classes/Connection/Elasticsearch.php b/Classes/Connection/Elasticsearch.php index b86bebf..555d4e7 100644 --- a/Classes/Connection/Elasticsearch.php +++ b/Classes/Connection/Elasticsearch.php @@ -112,7 +112,7 @@ class Elasticsearch implements Singleton, ConnectionInterface $this->queryFactory = $queryFactory; } - public function addDocument($documentType, array $document) + public function addDocument(string $documentType, array $document) { $this->withType( $documentType, @@ -122,7 +122,7 @@ class Elasticsearch implements Singleton, ConnectionInterface ); } - public function deleteDocument($documentType, $identifier) + public function deleteDocument(string $documentType, string $identifier) { try { $this->withType( @@ -139,7 +139,7 @@ class Elasticsearch implements Singleton, ConnectionInterface } } - public function updateDocument($documentType, array $document) + public function updateDocument(string $documentType, array $document) { $this->withType( $documentType, @@ -149,7 +149,7 @@ class Elasticsearch implements Singleton, ConnectionInterface ); } - public function addDocuments($documentType, array $documents) + public function addDocuments(string $documentType, array $documents) { $this->withType( $documentType, @@ -159,7 +159,7 @@ class Elasticsearch implements Singleton, ConnectionInterface ); } - public function deleteIndex($documentType) + public function deleteIndex(string $documentType) { $index = $this->connection->getClient()->getIndex('typo3content'); @@ -173,11 +173,8 @@ class Elasticsearch implements Singleton, ConnectionInterface /** * Execute given callback with Elastica Type based on provided documentType - * - * @param string $documentType - * @param callable $callback */ - protected function withType($documentType, callable $callback) + protected function withType(string $documentType, callable $callback) { $type = $this->getType($documentType); // TODO: Check whether it's to heavy to send it so often e.g. for every single document. @@ -191,12 +188,7 @@ class Elasticsearch implements Singleton, ConnectionInterface $type->getIndex()->refresh(); } - /** - * @param SearchRequestInterface $searchRequest - * - * @return SearchResultInterface - */ - public function search(SearchRequestInterface $searchRequest) + public function search(SearchRequestInterface $searchRequest) : SearchResultInterface { $this->logger->debug('Search for', [$searchRequest->getSearchTerm()]); @@ -207,12 +199,7 @@ class Elasticsearch implements Singleton, ConnectionInterface return $this->objectManager->get(SearchResult::class, $searchRequest, $search->search()); } - /** - * @param string $documentType - * - * @return \Elastica\Type - */ - protected function getType($documentType) + protected function getType(string $documentType) : \Elastica\Type { return $this->typeFactory->getType( $this->indexFactory->getIndex( diff --git a/Classes/Connection/Elasticsearch/Connection.php b/Classes/Connection/Elasticsearch/Connection.php index cd0a1fd..a5e7d0f 100644 --- a/Classes/Connection/Elasticsearch/Connection.php +++ b/Classes/Connection/Elasticsearch/Connection.php @@ -44,7 +44,7 @@ class Connection implements Singleton /** * @param ConfigurationContainerInterface $configuration - * @param \Elastica\Client $elasticaClient + * @param \Elastica\Client|null $elasticaClient */ public function __construct( ConfigurationContainerInterface $configuration, @@ -52,9 +52,8 @@ class Connection implements Singleton ) { $this->configuration = $configuration; - $this->elasticaClient = $elasticaClient; - if ($this->elasticaClient === null) { - $this->elasticaClient = new \Elastica\Client([ + if ($elasticaClient === null) { + $elasticaClient = new \Elastica\Client([ 'host' => $this->configuration->get('connections.elasticsearch.host'), 'port' => $this->configuration->get('connections.elasticsearch.port'), // TODO: Make configurable @@ -63,14 +62,13 @@ class Connection implements Singleton // TODO: Make configurable. // new \Elastica\Log($this->elasticaClient); } + $this->elasticaClient = $elasticaClient; } /** * Get the concrete client for internal usage! - * - * @return \Elastica\Client */ - public function getClient() + public function getClient() : \Elastica\Client { return $this->elasticaClient; } diff --git a/Classes/Connection/Elasticsearch/DocumentFactory.php b/Classes/Connection/Elasticsearch/DocumentFactory.php index 390c592..beb091a 100644 --- a/Classes/Connection/Elasticsearch/DocumentFactory.php +++ b/Classes/Connection/Elasticsearch/DocumentFactory.php @@ -44,13 +44,8 @@ class DocumentFactory implements Singleton /** * Creates document from document. - * - * @param string $documentType - * @param array $document - * - * @return \Elastica\Document */ - public function getDocument($documentType, array $document) + public function getDocument(string $documentType, array $document) : \Elastica\Document { // TODO: Use DocumentType for further configuration. @@ -70,13 +65,8 @@ class DocumentFactory implements Singleton /** * Creates documents based on documents. - * - * @param string $documentType - * @param array $documents - * - * @return array */ - public function getDocuments($documentType, array $documents) + public function getDocuments(string $documentType, array $documents) : array { foreach ($documents as &$document) { $document = $this->getDocument($documentType, $document); diff --git a/Classes/Connection/Elasticsearch/Facet.php b/Classes/Connection/Elasticsearch/Facet.php index 1142d88..27de076 100644 --- a/Classes/Connection/Elasticsearch/Facet.php +++ b/Classes/Connection/Elasticsearch/Facet.php @@ -22,6 +22,7 @@ namespace Codappix\SearchCore\Connection\Elasticsearch; use Codappix\SearchCore\Configuration\ConfigurationContainerInterface; use Codappix\SearchCore\Connection\FacetInterface; +use Codappix\SearchCore\Connection\FacetOptionInterface; class Facet implements FacetInterface { diff --git a/Classes/Connection/Elasticsearch/IndexFactory.php b/Classes/Connection/Elasticsearch/IndexFactory.php index 49956f0..98001f2 100644 --- a/Classes/Connection/Elasticsearch/IndexFactory.php +++ b/Classes/Connection/Elasticsearch/IndexFactory.php @@ -22,10 +22,8 @@ namespace Codappix\SearchCore\Connection\Elasticsearch; use Codappix\SearchCore\Configuration\ConfigurationContainerInterface; use Codappix\SearchCore\Configuration\InvalidArgumentException; -use Elastica\Exception\ResponseException; use TYPO3\CMS\Core\SingletonInterface as Singleton; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface; /** * Factory to get indexes. @@ -64,13 +62,8 @@ class IndexFactory implements Singleton /** * Get an index bases on TYPO3 table name. - * - * @param Connection $connection - * @param string $documentType - * - * @return \Elastica\Index */ - public function getIndex(Connection $connection, $documentType) + public function getIndex(Connection $connection, string $documentType) : \Elastica\Index { $index = $connection->getClient()->getIndex('typo3content'); @@ -84,12 +77,7 @@ class IndexFactory implements Singleton return $index; } - /** - * @param string $documentType - * - * @return array - */ - protected function getConfigurationFor($documentType) + protected function getConfigurationFor(string $documentType) : array { try { $configuration = $this->configuration->get('indexing.' . $documentType . '.index'); @@ -108,12 +96,7 @@ class IndexFactory implements Singleton } } - /** - * @param array $options - * - * @return array - */ - protected function prepareOptions(array $options) + protected function prepareOptions(array $options) : array { $fieldsToExplode = ['char_filter', 'filter', 'word_list']; diff --git a/Classes/Connection/Elasticsearch/MappingFactory.php b/Classes/Connection/Elasticsearch/MappingFactory.php index 44a05c1..3882556 100644 --- a/Classes/Connection/Elasticsearch/MappingFactory.php +++ b/Classes/Connection/Elasticsearch/MappingFactory.php @@ -44,12 +44,8 @@ class MappingFactory implements Singleton /** * Get an mapping based on type. - * - * @param \Elastica\Type $type - * - * @return \Elastica\Mapping */ - public function getMapping(\Elastica\Type $type) + public function getMapping(\Elastica\Type $type) : \Elastica\Type\Mapping { $mapping = new \Elastica\Type\Mapping(); $mapping->setType($type); @@ -64,11 +60,7 @@ class MappingFactory implements Singleton return $mapping; } - /** - * @param string $identifier - * @return array - */ - protected function getConfiguration($identifier) + protected function getConfiguration(string $identifier) : array { try { return $this->configuration->get('indexing.' . $identifier . '.mapping'); diff --git a/Classes/Connection/Elasticsearch/SearchResult.php b/Classes/Connection/Elasticsearch/SearchResult.php index 867d823..5b3d381 100644 --- a/Classes/Connection/Elasticsearch/SearchResult.php +++ b/Classes/Connection/Elasticsearch/SearchResult.php @@ -77,7 +77,7 @@ class SearchResult implements SearchResultInterface /** * @return array */ - public function getResults() + public function getResults() : array { $this->initResults(); @@ -89,14 +89,14 @@ class SearchResult implements SearchResultInterface * * @return array */ - public function getFacets() + public function getFacets() : array { $this->initFacets(); return $this->facets; } - public function getCurrentCount() + public function getCurrentCount() : int { return $this->result->count(); } diff --git a/Classes/Connection/Elasticsearch/TypeFactory.php b/Classes/Connection/Elasticsearch/TypeFactory.php index d5283f8..e84cdd0 100644 --- a/Classes/Connection/Elasticsearch/TypeFactory.php +++ b/Classes/Connection/Elasticsearch/TypeFactory.php @@ -21,7 +21,6 @@ namespace Codappix\SearchCore\Connection\Elasticsearch; */ use TYPO3\CMS\Core\SingletonInterface as Singleton; -use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface; /** * Factory to get indexes. @@ -32,13 +31,8 @@ class TypeFactory implements Singleton { /** * Get an index bases on TYPO3 table name. - * - * @param \Elastica\Index $index - * @param string $documentType - * - * @return \Elastica\Type */ - public function getType(\Elastica\Index $index, $documentType) + public function getType(\Elastica\Index $index, string $documentType) : \Elastica\Type { return $index->getType($documentType); } diff --git a/Classes/Connection/FacetInterface.php b/Classes/Connection/FacetInterface.php index b1cc421..3ec549d 100644 --- a/Classes/Connection/FacetInterface.php +++ b/Classes/Connection/FacetInterface.php @@ -25,15 +25,12 @@ namespace Codappix\SearchCore\Connection; */ interface FacetInterface { - /** - * @return string - */ - public function getName(); + public function getName() : string; /** * Returns all possible options for this facet. * * @return array */ - public function getOptions(); + public function getOptions() : array; } diff --git a/Classes/Connection/SearchRequestInterface.php b/Classes/Connection/SearchRequestInterface.php index e24adc3..a400447 100644 --- a/Classes/Connection/SearchRequestInterface.php +++ b/Classes/Connection/SearchRequestInterface.php @@ -20,6 +20,8 @@ namespace Codappix\SearchCore\Connection; * 02110-1301, USA. */ +use Codappix\SearchCore\Connection\ConnectionInterface; +use Codappix\SearchCore\Connection\FacetRequestInterface; use Codappix\SearchCore\Domain\Search\SearchService; use TYPO3\CMS\Extbase\Persistence\QueryInterface; @@ -27,24 +29,38 @@ interface SearchRequestInterface extends QueryInterface { /** * Returns the actual string the user searched for. - * - * @return string */ - public function getSearchTerm(); + public function getSearchTerm() : string; + + public function hasFilter() : bool; + + public function getFilter() : array; + + public function setFilter(array $filter); /** - * @return bool + * @return void */ - public function hasFilter(); + public function addFacet(FacetRequestInterface $facet); /** - * @return array + * @return array */ - public function getFilter(); + public function getFacets() : array; /** * Workaround for paginate widget support which will * use the request to build another search. + * + * @return void + */ + public function setConnection(ConnectionInterface $connection); + + /** + * Workaround for paginate widget support which will + * use the request to build another search. + * + * @return void */ public function setSearchService(SearchService $searchService); } diff --git a/Classes/Connection/SearchResultInterface.php b/Classes/Connection/SearchResultInterface.php index 60718cd..be698fa 100644 --- a/Classes/Connection/SearchResultInterface.php +++ b/Classes/Connection/SearchResultInterface.php @@ -30,19 +30,17 @@ interface SearchResultInterface extends \Iterator, \Countable, QueryResultInterf /** * @return array */ - public function getResults(); + public function getResults() : array; /** * Return all facets, if any. * * @return array */ - public function getFacets(); + public function getFacets() : array; /** * Returns the number of results in current result - * - * @return int */ - public function getCurrentCount(); + public function getCurrentCount() : int; } diff --git a/Classes/DataProcessing/GeoPointProcessor.php b/Classes/DataProcessing/GeoPointProcessor.php index c5b6d18..971e2c4 100644 --- a/Classes/DataProcessing/GeoPointProcessor.php +++ b/Classes/DataProcessing/GeoPointProcessor.php @@ -27,7 +27,7 @@ class GeoPointProcessor implements ProcessorInterface { public function processData(array $record, array $configuration) : array { - if (! $this->canApply($record, $configuration)) { + if (! $this->isApplyable($record, $configuration)) { return $record; } @@ -39,7 +39,7 @@ class GeoPointProcessor implements ProcessorInterface return $record; } - protected function canApply(array $record, array $configuration) : bool + protected function isApplyable(array $record, array $configuration) : bool { if (!isset($record[$configuration['lat']]) || !is_numeric($record[$configuration['lat']]) diff --git a/Classes/Domain/Index/AbstractIndexer.php b/Classes/Domain/Index/AbstractIndexer.php index 431fb4d..9893262 100644 --- a/Classes/Domain/Index/AbstractIndexer.php +++ b/Classes/Domain/Index/AbstractIndexer.php @@ -23,7 +23,6 @@ namespace Codappix\SearchCore\Domain\Index; use Codappix\SearchCore\Configuration\ConfigurationContainerInterface; use Codappix\SearchCore\Configuration\InvalidArgumentException; use Codappix\SearchCore\Connection\ConnectionInterface; -use Codappix\SearchCore\DataProcessing\ProcessorInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; abstract class AbstractIndexer implements IndexerInterface @@ -69,7 +68,7 @@ abstract class AbstractIndexer implements IndexerInterface $this->logger = $logManager->getLogger(__CLASS__); } - public function setIdentifier($identifier) + public function setIdentifier(string $identifier) { $this->identifier = $identifier; } @@ -98,11 +97,11 @@ abstract class AbstractIndexer implements IndexerInterface $this->logger->info('Finish indexing'); } - public function indexDocument($identifier) + public function indexDocument(string $identifier) { $this->logger->info('Start indexing single record.', [$identifier]); try { - $record = $this->getRecord($identifier); + $record = $this->getRecord((int) $identifier); $this->prepareRecord($record); $this->connection->addDocument($this->getDocumentName(), $record); @@ -120,10 +119,7 @@ abstract class AbstractIndexer implements IndexerInterface $this->logger->info('Finish deletion.'); } - /** - * @return \Generator - */ - protected function getRecordGenerator() + protected function getRecordGenerator() : \Generator { $offset = 0; $limit = $this->getLimit(); @@ -134,9 +130,6 @@ abstract class AbstractIndexer implements IndexerInterface } } - /** - * @param array &$record - */ protected function prepareRecord(array &$record) { try { @@ -150,9 +143,6 @@ abstract class AbstractIndexer implements IndexerInterface $this->handleAbstract($record); } - /** - * @param array &$record - */ protected function handleAbstract(array &$record) { $record['search_abstract'] = ''; @@ -162,7 +152,7 @@ abstract class AbstractIndexer implements IndexerInterface ',', $this->configuration->get('indexing.' . $this->identifier . '.abstractFields') ); - if (!$fieldsToUse) { + if ($fieldsToUse === []) { return; } foreach ($fieldsToUse as $fieldToUse) { @@ -178,31 +168,22 @@ abstract class AbstractIndexer implements IndexerInterface /** * Returns the limit to use to fetch records. - * - * @return int */ - protected function getLimit() + protected function getLimit() : int { // TODO: Make configurable. return 50; } /** - * @param int $offset - * @param int $limit * @return array|null */ - abstract protected function getRecords($offset, $limit); + abstract protected function getRecords(int $offset, int $limit); /** - * @param int $identifier - * @return array * @throws NoRecordFoundException If record could not be found. */ - abstract protected function getRecord($identifier); + abstract protected function getRecord(int $identifier) : array; - /** - * @return string - */ - abstract protected function getDocumentName(); + abstract protected function getDocumentName() : string; } diff --git a/Classes/Domain/Index/IndexerInterface.php b/Classes/Domain/Index/IndexerInterface.php index 72ebb9d..4acfb28 100644 --- a/Classes/Domain/Index/IndexerInterface.php +++ b/Classes/Domain/Index/IndexerInterface.php @@ -35,20 +35,16 @@ interface IndexerInterface /** * Fetches a single document and pushes it to the connection. * - * @param string $identifier - * * @return void */ - public function indexDocument($identifier); + public function indexDocument(string $identifier); /** * Recieves the identifier of the indexer itself. * - * @param string $identifier - * * @return void */ - public function setIdentifier($identifier); + public function setIdentifier(string $identifier); /** * Delete the whole index. diff --git a/Classes/Domain/Index/TcaIndexer.php b/Classes/Domain/Index/TcaIndexer.php index 44d7c46..b2333b4 100644 --- a/Classes/Domain/Index/TcaIndexer.php +++ b/Classes/Domain/Index/TcaIndexer.php @@ -43,17 +43,14 @@ class TcaIndexer extends AbstractIndexer ConnectionInterface $connection, ConfigurationContainerInterface $configuration ) { + parent::__construct($connection, $configuration); $this->tcaTableService = $tcaTableService; - $this->connection = $connection; - $this->configuration = $configuration; } /** - * @param int $offset - * @param int $limit * @return array|null */ - protected function getRecords($offset, $limit) + protected function getRecords(int $offset, int $limit) { $records = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows( $this->tcaTableService->getFields(), @@ -76,11 +73,9 @@ class TcaIndexer extends AbstractIndexer } /** - * @param int $identifier - * @return array * @throws NoRecordFoundException If record could not be found. */ - protected function getRecord($identifier) + protected function getRecord(int $identifier) : array { $record = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow( $this->tcaTableService->getFields(), @@ -100,10 +95,7 @@ class TcaIndexer extends AbstractIndexer return $record; } - /** - * @return string - */ - protected function getDocumentName() + protected function getDocumentName() : string { return $this->tcaTableService->getTableName(); } diff --git a/Classes/Domain/Index/TcaIndexer/PagesIndexer.php b/Classes/Domain/Index/TcaIndexer/PagesIndexer.php index 1108676..4650a2f 100644 --- a/Classes/Domain/Index/TcaIndexer/PagesIndexer.php +++ b/Classes/Domain/Index/TcaIndexer/PagesIndexer.php @@ -42,7 +42,7 @@ class PagesIndexer extends TcaIndexer /** * @param TcaTableService $tcaTableService - * @param TcaTableService $tcaTableService + * @param TcaTableService $contentTableService * @param ConnectionInterface $connection * @param ConfigurationContainerInterface $configuration */ @@ -52,10 +52,8 @@ class PagesIndexer extends TcaIndexer ConnectionInterface $connection, ConfigurationContainerInterface $configuration ) { - $this->tcaTableService = $tcaTableService; + parent::__construct($tcaTableService, $connection, $configuration); $this->contentTableService = $contentTableService; - $this->connection = $connection; - $this->configuration = $configuration; } protected function prepareRecord(array &$record) diff --git a/Classes/Domain/Index/TcaIndexer/TcaTableService.php b/Classes/Domain/Index/TcaIndexer/TcaTableService.php index beab49b..558a231 100644 --- a/Classes/Domain/Index/TcaIndexer/TcaTableService.php +++ b/Classes/Domain/Index/TcaIndexer/TcaTableService.php @@ -21,7 +21,6 @@ namespace Codappix\SearchCore\Domain\Index\TcaIndexer; */ use Codappix\SearchCore\Configuration\ConfigurationContainerInterface; -use Codappix\SearchCore\Configuration\InvalidArgumentException as InvalidConfigurationArgumentException; use Codappix\SearchCore\Domain\Index\IndexingException; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -105,17 +104,11 @@ class TcaTableService $this->relationResolver = $relationResolver; } - /** - * @return string - */ public function getTableName() : string { return $this->tableName; } - /** - * @return string - */ public function getTableClause() : string { if ($this->tableName === 'pages') { @@ -138,9 +131,6 @@ class TcaTableService ); } - /** - * Adjust record accordingly to configuration. - */ public function prepareRecord(array &$record) { $this->relationResolver->resolveRelationsForRecord($this, $record); diff --git a/Classes/Domain/Model/SearchRequest.php b/Classes/Domain/Model/SearchRequest.php index 69237bb..22bd697 100644 --- a/Classes/Domain/Model/SearchRequest.php +++ b/Classes/Domain/Model/SearchRequest.php @@ -72,56 +72,39 @@ class SearchRequest implements SearchRequestInterface /** * @param string $query */ - public function __construct($query = '') + public function __construct(string $query = '') { - $this->query = (string) $query; + $this->query = $query; } - /** - * @return string - */ - public function getQuery() + public function getQuery() : string { return $this->query; } - /** - * @return string - */ - public function getSearchTerm() + public function getSearchTerm() : string { return $this->query; } - /** - * @param array $filter - */ public function setFilter(array $filter) { $filter = \TYPO3\CMS\Core\Utility\ArrayUtility::removeArrayEntryByValue($filter, ''); $this->filter = \TYPO3\CMS\Extbase\Utility\ArrayUtility::removeEmptyElementsRecursively($filter); } - /** - * @return bool - */ - public function hasFilter() + public function hasFilter() : bool { return count($this->filter) > 0; } - /** - * @return array - */ - public function getFilter() + public function getFilter() : array { return $this->filter; } /** * Add a facet to gather in this search request. - * - * @param FacetRequestInterface $facet */ public function addFacet(FacetRequestInterface $facet) { @@ -130,10 +113,8 @@ class SearchRequest implements SearchRequestInterface /** * Returns all configured facets to fetch in this search request. - * - * @return array */ - public function getFacets() + public function getFacets() : array { return $this->facets; } @@ -141,8 +122,6 @@ class SearchRequest implements SearchRequestInterface /** * Define connection to use for this request. * Necessary to allow implementation of execute for interface. - * - * @param ConnectionInterface $connection */ public function setConnection(ConnectionInterface $connection) { @@ -177,11 +156,15 @@ class SearchRequest implements SearchRequestInterface public function setLimit($limit) { $this->limit = (int) $limit; + + return $this; } public function setOffset($offset) { $this->offset = (int) $offset; + + return $this; } public function getLimit() diff --git a/Classes/Domain/Model/SearchResult.php b/Classes/Domain/Model/SearchResult.php index d91820d..163b996 100644 --- a/Classes/Domain/Model/SearchResult.php +++ b/Classes/Domain/Model/SearchResult.php @@ -62,7 +62,7 @@ class SearchResult implements SearchResultInterface /** * @return array */ - public function getResults() + public function getResults() : array { $this->initResults(); @@ -80,12 +80,12 @@ class SearchResult implements SearchResultInterface } } - public function getFacets() + public function getFacets() : array { return $this->originalSearchResult->getFacets(); } - public function getCurrentCount() + public function getCurrentCount() : int { return $this->originalSearchResult->getCurrentCount(); } diff --git a/Classes/Domain/Search/QueryFactory.php b/Classes/Domain/Search/QueryFactory.php index 23e93a1..98e3324 100644 --- a/Classes/Domain/Search/QueryFactory.php +++ b/Classes/Domain/Search/QueryFactory.php @@ -23,7 +23,6 @@ namespace Codappix\SearchCore\Domain\Search; use Codappix\SearchCore\Configuration\ConfigurationContainerInterface; use Codappix\SearchCore\Configuration\ConfigurationUtility; use Codappix\SearchCore\Configuration\InvalidArgumentException; -use Codappix\SearchCore\Connection\Elasticsearch\Query; use Codappix\SearchCore\Connection\SearchRequestInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Utility\ArrayUtility; diff --git a/Classes/Domain/Search/SearchService.php b/Classes/Domain/Search/SearchService.php index 03fc11b..3a83b7b 100644 --- a/Classes/Domain/Search/SearchService.php +++ b/Classes/Domain/Search/SearchService.php @@ -74,11 +74,7 @@ class SearchService $this->dataProcessorService = $dataProcessorService; } - /** - * @param SearchRequestInterface $searchRequest - * @return SearchResultInterface - */ - public function search(SearchRequestInterface $searchRequest) + public function search(SearchRequestInterface $searchRequest) : SearchResultInterface { $this->addSize($searchRequest); $this->addConfiguredFacets($searchRequest); @@ -93,8 +89,6 @@ class SearchService /** * Add configured size of search result items to request. - * - * @param SearchRequestInterface $searchRequest */ protected function addSize(SearchRequestInterface $searchRequest) { @@ -105,8 +99,6 @@ class SearchService /** * Add facets from configuration to request. - * - * @param SearchRequestInterface $searchRequest */ protected function addConfiguredFacets(SearchRequestInterface $searchRequest) { @@ -126,8 +118,6 @@ class SearchService /** * Add filters from configuration, e.g. flexform or TypoScript. - * - * @param SearchRequestInterface $searchRequest */ protected function addConfiguredFilters(SearchRequestInterface $searchRequest) { diff --git a/Classes/Domain/Service/DataHandler.php b/Classes/Domain/Service/DataHandler.php index edb6386..de226b9 100644 --- a/Classes/Domain/Service/DataHandler.php +++ b/Classes/Domain/Service/DataHandler.php @@ -22,9 +22,9 @@ namespace Codappix\SearchCore\Domain\Service; use Codappix\SearchCore\Configuration\ConfigurationContainerInterface; use Codappix\SearchCore\Domain\Index\IndexerFactory; +use Codappix\SearchCore\Domain\Index\IndexerInterface; use Codappix\SearchCore\Domain\Index\NoMatchingIndexerException; use TYPO3\CMS\Core\SingletonInterface as Singleton; -use TYPO3\CMS\Core\Utility\GeneralUtility; /** * Handles all data related things like updates, deletes and inserts. @@ -82,41 +82,27 @@ class DataHandler implements Singleton $this->indexerFactory = $indexerFactory; } - /** - * @param string $table - */ - public function update($table, array $record) + public function update(string $table, array $record) { $this->logger->debug('Record received for update.', [$table, $record]); $this->getIndexer($table)->indexDocument($record['uid']); } - /** - * @param string $table - * @param int $identifier - */ - public function delete($table, $identifier) + public function delete(string $table, string $identifier) { $this->logger->debug('Record received for delete.', [$table, $identifier]); $this->connection->deleteDocument($table, $identifier); } /** - * @param string $table - * @return IndexerInterface - * * @throws NoMatchingIndexerException */ - protected function getIndexer($table) + protected function getIndexer(string $table) : IndexerInterface { return $this->indexerFactory->getIndexer($table); } - /** - * @param string $table - * @return bool - */ - public function canHandle($table) + public function supportsTable(string $table) : bool { try { $this->getIndexer($table); @@ -124,7 +110,5 @@ class DataHandler implements Singleton } catch (NoMatchingIndexerException $e) { return false; } - - return false; } } diff --git a/Classes/Hook/DataHandler.php b/Classes/Hook/DataHandler.php index 22f1175..71fe44b 100644 --- a/Classes/Hook/DataHandler.php +++ b/Classes/Hook/DataHandler.php @@ -48,46 +48,38 @@ class DataHandler implements Singleton /** * Dependency injection as TYPO3 doesn't provide it on it's own. * Still you can submit your own dataHandler. - * - * @param OwnDataHandler $dataHandler - * @param Logger $logger */ public function __construct(OwnDataHandler $dataHandler = null, Logger $logger = null) { - $this->dataHandler = $dataHandler; - if ($this->dataHandler === null) { + if ($dataHandler === null) { try { - $this->dataHandler = GeneralUtility::makeInstance(ObjectManager::class) + $dataHandler = GeneralUtility::makeInstance(ObjectManager::class) ->get(OwnDataHandler::class); } catch (NoConfigurationException $e) { // We have no configuration. That's fine, hooks will not be // executed due to check for existing DataHandler. } } + $this->dataHandler = $dataHandler; - $this->logger = $logger; - if ($this->logger === null) { - $this->logger = GeneralUtility::makeInstance(LogManager::class) + if ($logger === null) { + $logger = GeneralUtility::makeInstance(LogManager::class) ->getLogger(__CLASS__); } + $this->logger = $logger; } /** * Called by CoreDataHandler on deletion of records. - * - * @param string $table - * @param int $uid - * - * @return bool False if hook was not processed. */ - public function processCmdmap_deleteAction($table, $uid) + public function processCmdmap_deleteAction(string $table, int $uid) : bool { if (! $this->shouldProcessHookForTable($table)) { $this->logger->debug('Delete not processed.', [$table, $uid]); return false; } - $this->dataHandler->delete($table, $uid); + $this->dataHandler->delete($table, (string) $uid); return true; } @@ -97,8 +89,8 @@ class DataHandler implements Singleton $uid = key($record); $fieldData = current($record); - if (isset($fieldArray['uid'])) { - $uid = $fieldArray['uid']; + if (isset($fieldData['uid'])) { + $uid = $fieldData['uid']; } elseif (isset($dataHandler->substNEWwithIDs[$uid])) { $uid = $dataHandler->substNEWwithIDs[$uid]; } @@ -124,17 +116,13 @@ class DataHandler implements Singleton return false; } - /** - * @param string $table - * @return bool - */ - protected function shouldProcessHookForTable($table) + protected function shouldProcessHookForTable(string $table) : bool { if ($this->dataHandler === null) { $this->logger->debug('Datahandler could not be setup.'); return false; } - if (! $this->dataHandler->canHandle($table)) { + if (! $this->dataHandler->supportsTable($table)) { $this->logger->debug('Table is not allowed.', [$table]); return false; } @@ -145,11 +133,9 @@ class DataHandler implements Singleton /** * Wrapper to allow unit testing. * - * @param string $table - * @param int $uid - * @return null|array + * @return array|null */ - protected function getRecord($table, $uid) + protected function getRecord(string $table, int $uid) { return BackendUtility::getRecord($table, $uid); } diff --git a/Classes/Utility/FrontendUtility.php b/Classes/Utility/FrontendUtility.php index 1282421..ffdbb6d 100644 --- a/Classes/Utility/FrontendUtility.php +++ b/Classes/Utility/FrontendUtility.php @@ -29,10 +29,7 @@ use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; */ class FrontendUtility extends BackendUtility { - /** - * @return TypoScriptFrontendController - */ - protected static function getLanguageService() + protected static function getLanguageService() : TypoScriptFrontendController { return $GLOBALS['TSFE']; } diff --git a/Documentation/source/changelog.rst b/Documentation/source/changelog.rst index 0d7f020..3b121a3 100644 --- a/Documentation/source/changelog.rst +++ b/Documentation/source/changelog.rst @@ -5,4 +5,5 @@ Changelog :maxdepth: 1 :glob: - changelog/* + changelog/20180408-introduce-php70-type-hints + changelog/20180406-120-facet-configuration diff --git a/Documentation/source/changelog/20180406-120-facet-configuration.rst b/Documentation/source/changelog/20180406-120-facet-configuration.rst index 53021d9..0c2338f 100644 --- a/Documentation/source/changelog/20180406-120-facet-configuration.rst +++ b/Documentation/source/changelog/20180406-120-facet-configuration.rst @@ -1,4 +1,4 @@ -Breacking Change 120 "Pass facets configuration to elasticsearch" +Breacking Change 120 "Pass facets configuration to Elasticsearch" ================================================================= In order to allow arbitrary facet configuration, we do not process the facet configuration anymore. @@ -35,6 +35,6 @@ Instead you have to provide the full configuration yourself: } } -You need to add line 4 and 6, the additional level ``terms`` for elasticsearch. +You need to add line 4 and 6, the additional level ``terms`` for Elasticsearch. See :issue:`120`. diff --git a/Documentation/source/changelog/20180408-introduce-php70-type-hints.rst b/Documentation/source/changelog/20180408-introduce-php70-type-hints.rst new file mode 100644 index 0000000..cc2dfe3 --- /dev/null +++ b/Documentation/source/changelog/20180408-introduce-php70-type-hints.rst @@ -0,0 +1,12 @@ +Breacking Change "Introduce PHP 7.0 TypeHints" +============================================== + +As PHP evolved, we now migrate the whole code base to use PHP 7.0 type hints. +We do not use PHP 7.1 Type Hints, as some customers still need PHP 7.0 support. + +Also we added missing methods to interfaces, that were already used in code. + +As this leads to changed method signatures, most custom implementations of interfaces, or overwrites +of existing methods are broken. + +To fix, just update the signatures as pointed out by PHP while running the code. diff --git a/Documentation/source/concepts.rst b/Documentation/source/concepts.rst index f4c5bbd..f81121b 100644 --- a/Documentation/source/concepts.rst +++ b/Documentation/source/concepts.rst @@ -3,33 +3,35 @@ Concepts ======== -The extension is built with the following concepts in mind. +The main concept is to provide a foundation where other developers can profit from, to provide +integrations into search services like Elasticsearch, Algolia, ... . + +Our code contains the following concepts which should be understand: .. _concepts_connections: Connections ----------- -It should be possible to use different search services like elasticsearch and solr out of the box. -If a service is not contained, it should be possible to implement the necessary part by implementing -the necessary interfaces and configuring the extension to use the new connection. +Different search services can provide integrations. ``search_core`` only provides abstractions and +interfaces. The main purpose is to provide a stable API between TYPO3 and concrete connection. -Also it should be possible to use multiple connections at once. This way multiple search services -can be used in the same installation. - -Currently only :ref:`Elasticsearch` is provided. +For information about implementing a new connection, take a look at :ref:`development_connection`. .. _concepts_indexing: Indexing -------- -The indexing is done by one of the available indexer. For each identifier it's possible to define -the indexer to use. Also it's possible to write custom indexer to use. +Indexing is the process of collecting and preparing data, before sending it to a Connection. +The indexing is done by one of the available indexer. Indexer are identified by a key, as configured +in TypoScript. -Currently only the :ref:`TcaIndexer` is provided. +Currently :ref:`TcaIndexer` and :ref:`PagesIndexer` are provided. -.. _concepts_indexing_dataprocessing: +For information about implementing a new indexer, take a look at :ref:`development_indexer`. + +.. _concepts_dataprocessing: DataProcessing ^^^^^^^^^^^^^^ @@ -39,4 +41,9 @@ known by :ref:`t3tsref:cobj-fluidtemplate-properties-dataprocessing` of :ref:`t3 The same is true for retrieved search results. They can be processed again by "DataProcessors" to prepare data for display in Templates or further usage. -Configuration is done through TypoScript, see :ref:`dataProcessing`. +This should keep indexers simple and move logic to DataProcessors. This makes most parts highly +flexible as integrators are able to configure DataProcessors and change their order. + +Configuration is done through TypoScript, see :ref:`dataprocessors`. + +For information about implementing a new DataProcessor, take a look at :ref:`development_dataprocessor`. diff --git a/Documentation/source/conf.py b/Documentation/source/conf.py index 1419689..aa846e0 100644 --- a/Documentation/source/conf.py +++ b/Documentation/source/conf.py @@ -51,7 +51,7 @@ master_doc = 'index' # General information about the project. project = u'TYPO3 Extension search_core' -copyright = u'2016, Daniel Siepmann' +copyright = u'2016 - 2018, Daniel Siepmann' author = u'Daniel Siepmann' # The version info for the project you're documenting, acts as replacement for @@ -59,9 +59,9 @@ author = u'Daniel Siepmann' # built documents. # # The short X.Y version. -version = u'1.0.0' +version = u'0.0.1' # The full version, including alpha/beta/rc tags. -release = u'1.0.0' +release = u'0.0.1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -133,7 +133,7 @@ html_theme_options = { # The name for this set of Sphinx documents. # " v documentation" by default. -#html_title = u'TYPO3 Extension search_core v1.0.0' +#html_title = u'TYPO3 Extension search_core v0.0.1' # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None @@ -150,7 +150,7 @@ html_theme_options = { # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +# html_static_path = ['_static'] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied diff --git a/Documentation/source/configuration.rst b/Documentation/source/configuration.rst index 09289ac..53ac469 100644 --- a/Documentation/source/configuration.rst +++ b/Documentation/source/configuration.rst @@ -8,9 +8,9 @@ Configuration Installation wide configuration is handled inside of the extension manager. Just check out the options there, they all have labels. -The extension offers the following configuration options through TypoScript. If you overwrite them -through `setup` make sure to keep them in the `module` area as they will be accessed from backend -mode of TYPO3 for indexing. Do so by placing the following line at the end:: +Everything else is configured through TypoScript. If you overwrite them through `setup` make sure to +keep them in the `module` area as they will be accessed from backend mode of TYPO3 for indexing. Do +so by placing the following line at the end:: module.tx_searchcore < plugin.tx_searchcore @@ -26,12 +26,10 @@ Here is the example default configuration that's provided through static include .. literalinclude:: ../../Configuration/TypoScript/constants.txt :language: typoscript - :linenos: :caption: Static TypoScript Constants .. literalinclude:: ../../Configuration/TypoScript/setup.txt :language: typoscript - :linenos: :caption: Static TypoScript Setup .. _configuration_options: diff --git a/Documentation/source/configuration/connections.rst b/Documentation/source/configuration/connections.rst index 5819730..6d0c524 100644 --- a/Documentation/source/configuration/connections.rst +++ b/Documentation/source/configuration/connections.rst @@ -4,7 +4,7 @@ Connections =========== Holds settings regarding the different possible connections for search services like Elasticsearch -or Solr. +or Algolia. Configured as:: @@ -22,15 +22,13 @@ Configured as:: Where ``connectionName`` is one of the available :ref:`connections`. -The following settings are available. For each setting its documented which connection consumes it. +The following settings are available. .. _host: ``host`` -------- -Used by: :ref:`Elasticsearch`. - The host, e.g. ``localhost`` or an IP where the search service is reachable from TYPO3 installation. @@ -43,13 +41,8 @@ Example:: ``port`` -------- -Used by: :ref:`Elasticsearch`. - The port where search service is reachable. E.g. default ``9200`` for Elasticsearch. Example:: plugin.tx_searchcore.settings.connections.elasticsearch.port = 9200 - - - diff --git a/Documentation/source/configuration/dataProcessing/RemoveProcessor.rst b/Documentation/source/configuration/dataProcessing/RemoveProcessor.rst index c8653a5..d39b42d 100644 --- a/Documentation/source/configuration/dataProcessing/RemoveProcessor.rst +++ b/Documentation/source/configuration/dataProcessing/RemoveProcessor.rst @@ -1,7 +1,7 @@ ``Codappix\SearchCore\DataProcessing\RemoveProcessor`` ====================================================== -Will remove fields from record, e.g. if you do not want to sent them to elasticsearch at all. +Will remove fields from record. Possible Options: diff --git a/Documentation/source/configuration/dataProcessing/availableAndPlanned.rst b/Documentation/source/configuration/dataProcessing/availableAndPlanned.rst deleted file mode 100644 index 9f31736..0000000 --- a/Documentation/source/configuration/dataProcessing/availableAndPlanned.rst +++ /dev/null @@ -1,36 +0,0 @@ -The following Processor are available: - -.. toctree:: - :maxdepth: 1 - :glob: - - /configuration/dataProcessing/ContentObjectDataProcessorAdapterProcessor - /configuration/dataProcessing/CopyToProcessor - /configuration/dataProcessing/GeoPointProcessor - /configuration/dataProcessing/RemoveProcessor - -The following Processor are planned: - - ``Codappix\SearchCore\DataProcessing\ReplaceProcessor`` - Will execute a search and replace on configured fields. - - ``Codappix\SearchCore\DataProcessing\RootLevelProcessor`` - Will attach the root level to the record. - - ``Codappix\SearchCore\DataProcessing\ChannelProcessor`` - Will add a configurable channel to the record, e.g. if you have different areas in your - website like "products" and "infos". - - ``Codappix\SearchCore\DataProcessing\RelationResolverProcessor`` - Resolves all relations using the TCA. - -Of course you are able to provide further processors. Just implement -``Codappix\SearchCore\DataProcessing\ProcessorInterface`` and use the FQCN (=Fully qualified -class name) as done in the examples above. - -By implementing also the same interface as necessary for TYPO3 -:ref:`t3tsref:cobj-fluidtemplate-properties-dataprocessing`, you are able to reuse the same code -also for Fluid to prepare the same record fetched from DB for your fluid. - -Dependency injection is possible inside of processors, as we instantiate through extbase -``ObjectManager``. diff --git a/Documentation/source/configuration/indexing.rst b/Documentation/source/configuration/indexing.rst index 7d6c3d4..050f0ab 100644 --- a/Documentation/source/configuration/indexing.rst +++ b/Documentation/source/configuration/indexing.rst @@ -40,11 +40,7 @@ Contains a comma separated list of page uids. Spaces are trimmed. Example:: - plugin.tx_searchcore.settings.indexing..rootLineBlacklist = 3, 10, 100 - -Also it's possible to define some behaviour for the different document types. In context of TYPO3 -tables are used as document types 1:1. It's possible to configure different tables. The following -options are available: + plugin.tx_searchcore.settings.indexing.pages.rootLineBlacklist = 3, 10, 100 .. _additionalWhereClause: @@ -55,16 +51,16 @@ Used by: :ref:`TcaIndexer`, :ref:`PagesIndexer`. Add additional SQL to where clauses to determine indexable records from the table. This way you can exclude specific records like ``tt_content`` records with specific ``CType`` values or -something else. E.g. you can add a new field to the table to exclude records from indexing. +something else. Example:: - plugin.tx_searchcore.settings.indexing..additionalWhereClause = tt_content.CType NOT IN ('gridelements_pi1', 'list', 'div', 'menu') + plugin.tx_searchcore.settings.indexing.tt_content.additionalWhereClause = tt_content.CType NOT IN ('gridelements_pi1', 'list', 'div', 'menu') .. attention:: Make sure to prefix all fields with the corresponding table name. The selection from - database will contain joins and can lead to SQL errors if a field exists in multiple tables. + database might contain joins and can lead to SQL errors if a field exists in multiple tables. .. _abstractFields: @@ -73,6 +69,10 @@ abstractFields Used by: :ref:`PagesIndexer`. +.. note:: + + Will be migrated to :ref:`dataprocessors` in the future. + Define which field should be used to provide the auto generated field "search_abstract". The fields have to exist in the record to be indexed. Therefore fields like ``content`` are also possible. @@ -80,7 +80,7 @@ possible. Example:: # As last fallback we use the content of the page - plugin.tx_searchcore.settings.indexing..abstractFields := addToList(content) + plugin.tx_searchcore.settings.indexing.pages.abstractFields := addToList(content) Default:: @@ -91,10 +91,10 @@ Default:: mapping ------- -Used by: Elasticsearch connection while indexing. +Used by: :ref:`connection_elasticsearch` connection while indexing. Define mapping for Elasticsearch, have a look at the official docs: https://www.elastic.co/guide/en/elasticsearch/reference/5.2/mapping.html -You are able to define the mapping for each property / columns. +You are able to define the mapping for each property / column. Example:: @@ -112,7 +112,7 @@ makes building a facet possible. index ----- -Used by: Elasticsearch connection while indexing. +Used by: :ref:`connection_elasticsearch` connection while indexing. Define index for Elasticsearch, have a look at the official docs: https://www.elastic.co/guide/en/elasticsearch/reference/5.2/indices-create-index.html @@ -141,36 +141,12 @@ Example:: ``char_filter`` and ``filter`` are a comma separated list of options. -.. _dataProcessing: +.. _indexing_dataProcessing: dataProcessing -------------- Used by: All connections while indexing, due to implementation inside ``AbstractIndexer``. -Configure modifications on each document before sending it to the configured connection. Same as -provided by TYPO3 for :ref:`t3tsref:cobj-fluidtemplate` through -:ref:`t3tsref:cobj-fluidtemplate-properties-dataprocessing`. - -All processors are applied in configured order. Allowing to work with already processed data. - -Example:: - - plugin.tx_searchcore.settings.indexing.tt_content.dataProcessing { - 1 = Codappix\SearchCore\DataProcessing\CopyToProcessor - 1 { - to = search_spellcheck - } - - 2 = Codappix\SearchCore\DataProcessing\CopyToProcessor - 2 { - to = search_all - } - } - -The above example will copy all existing fields to the field ``search_spellcheck``. Afterwards -all fields, including ``search_spellcheck`` will be copied to ``search_all``. - -.. include:: /configuration/dataProcessing/availableAndPlanned.rst - -Also data processors are available for search results too, see :ref:`searching_dataProcessing`. +Configure modifications on each document before sending it to the configured connection. +For full documentation check out :ref:`dataprocessors`. diff --git a/Documentation/source/configuration/searching.rst b/Documentation/source/configuration/searching.rst index 857aa74..52abc07 100644 --- a/Documentation/source/configuration/searching.rst +++ b/Documentation/source/configuration/searching.rst @@ -8,45 +8,50 @@ Searching size ---- -Used by: Elasticsearch connection while building search query. - Defined how many search results should be fetched to be available in search result. Example:: plugin.tx_searchcore.settings.searching.size = 50 -Default if not configured is 10. +Default is ``10``. .. _facets: facets ------ -Used by: Elasticsearch connection while building search query. - Define aggregations for Elasticsearch, have a look at the official docs: https://www.elastic.co/guide/en/elasticsearch/reference/5.2/search-aggregations-bucket-terms-aggregation.html -Currently only the term facet is provided. Example:: - plugin.tx_searchcore.settings.searching.facets { - contentTypes { - field = CType + category { + terms { + field = categories } } -The above example will provide a facet with options for all found ``CType`` results together -with a count. + month { + date_histogram { + field = released + interval = month + format = Y-MM-01 + order { + _time = desc + } + } + } + + +The above example will provide a facet with options for all found ``categories`` results together +with a count. Also a facet for ``released`` will be provided. .. _filter: filter ------ -Used by: While building search request. - -Define filter that should be set for all requests. +Define filter that should be set for all search requests. Example:: @@ -54,6 +59,9 @@ Example:: property = value } +Also see :ref:`mapping.filter` to map incoming request information, e.g. from a ``select``, to build +more complex filters. + For Elasticsearch the fields have to be filterable, e.g. need a mapping as ``keyword``. .. _minimumShouldMatch: @@ -61,9 +69,8 @@ For Elasticsearch the fields have to be filterable, e.g. need a mapping as ``key minimumShouldMatch ------------------ -Used by: Elasticsearch connection while building search query. - -Define the minimum match for Elasticsearch, have a look at the official docs: https://www.elastic.co/guide/en/elasticsearch/reference/5.2/query-dsl-minimum-should-match.html +Define the minimum match for Elasticsearch, have a look at the official docs: +https://www.elastic.co/guide/en/elasticsearch/reference/5.2/query-dsl-minimum-should-match.html Example:: @@ -74,8 +81,6 @@ Example:: boost ----- -Used by: Elasticsearch connection while building search query. - Define fields that should boost the score for results. Example:: @@ -93,10 +98,9 @@ https://www.elastic.co/guide/en/elasticsearch/guide/2.x/_boosting_query_clauses. fieldValueFactor ---------------- -Used by: Elasticsearch connection while building search query. - -Define a field to use as a factor for scoring. The configuration is passed through to elastic -search ``field_value_factor``, see: https://www.elastic.co/guide/en/elasticsearch/reference/5.2/query-dsl-function-score-query.html#function-field-value-factor +Define a field to use as a factor for scoring. The configuration is passed through to Elasticsearch +``field_value_factor``, see: +https://www.elastic.co/guide/en/elasticsearch/reference/5.2/query-dsl-function-score-query.html#function-field-value-factor Example:: @@ -119,34 +123,34 @@ E.g. you submit a filter in form of: .. code-block:: html - - Due to TYPO3 7.x fluid limitations, we build this input ourself. - No longer necessary in 8 and above - - - + + Due to TYPO3 7.x fluid limitations, we build this input ourself. + No longer necessary in 8 and above + + + -This will create a ``distance`` filter with subproperties. To make this filter actually work, you +This will create a ``month`` filter with sub properties. To make this filter actually work, you can add the following TypoScript, which will be added to the filter:: mapping { @@ -167,38 +171,36 @@ can add the following TypoScript, which will be added to the filter:: } ``fields`` has a special meaning here. This will actually map the properties of the filter to fields -in elasticsearch. In above example they do match, but you can also use different names in your form. -On the left hand side is the elasticsearch field name, on the right side the one submitted as a -filter. +in Elasticsearch. On the left hand side is the Elasticsearch field name, on the right side the one +submitted as a filter. -The ``field``, in above example ``released``, will be used as the elasticsearch field for -filtering. This way you can use arbitrary filter names and map them to existing elasticsearch fields. +The ``field``, in above example ``released``, will be used as the Elasticsearch field for +filtering. This way you can use arbitrary filter names and map them to existing Elasticsearch fields. Everything that is configured inside ``raw`` is passed, as is, to search service, e.g. -elasticsearch. +Elasticsearch. .. _fields: fields ------ -Defines the fields to fetch and search from elasticsearch. With the following sub keys: +Defines the fields to fetch and search from Elasticsearch. With the following sub keys: -``query`` defines the fields to search in. Default is ``_all`` from 5.x times of elasticsearch. -Configure a comma separated list of fields to search in. This is necessary if you have configured -special mapping for some fields, or just want to search some fields. -The most hits get ranked highest. The following is an example configuration:: +``query`` defines the fields to search in. Configure a comma separated list of fields to search in. +This is necessary if you have configured special mapping for some fields, or just want to search +some fields. The following is an example configuration:: fields { query = _all, city } -The following sub properties configure the fields to fetch from elasticsearch: +The following sub properties configure the fields to fetch from Elasticsearch: First ``stored_fields`` which is a list of comma separated fields which actually exist and will be added. Typically you will use ``_source`` to fetch the whole indexed fields. -Second is ``script_fields``, which allow you to configure scripted fields for elasticsearch. +Second is ``script_fields``, which allow you to configure scripted fields for Elasticsearch. An example might look like the following:: fields { @@ -221,7 +223,7 @@ In above example we add a single ``script_field`` called ``distance``. We add a field should be added. The condition will be parsed as Fluidtemplate and is casted to bool via PHP. If the condition is true, or no ``condition`` exists, the ``script_field`` will be added to the query. The ``condition`` will be removed and everything else is submitted one to one to -elasticsearch, except each property is run through Fluidtemplate, to allow you to use information +Elasticsearch, except each property is run through Fluidtemplate, to allow you to use information from search request, e.g. to insert latitude and longitude from a filter, like in the above example. .. _sort: @@ -246,38 +248,14 @@ Example:: mode = filter } -Only ``filter`` is allowed as value. Will submit an empty query to switch to filter mode. +Only ``filter`` is allowed as value, as ``search`` is default behaviour. Using ``filter`` will +trigger a search to provide data while visiting the page, possible :ref:`filter` allow you to build +pages like "News". -.. _searching_dataProcessing: +.. _searching_dataprocessing: dataProcessing -------------- -Used by: All connections while indexing, due to implementation inside ``SearchService``. - -Configure modifications on each document before returning search result. Same as provided by TYPO3 -for :ref:`t3tsref:cobj-fluidtemplate` through -:ref:`t3tsref:cobj-fluidtemplate-properties-dataprocessing`. - -All processors are applied in configured order. Allowing to work with already processed data. - -Example:: - - plugin.tx_searchcore.settings.searching.dataProcessing { - 1 = Codappix\SearchCore\DataProcessing\CopyToProcessor - 1 { - to = search_spellcheck - } - - 2 = Codappix\SearchCore\DataProcessing\CopyToProcessor - 2 { - to = search_all - } - } - -The above example will copy all existing fields to the field ``search_spellcheck``. Afterwards -all fields, including ``search_spellcheck`` will be copied to ``search_all``. - -.. include:: /configuration/dataProcessing/availableAndPlanned.rst - -Also data processors are available while indexing too, see :ref:`dataProcessing`. +Configure modifications on each document before returning search result. +For full documentation check out :ref:`dataprocessors`. diff --git a/Documentation/source/connections.rst b/Documentation/source/connections.rst index b51f280..73ce273 100644 --- a/Documentation/source/connections.rst +++ b/Documentation/source/connections.rst @@ -5,26 +5,25 @@ Connections See Concept of :ref:`concepts_connections` for further background information. -The extension provides the following connections out of the box: +For information about implementing a new connection, take a look at :ref:`development_connection`. -.. _Elasticsearch: +The following connections were developed, or are in development, for ``search_core``: + +.. _connection_elasticsearch: Elasticsearch ------------- -Integrates `elastic Elasticsearch`_ using `elastica`_ into TYPO3. +Support for `Elasticsearch`_ is provided out of the box by `search_core` at the moment. -Provides basic support like indexing without mappings and full text search at the moment. +.. _Elasticsearch: https://www.elastic.co/products/elasticsearch -The connection is configurable through the following options: +.. _connection_algolia: -* :ref:`host` +Algolia +------- -* :ref:`port` +`search_algolia`_ will integrate `Algolia`_ and is currently under development by Martin Hummer. -* :ref:`mapping` - -* :ref:`facets` - -.. _elastic Elasticsearch: https://www.elastic.co/products/elasticsearch -.. _elastica: http://elastica.io/ +.. _search_algolia: https://github.com/martinhummer/search_algolia/ +.. _Algolia: https://www.algolia.com/ diff --git a/Documentation/source/dataprocessors.rst b/Documentation/source/dataprocessors.rst new file mode 100644 index 0000000..67ff655 --- /dev/null +++ b/Documentation/source/dataprocessors.rst @@ -0,0 +1,98 @@ +.. _dataprocessors: + +DataProcessors +============== + +See Concept of :ref:`concepts_dataprocessing` for further background information. + +For information about implementing a new DataProcessor, take a look at +:ref:`development_dataprocessor`. + +Same as provided by TYPO3 for :ref:`t3tsref:cobj-fluidtemplate` through +:ref:`t3tsref:cobj-fluidtemplate-properties-dataprocessing`. + +.. _dataprocessors_usage: + +Usage +----- + +All processors are applied in configured order. Allowing to work with already processed data. +They can be applied during indexing and for search results. + +Example for indexing:: + + plugin.tx_searchcore.settings.indexing.pages.dataProcessing { + 1 = Codappix\SearchCore\DataProcessing\CopyToProcessor + 1 { + to = search_spellcheck + } + + 2 = Codappix\SearchCore\DataProcessing\CopyToProcessor + 2 { + to = search_all + } + } + +The above example will copy all existing fields to the field ``search_spellcheck``. Afterwards +all fields, including ``search_spellcheck`` will be copied to ``search_all``. + +Example for search results:: + + plugin.tx_searchcore.settings.searching.dataProcessing { + 1 = Codappix\SearchCore\DataProcessing\CopyToProcessor + 1 { + to = search_spellcheck + } + + 2 = Codappix\SearchCore\DataProcessing\CopyToProcessor + 2 { + to = search_all + } + } + +The above example will copy all existing fields to the field ``search_spellcheck``. Afterwards +all fields, including ``search_spellcheck`` will be copied to ``search_all``. + +.. _dataprocessors_availableDataProcessors: + +Available DataProcessors +------------------------ + +.. toctree:: + :maxdepth: 1 + :glob: + + /configuration/dataProcessing/ContentObjectDataProcessorAdapterProcessor + /configuration/dataProcessing/CopyToProcessor + /configuration/dataProcessing/GeoPointProcessor + /configuration/dataProcessing/RemoveProcessor + +.. _dataprocessors_plannedDataProcessors: + +Planned DataProcessors +---------------------- + + ``Codappix\SearchCore\DataProcessing\ReplaceProcessor`` + Will execute a search and replace on configured fields. + + ``Codappix\SearchCore\DataProcessing\RootLevelProcessor`` + Will attach the root level to the record. + + ``Codappix\SearchCore\DataProcessing\ChannelProcessor`` + Will add a configurable channel to the record, e.g. if you have different areas in your + website like "products" and "infos". + + ``Codappix\SearchCore\DataProcessing\RelationResolverProcessor`` + Resolves all relations using the TCA. + This is currently done through indexer. + +.. Of course you are able to provide further processors. Just implement +.. ``Codappix\SearchCore\DataProcessing\ProcessorInterface`` and use the FQCN (=Fully qualified +.. class name) as done in the examples above. + +.. By implementing also the same interface as necessary for TYPO3 +.. :ref:`t3tsref:cobj-fluidtemplate-properties-dataprocessing`, you are able to reuse the same code +.. also for Fluid to prepare the same record fetched from DB for your fluid. + +.. Dependency injection is possible inside of processors, as we instantiate through extbase +.. ``ObjectManager``. diff --git a/Documentation/source/development.rst b/Documentation/source/development.rst index e73425c..e65dcdf 100644 --- a/Documentation/source/development.rst +++ b/Documentation/source/development.rst @@ -1,71 +1,16 @@ .. highlight:: bash -.. _contribution: - -Contribution -============ - -Everyone is welcome to contribute, whether it's code, issues, feature requests or any other kind. - -Below is a documentation what to respect during contributions. - -.. _contribution_setup: - -Setup ------ - -To start contributions regarding code, make sure your environment matches the following -requirements: - -* composer is executable - -* PHP on CLI is executable - -* MySQL is up and running with user *dev* and password *dev* on *127.0.0.1* or to overwrite the - environment variables, see :file:`Makefile`. - And MySQL is not set to strict mode as TYPO3 doesn't support strict mode, see - https://review.typo3.org/#/c/26725/3/INSTALL.md. - -* Elasticsearch is installed and up and running on *localhost:9200*. - -Then setup your system:: - - git clone git@github.com:DanielSiepmann/search_core.git \ - && cd search_core \ - && export typo3DatabaseName="searchcoretest76" \ - && export TYPO3_VERSION="~7.6" \ - && make install \ - && make unitTests \ - && make functionalTests - -If all tests are okay, start your work. - -If you are working with multiple TYPO3 versions make sure to export `typo3DatabaseName` and -`TYPO3_VERSION` in your environment like:: - - export typo3DatabaseName="searchcoretest62" - export TYPO3_VERSION="~6.2" - -Also run the install command for each version before running any tests. Only this will make sure you -are testing against the actual TYPO3 Version and database scheme. - -.. _contribution_development: - Development ------------ +=========== -All changes are introduced through pull requests at `Github`_ and should contain the following: +There are some ways we will cover here. One is how you can develop own parts like Indexer, +DataProcessor and Connection. The other is how to contribute. -* Adjusted tests if tests existed before. Otherwise they will break on `travis-ci`_. +.. toctree:: + :maxdepth: 1 + :glob: -* New tests whenever possible and useful. - -* Code has to follow `PSR-2`_. - -* Adjusted documentation. - -* Make sure to follow the documented :ref:`concepts`. - -.. _Github: https://github.com/DanielSiepmann/search_core -.. _travis-ci: https://travis-ci.org/ -.. _PSR-2: http://www.php-fig.org/psr/psr-2/ + development/indexer + development/dataProcessor + development/connection + development/contribution diff --git a/Documentation/source/development/connection.rst b/Documentation/source/development/connection.rst new file mode 100644 index 0000000..af0ab14 --- /dev/null +++ b/Documentation/source/development/connection.rst @@ -0,0 +1,11 @@ +.. _development_connection: + +Develop a new Connection +======================== + +Make sure you understood :ref:`concepts_connections`. + +Each Connection has to be a single class which implements +``Codappix\SearchCore\Connection\ConnectionInterface``. + +Dependency Injection is working for custom Connections. diff --git a/Documentation/source/development/contribution.rst b/Documentation/source/development/contribution.rst new file mode 100644 index 0000000..c362c37 --- /dev/null +++ b/Documentation/source/development/contribution.rst @@ -0,0 +1,69 @@ +.. _contribution: + +Contribution +============ + +Everyone is welcome to contribute, whether it's code, issues, feature requests or any other kind. + +Below is a documentation what to respect during contributions. + +.. _contribution_setup: + +Setup +----- + +To start contributions regarding code, make sure your environment matches the following +requirements: + +* composer is executable + +* PHP on CLI is executable + +* MySQL is up and running with user *dev* and password *dev* on *127.0.0.1* or to overwrite the + environment variables, see :file:`Makefile`. + And MySQL is not set to strict mode as TYPO3 doesn't support strict mode, see + https://review.typo3.org/#/c/26725/3/INSTALL.md. + +* Elasticsearch is installed and up and running on *localhost:9200*. + +Then setup your system:: + + git clone git@github.com:codappix/search_core.git \ + && cd search_core \ + && export typo3DatabaseName="searchcoretest76" \ + && export TYPO3_VERSION="~8.7" \ + && make install \ + && make unitTests \ + && make functionalTests + +If all tests are okay, start your work. + +If you are working with multiple TYPO3 versions make sure to export `typo3DatabaseName` and +`TYPO3_VERSION` in your environment like:: + + export typo3DatabaseName="searchcoretest62" + export TYPO3_VERSION="~6.2" + +Also run the install command for each version before running any tests. Only this will make sure you +are testing against the actual TYPO3 Version and database scheme. + +.. _contribution_development: + +Development +----------- + +All changes are introduced through pull requests at `Github`_ and should contain the following: + +* Adjusted tests if tests existed before. Otherwise they will break on `travis-ci`_. + +* New tests whenever possible and useful. + +* Code has to follow `PSR-2`_. + +* Adjusted documentation. + +* Make sure to follow the documented :ref:`concepts`. + +.. _Github: https://github.com/codappix/search_core +.. _travis-ci: https://travis-ci.org/ +.. _PSR-2: http://www.php-fig.org/psr/psr-2/ diff --git a/Documentation/source/development/dataProcessor.rst b/Documentation/source/development/dataProcessor.rst new file mode 100644 index 0000000..af2732b --- /dev/null +++ b/Documentation/source/development/dataProcessor.rst @@ -0,0 +1,15 @@ +.. _development_dataprocessor: + +Develop a new DataProcessor +=========================== + +Make sure you understood :ref:`concepts_dataprocessing`. + +Each DataProcessor has to be a single class which implements +``Codappix\SearchCore\DataProcessing\ProcessorInterface``. + +Make sure you support both, Frontend and Backend, as processors can be called during searching and +indexing. Therefore do not rely on e.g. ``TSFE``, make sure dependencies are met and your code will +work in both environments. + +Dependency Injection is working for custom DataProcessors. diff --git a/Documentation/source/development/indexer.rst b/Documentation/source/development/indexer.rst new file mode 100644 index 0000000..d5a067e --- /dev/null +++ b/Documentation/source/development/indexer.rst @@ -0,0 +1,21 @@ +.. _development_indexer: + +Develop a new Indexer +===================== + +Make sure you understood :ref:`concepts_indexing`. + +Each indexer has to be a single class which implements +``Codappix\SearchCore\Domain\Index\IndexerInterface``. + +The indexer should call the connection with all necessary information about the document(s) to +trigger indexing or deletion of whole index. + +As this is the "indexer", deletion of single documents is directly processed by the connection. + +``setIdentifier`` is called with the identifier of the current Indexer. This might be useful to +fetch configuration, related to the indexing, from +``Codappix\SearchCore\Configuration\ConfigurationContainerInterface``. + +Dependency Injection is working for custom indexers, therefore you are able to inject the +``ConfigurationContainerInterface``. diff --git a/Documentation/source/features.rst b/Documentation/source/features.rst index 1a4abd6..57014bd 100644 --- a/Documentation/source/features.rst +++ b/Documentation/source/features.rst @@ -3,28 +3,34 @@ Features ======== -The following features are currently provided: +The following features are available: .. _features_indexing: Indexing -------- -Indexing data to Elasticsearch is provided. The extension delivers an indexer for TCA with zero -configuration needs. Still it's possible to configure the indexer. +Indexing of data is possible. We deliver an indexer for TCA with zero configuration needs. You can +also provide custom indexer for arbitrary data which is not indexable through TCA. -Also custom classes can be used as indexers. +Also a finisher for TYPO3 Form-Extension is provided to integrate indexing after something was +update through the Form-Extension. -Furthermore a finisher for TYPO3 Form-Extension is provided to integrate indexing. +Indexing is done through Hooks and CLI. We therefore provide commands to index and delete indexed +data. .. _features_search: Searching --------- -Currently all fields are searched for a single search input. +.. note:: + Currently only integrated for Elasticsearch with no abstraction. + If you need to implement your own search, please open an issue on Github and we will change the code + base. -Also multiple filter are supported. Filtering results by fields for string contents. +Via TypoScript it's possible to configure the fields to query, minimum match and script fields. +Also multiple filter are supported, filtering results by fields. Facets / aggregates are also possible. Therefore a mapping has to be defined in TypoScript for indexing, and the facets itself while searching. @@ -32,19 +38,25 @@ indexing, and the facets itself while searching. .. _features_dataProcessing: DataProcessing -============== +-------------- -DataProcessing, as known from ``FLUIDTEMPLATE`` is available while indexing and for search results. -Each item can be processed by multiple processor to prepare data for indexing and output. +DataProcessing, as known from ``FLUIDTEMPLATE``, is available while indexing and for search results. +Each record and result item can be processed by multiple processor to prepare data for indexing and +output. -See :ref:`concepts_indexing_dataprocessing` in :ref:`concepts` section. +See :ref:`concepts_dataprocessing` in :ref:`concepts` section. .. _features_planned: Planned ---------- +------- The following features are currently planned and will be integrated: -#. Pagination - Add a pagination to search results, to allow users to walk through all results. +#. :issue:`25` Multi language. +#. :issue:`94` Respect access rights while indexing relations. +#. :issue:`75` Configuration of index name (for Elasticsearch). + +For a full list, check out our `open issues`_. + +.. _open issues: https://github.com/Codappix/search_core/issues diff --git a/Documentation/source/index.rst b/Documentation/source/index.rst index 2edfae3..1cc9eb6 100644 --- a/Documentation/source/index.rst +++ b/Documentation/source/index.rst @@ -1,7 +1,7 @@ .. include:: readme.rst Table of Contents -================= +----------------- .. toctree:: :maxdepth: 1 @@ -14,5 +14,6 @@ Table of Contents concepts connections indexer + dataprocessors development changelog diff --git a/Documentation/source/indexer.rst b/Documentation/source/indexer.rst index 3bb10bc..733f5b9 100644 --- a/Documentation/source/indexer.rst +++ b/Documentation/source/indexer.rst @@ -5,6 +5,8 @@ Indexer See Concept of :ref:`concepts_indexing` for further background information. +For information about implementing a new indexer, take a look at :ref:`development_indexer`. + The extension provides the following indexer out of the box: .. _TcaIndexer: @@ -15,23 +17,12 @@ TcaIndexer Provides zero configuration TYPO3 integration by using the :ref:`t3tcaref:start`. You just can start indexing TYPO3. -The indexer will use the TCA to fetch all necessary information like relations. Currently the -implementation is very basic. In future it will also provide mapping for :ref:`Elasticsearch` and -further stuff. +Just add the indexer for a TYPO3 table. The indexer will use the TCA to fetch all necessary +information like relations. -The indexer is configurable through the following options: +.. note:: -* :ref:`rootLineBlacklist` - -* :ref:`additionalWhereClause` - -* :ref:`abstractFields` - -* :ref:`mapping` - -* :ref:`index` - -* :ref:`dataProcessing` + Not all relations are resolved yet, see :issue:`17`. .. _PagesIndexer: @@ -42,23 +33,7 @@ Provides zero configuration TYPO3 integration by using the :ref:`t3tcaref:start` start indexing TYPO3. The indexer will use the TCA to fetch all necessary information like relations. Currently the -implementation is very basic. In future it will also provide mapping for :ref:`Elasticsearch` and -further stuff. Also all static content from each page will be concatenated into a single field to -improve search. - -The indexer is configurable through the following options: - -* :ref:`rootLineBlacklist` - -* :ref:`additionalWhereClause` - -* :ref:`abstractFields` - -* :ref:`mapping` - -* :ref:`index` - -* :ref:`dataProcessing` +implementation is very basic. .. note:: diff --git a/Documentation/source/installation.rst b/Documentation/source/installation.rst index 5bb0c56..0a0e5b6 100644 --- a/Documentation/source/installation.rst +++ b/Documentation/source/installation.rst @@ -4,23 +4,41 @@ Installation ============ +Composer +-------- + The extension can be installed through composer:: - composer require "leonmrni/search_core dev-master as 1.0.x-dev" + composer require "codappix/search_core" "~1.0.0" -or by `downloading`_ and placing it inside the :file:`typo3conf/ext`-Folder of your installation. -In that case you need to install all dependencies yourself. Dependencies are: +Note that you have to allow unstable packages: + +.. code-block:: json + + { + "minimum-stability": "dev", + "prefer-stable": true + } + +Download +-------- + +You can also `download`_ the extension and placing it inside the :file:`typo3conf/ext`-Folder of +your installation. In that case you need to install all dependencies yourself. Dependencies are: .. literalinclude:: ../../composer.json :caption: Dependencies from composer.json :lines: 19-21 :dedent: 8 +Setup +----- + Afterwards you need to enable the extension through the extension manager and include the static TypoScript setup. -If you **don't** want to use the included elasticsearch integration, you have to disable it in the +If you **don't** want to use the included Elasticsearch integration, you have to disable it in the extension manager configuration of the extension by checking the checkbox. It's currently enabled by default but will be moved into its own extension in the future. -.. _downloading: https://github.com/DanielSiepmann/search_core/archive/master.zip +.. _download: https://github.com/codappix/search_core/archive/develop.zip diff --git a/Documentation/source/readme.rst b/Documentation/source/readme.rst index cc516d1..f4ad917 100644 --- a/Documentation/source/readme.rst +++ b/Documentation/source/readme.rst @@ -1,5 +1,5 @@ -TYPO3 Extension search_core's documentation! -============================================ +TYPO3 Extension search_core +=========================== Introduction ============ @@ -8,23 +8,21 @@ What does it do? ---------------- The goal of this extension is to provide search integrations into TYPO3 CMS. The extension will -abstract the concrete implementations to allow exchange of concrete backends like Elasticsearch or -solr. +provide a convenient API to allow developers to provide concrete implementations of backends like +Elasticsearch, Algolia or Solr. The extension provides integration into TYPO3 like a frontend plugin for searches and hooks to update search indexes on updates. Also a command line interface is provided for interactions like -reindexing. +re-indexing. Current state ------------- This is still a very early beta version. More information can be taken from Github at -`current issues`_ and `current projects`_. +`current issues`_. -We are also focusing on Code Quality and Testing through `travis ci`_, `scrutinizer`_ and `codacy`_. +We are also focusing on Code Quality and Testing through `travis ci`_, ``phpcs``, ``phpunit`` and +``phpstan``. .. _current issues: https://github.com/Codappix/search_core/issues -.. _current projects: https://github.com/Codappix/search_core/projects .. _travis ci: https://travis-ci.org/Codappix/search_core -.. _scrutinizer: https://scrutinizer-ci.com/g/Codappix/search_core/inspections -.. _codacy: https://www.codacy.com/app/Codappix/search_core/dashboard diff --git a/Documentation/source/usage.rst b/Documentation/source/usage.rst index d57d643..fc6d08a 100644 --- a/Documentation/source/usage.rst +++ b/Documentation/source/usage.rst @@ -11,9 +11,10 @@ Manual indexing You can trigger indexing from CLI:: - ./typo3/cli_dispatch.phpsh extbase index:index --identifier 'tt_content' + ./typo3/cli_dispatch.phpsh extbase index:index --identifier 'pages' + ./bin/typo3cms index:index --identifier 'pages' -This will index the table ``tt_content`` using the :ref:`TcaIndexer`. +This will index the table ``pages`` using the :ref:`TcaIndexer`. Only one index per call is available, to run multiple indexers, just make multiple calls. The indexers have to be defined in TypoScript via :ref:`configuration_options_index`. @@ -25,9 +26,10 @@ Manual deletion You can trigger deletion for a single index from CLI:: - ./typo3/cli_dispatch.phpsh extbase index:delete --identifier 'tt_content' + ./typo3/cli_dispatch.phpsh extbase index:delete --identifier 'pages' + ./bin/typo3cms index:delete --identifier 'pages' -This will delete the index for the table ``tt_content``. +This will delete the index for the table ``pages``. Only one delete per call is available, to run multiple deletions, just make multiple calls. @@ -53,7 +55,6 @@ A form finisher is provided to integrate indexing into form extension. Add form finisher to your available finishers and configure it like: .. code-block:: yaml - :linenos: - identifier: SearchCoreIndexer @@ -62,7 +63,7 @@ Add form finisher to your available finishers and configure it like: indexIdentifier: 'fe_users' recordUid: '{FeUser.user.uid}' -All three options are necessary, where +All three options are necessary, where: ``action`` Is one of ``delete``, ``update`` or ``add``. @@ -81,7 +82,7 @@ plugin. The plugin is named *Search Core*. Please provide your own template, the extension will not deliver a useful template for now. -The extbase mapping is used, this way you can create a form: +The Extbase mapping is used, this way you can create a form: .. code-block:: html @@ -95,11 +96,10 @@ The extbase mapping is used, this way you can create a form: Filter """""" -Thanks to extbase mapping, filter are added to the form: +Thanks to Extbase mapping, filter are added to the form: .. code-block:: html - .. _usage_searching_facets: diff --git a/Tests/Functional/Connection/Elasticsearch/IndexDeletionTest.php b/Tests/Functional/Connection/Elasticsearch/IndexDeletionTest.php index 8297a2a..05070b2 100644 --- a/Tests/Functional/Connection/Elasticsearch/IndexDeletionTest.php +++ b/Tests/Functional/Connection/Elasticsearch/IndexDeletionTest.php @@ -25,6 +25,14 @@ use TYPO3\CMS\Extbase\Object\ObjectManager; class IndexDeletionTest extends AbstractFunctionalTestCase { + protected function getDataSets() + { + return array_merge( + parent::getDataSets(), + ['Tests/Functional/Fixtures/Indexing/IndexTcaTable.xml'] + ); + } + /** * @test */