silverstripe / silverstripe-elemental

Create pages in Silverstripe CMS using content blocks
http://dna.co.nz
BSD 3-Clause "New" or "Revised" License
110 stars 115 forks source link

ElementalSolrIndex breaks Solr_Configure #206

Closed markhowardnz closed 6 years ago

markhowardnz commented 6 years ago

With a default Silverstripe setup, plus the dnadesign/silverstripe-elemental and silverstripe/fulltextsearch-localsolr dependencies, I cannot successfully run vendor/bin/sake dev/tasks/Solr_Configure

I have project which is happily using Elemental. I then add the fulltextsearch-localsolr dependency and follow the instructions on https://github.com/silverstripe/silverstripe-fulltextsearch/blob/master/docs/en/Solr.md

I configure the SS _config.php and create my own subclass of SolrIndex. I get as far as running vendor/bin/sake dev/tasks/Solr_Configure

At this point, the Solr_Configure task finds my index and works OK, then finds the ElementalSolrIndex class and tries to build that index. It fails with:

ERROR [Emergency]: Uncaught InvalidArgumentException: Can't add classes which don't have data tables (no $db or $has_one set on the class)
IN GET dev/tasks/Solr_Configure
Line 286 in /var/www/silverstripe-clearfield-v4/clearfield/vendor/silverstripe/fulltextsearch/src/Search/Indexes/SearchIndex.php

Source
======
  277:      * @param array $options - TODO: Remove
  278:      */
  279:     public function addClass($class, $options = array())
  280:     {
  281:         if ($this->fulltextFields || $this->filterFields || $this->sortFields) {
  282:             throw new Exception('Can\'t add class to Index after fields have already been added');
  283:         }
  284: 
  285:         if (!DataObject::getSchema()->classHasTable($class)) {
* 286:             throw new \InvalidArgumentException('Can\'t add classes which don\'t have data tables
       (no $db or $has_one set on the class)');
  287:         }
  288: 
  289:         $options = array_merge(array(
  290:             'include_children' => true
  291:         ), $options);
  292: 

Trace
=====
SilverStripe\FullTextSearch\Search\Indexes\SearchIndex->addClass(Page)
ElementalSolrIndex.php:20

DNADesign\Elemental\Search\ElementalSolrIndex->init()
SearchIndex.php:80

SilverStripe\FullTextSearch\Search\Indexes\SearchIndex->__construct()

ReflectionClass->newInstance()
InjectionCreator.php:26

SilverStripe\Core\Injector\InjectionCreator->create(DNADesign\Elemental\Search\ElementalSolrIndex, Array)
Injector.php:585

SilverStripe\Core\Injector\Injector->instantiate(Array, DNADesign\Elemental\Search\ElementalSolrIndex, singleton)
Injector.php:988

SilverStripe\Core\Injector\Injector->getNamedService(DNADesign\Elemental\Search\ElementalSolrIndex, 1, Array)
Injector.php:941

SilverStripe\Core\Injector\Injector->get(DNADesign\Elemental\Search\ElementalSolrIndex)
functions.php:34

singleton(DNADesign\Elemental\Search\ElementalSolrIndex)
FullTextSearch.php:76

SilverStripe\FullTextSearch\Search\FullTextSearch::get_indexes()
FullTextSearch.php:85

SilverStripe\FullTextSearch\Search\FullTextSearch::get_indexes(SilverStripe\FullTextSearch\Solr\SolrIndex)
Solr.php:152

SilverStripe\FullTextSearch\Solr\Solr::get_indexes()
Solr_Configure.php:25

SilverStripe\FullTextSearch\Solr\Tasks\Solr_Configure->run(SilverStripe\Control\HTTPRequest)
TaskRunner.php:104

SilverStripe\Dev\TaskRunner->runTask(SilverStripe\Control\HTTPRequest)
RequestHandler.php:319

SilverStripe\Control\RequestHandler->handleAction(SilverStripe\Control\HTTPRequest, runTask)
Controller.php:282

SilverStripe\Control\Controller->handleAction(SilverStripe\Control\HTTPRequest, runTask)
RequestHandler.php:201

SilverStripe\Control\RequestHandler->handleRequest(SilverStripe\Control\HTTPRequest)
Controller.php:207

SilverStripe\Control\Controller->handleRequest(SilverStripe\Control\HTTPRequest)
RequestHandler.php:225

SilverStripe\Control\RequestHandler->handleRequest(SilverStripe\Control\HTTPRequest)
Controller.php:207

SilverStripe\Control\Controller->handleRequest(SilverStripe\Control\HTTPRequest)
Director.php:360

SilverStripe\Control\Director->SilverStripe\Control\{closure}(SilverStripe\Control\HTTPRequest)
VersionedHTTPMiddleware.php:40

SilverStripe\Versioned\VersionedHTTPMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)
HTTPMiddlewareAware.php:62

SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)
AuthenticationMiddleware.php:61

SilverStripe\Security\AuthenticationMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)
HTTPMiddlewareAware.php:62

SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)
CanonicalURLMiddleware.php:155

SilverStripe\Control\Middleware\CanonicalURLMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)
HTTPMiddlewareAware.php:62

SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)
FlushMiddleware.php:26

SilverStripe\Control\Middleware\FlushMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)
HTTPMiddlewareAware.php:62

SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)
RequestProcessor.php:66

SilverStripe\Control\RequestProcessor->process(SilverStripe\Control\HTTPRequest, Closure)
HTTPMiddlewareAware.php:62

SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)
SessionMiddleware.php:20

SilverStripe\Control\Middleware\SessionMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)
HTTPMiddlewareAware.php:62

SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)
AllowedHostsMiddleware.php:60

SilverStripe\Control\Middleware\AllowedHostsMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)
HTTPMiddlewareAware.php:62

SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)
TrustedProxyMiddleware.php:176

SilverStripe\Control\Middleware\TrustedProxyMiddleware->process(SilverStripe\Control\HTTPRequest, Closure)
HTTPMiddlewareAware.php:62

SilverStripe\Control\Director->SilverStripe\Control\Middleware\{closure}(SilverStripe\Control\HTTPRequest)
HTTPMiddlewareAware.php:65

SilverStripe\Control\Director->callMiddleware(SilverStripe\Control\HTTPRequest, Closure)
Director.php:369

SilverStripe\Control\Director->handleRequest(SilverStripe\Control\HTTPRequest)
HTTPApplication.php:48

SilverStripe\Control\HTTPApplication->SilverStripe\Control\{closure}(SilverStripe\Control\HTTPRequest)

call_user_func(Closure, SilverStripe\Control\HTTPRequest)
HTTPApplication.php:66

SilverStripe\Control\HTTPApplication->SilverStripe\Control\{closure}(SilverStripe\Control\HTTPRequest)
HTTPMiddlewareAware.php:65

SilverStripe\Control\HTTPApplication->callMiddleware(SilverStripe\Control\HTTPRequest, Closure)
HTTPApplication.php:67

SilverStripe\Control\HTTPApplication->execute(SilverStripe\Control\HTTPRequest, Closure, )
HTTPApplication.php:49

SilverStripe\Control\HTTPApplication->handle(SilverStripe\Control\HTTPRequest)
cli-script.php:22

This appears to happen because my Page class has empty arrays arrays for $db and $has_one, which is "sanity checked" in for in SearchIndex->addClass(). According to the check, Page has no database fields. For some reason, the check does not consider fields defined in a superclass as being part of the "field set".

My Page.php implementation is the same as the one provided by the default "silverstripe/recipe-cms": "1.0.2@stable" package. All my other CMS page types are subclasses of Page, and I haven't needed to modify the provided/default Page class.

I understand that the ElementalSolrIndex is intended to be more of an "example" - is there any way to stop it being picked up and used by Solr_Configure? It's a useful reference, but I don't actually need to build that index!

The dependency lines from my composer:

"require": {
        "php": ">=5.6.0",
        "silverstripe/recipe-plugin": "^1",
        "silverstripe/recipe-cms": "1.0.2@stable",
        "silverstripe-themes/simple": "~3.2.0",
        "twbs/bootstrap": "4.0.0",
        "dnadesign/silverstripe-elemental": "2.x-dev",
        "axllent/silverstripe-bootstrap-forms": "2.0.2",
        "silverstripe/fulltextsearch-localsolr": "dev-master"
    },

Happy to provide a git repo with test case if it helps.

robbieaverill commented 6 years ago

Can you please show the version of silverstripe/fulltextsearch you're using? I believe we've fixed this in master (reference: https://github.com/silverstripe/silverstripe-fulltextsearch/pull/204) and updating your version to 3.x-dev might fix it.

markhowardnz commented 6 years ago

Looks like it's pulling:

 {
            "name": "silverstripe/fulltextsearch",
            "version": "3.0.0-rc1",
            "source": {
                "type": "git",
                "url": "https://github.com/silverstripe/silverstripe-fulltextsearch.git",
                "reference": "10344580c9905fa3a9ee97c529e877ad1aa58ad2"
            },

Will tweak my composer dependencies to point fulltextsearch to 3.x-dev and report back.

markhowardnz commented 6 years ago

Looks like changing fulltextsearch to 3.x-dev has sorted it.

I've gone explicit and added the following to composer.json:

        "silverstripe/fulltextsearch": "3.x-dev",
        "silverstripe/fulltextsearch-localsolr": "dev-master"

Running vendor/bin/sake dev/tasks/Solr_Configure now produces no errors and I see that ElementalSolrIndex has been successfully created in the solr logs.

robbieaverill commented 6 years ago

Cool. We'll be tagging a new release of fulltextsearch in the coming days. Thanks for reporting!

markhowardnz commented 6 years ago

No worries. Thanks for your extremely fast and helpful response to the issue - It is very much appreciated.