Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[STU-52] TypeError with getSiteById() on multi-site #276

Closed
ten1seven opened this issue Oct 10, 2023 · 2 comments
Closed

[STU-52] TypeError with getSiteById() on multi-site #276

ten1seven opened this issue Oct 10, 2023 · 2 comments
Assignees
Labels
⚙️ CP Control Panel/Administration related linear Created by Linear-GitHub Sync Medium priority scout

Comments

@ten1seven
Copy link

ten1seven commented Oct 10, 2023

I recently discovered this TypeError when trying to visit the /scout-indices page:

craft\services\Sites::getSiteById(): Argument #1 ($siteId) must be of type int, array given, called in /var/www/html/vendor/studioespresso/craft-scout/src/utilities/ScoutUtility.php on line 37

PHP: 8.1.22
Craft: 4.4.17 (recently upgraded from Craft 3)
Scout: 3.2.1
Running multi-site

I found that if I manually change line 37 in ScoutUtility.php to the ID of the primary site (1) the page loads correctly. What other information would be helpful for debugging?

'site' => $engine->scoutIndex->criteria->siteId === '*' ? 'all' : Craft::$app->getSites()->getSiteById($engine->scoutIndex->criteria->siteId)

to 

'site' => $engine->scoutIndex->criteria->siteId === '*' ? 'all' : Craft::$app->getSites()->getSiteById(1)

(full Yii error report for reference)
Screen Shot 2023-10-10 at 07 27 45-fullpage

STU-52

@janhenckens
Copy link
Member

@ten1seven Could you share the configuration you have in scout.php? Either way it's something to fix but your specific config would provide a good case to test against. Thanks!

@janhenckens janhenckens self-assigned this Oct 10, 2023
@janhenckens janhenckens added the ⚙️ CP Control Panel/Administration related label Oct 10, 2023
@ten1seven
Copy link
Author

Sure!

scout.php

<?php

use modules\hrc\web\services\Search;

return [
    /*
     * Scout listens to numerous Element events to keep them updated in
     * their respective indices. You can disable these and update
     * your indices manually using the commands.
     */
    'sync' => true,

    /*
     *
     * @depcretio
     * By default Scout handles all indexing in a queued job, you can disable
     * this so the indices are updated as soon as the elements are updated
     *
     * Disabling the `queue` option will no longer be supported in the next version of Scout
     *
     */
    'queue' => true,

    /*
     * The connection timeout (in seconds), increase this only if necessary
     */
    'connect_timeout' => 1,

    /*
     * The batch size Scout uses when importing a large amount of elements
     */
    'batch_size' => 1000,

    /*
     * By default Scout will index elements related to the element being save (that are in the same index).
     * Disabling this can improve performance on larger sites that have lots of relations.
     */
    'indexRelations' => true,

    /*
     * The Algolia Application ID, this id can be found in your Algolia Account
     * https://www.algolia.com/api-keys. This id is used to update records.
     */
    'application_id' => '$ALGOLIA_APPLICATION_ID',

    /*
     * The Algolia Admin API key, this key can be found in your Algolia Account
     * https://www.algolia.com/api-keys. This key is used to update records.
     */
    'admin_api_key' => '$ALGOLIA_ADMIN_API_KEY',

    /*
     * The Algolia search API key, this key can be found in your Algolia Account
     * https://www.algolia.com/api-keys. This search key is not used in Scout
     * but can be used through the Scout variable in your template files.
     */
    'search_api_key' => '$ALGOLIA_SEARCH_API_KEY',

    /*
     * A collection of indices that Scout should sync to, these can be configured
     * by using the \rias\scout\ScoutIndex::create('IndexName') command. Each
     * index should define an ElementType, criteria and a transformer.
     */
    'indices' => Search::getIndices(),
];

modules\hrc\web\services\Search.php

<?php

namespace modules\hrc\web\services;

use craft\elements\db\EntryQuery;
use craft\elements\Entry;
use Exception;
use modules\hrc\web\models\SearchTransformer;
use modules\hrc\web\models\SearchTransformerEvents;
use modules\hrc\web\models\SearchTransformerNewsPress;
use rias\scout\IndexSettings;
use rias\scout\ScoutIndex;


class Search
{
    public const SECTION_NEWS = 'news';
    public const SECTION_PRESS_RELEASES = 'pressReleases';
    public const SECTION_RESOURCES = 'resources';
    public const SECTION_EVENTS = 'events';
    public const SECTION_PAGES = 'pages';
    public const SECTION_CAMPAIGNS = 'campaigns';
    public const SECTION_STORIES = 'stories';
    public const SECTION_EQUALITY_INDEXES = 'equalityIndexes';
    public const SECTION_DATA_EXPLORERS = 'dataExplorers';
    public const SECTION_STAFF = 'staff';
    public const SECTION_RESOURCE_TOPICS = 'resourceTopics';
    public const SECTION_MAGAZINE_ARTICLES = 'magazineArticles';

    public const SECTION_FOUNDATION_PAGES = 'foundationPages';
    public const SECTION_FOUNDATION_PROGRAMS = 'programs';
    public const SECTION_FOUNDATION_PROFESSIONAL_RESOURCES = 'professionalResources';

    /**
     * Creates an index name based on the current CRAFT_ENVIRONMENT
     *
     * @param string $name
     * @return string
     */
    public static function getIndexName(string $name): string
    {
        return implode('_', [
            CRAFT_ENVIRONMENT,
            $name,
        ]);
    }

    /**
     * Configure the Scout indices and data for Algolia
     *
     * @return array
     * @throws Exception
     */
    public static function getIndices(): array
    {
        $indices = [];

        $siteSearchConfig = self::_getSiteSearchConfig();

        $hrcIndex = self::getIndexName('hrcSearch');
        $indices[] = ScoutIndex::create($hrcIndex)
            ->elementType(Entry::class)
            ->criteria(function (EntryQuery $query) use ($siteSearchConfig) {
                return $query->section([
                    array_keys($siteSearchConfig)
                ])
                    ->site([
                        'hrc',
                        'hrcES'
                    ]);
            })
            ->transformer(function (Entry $entry) use ($siteSearchConfig) {
                return self::_getTransformer($siteSearchConfig, $entry);
            })
            ->splitElementsOn([
                'content',
            ])
            ->indexSettings(IndexSettings::create()
                ->hitsPerPage(10)
                ->attributeForDistinct('distinctID')
                ->distinct(true)
                ->attributesForFaceting([
                    'distinctID',
                    'type',
                    'topics',
                    'locations',
                    'year',
                ])
                ->replicas([
                    $hrcIndex . '_dateAsc',
                    $hrcIndex . '_dateDesc',
                    $hrcIndex . '_popularity',
                ])
            );

        $foundationSearchConfig = self::_getFoundationSearchConfig();

        $hrcFoundationIndex = self::getIndexName('hrcFoundationSearch');
        $indices[] = ScoutIndex::create($hrcFoundationIndex)
            ->elementType(Entry::class)
            ->criteria(function (EntryQuery $query) use ($foundationSearchConfig) {
                return $query->section(
                    array_keys($foundationSearchConfig)
                )
                    ->site([
                        'hrcFoundation',
                    ]);
            })
            ->transformer(function (Entry $entry) use ($foundationSearchConfig) {
                return self::_getTransformer($foundationSearchConfig, $entry);
            })
            ->splitElementsOn([
                'content',
            ])
            ->indexSettings(IndexSettings::create()
                ->hitsPerPage(10)
                ->attributeForDistinct('distinctID')
                ->distinct(true)
                ->attributesForFaceting([
                    'distinctID',
                    'type',
                    'topics',
                    'locations',
                    'year',
                ])
                ->replicas([
                    $hrcFoundationIndex . '_dateAsc',
                    $hrcFoundationIndex . '_dateDesc',
                ])
            );

        return $indices;
    }


    /**
     * @param array $config
     * @param Entry $entry
     * @return array
     * @throws Exception
     */
    private static function _getTransformer(array $config, Entry $entry): array
    {
        $transformer = $config[$entry->section->handle];

        if ($transformer instanceof SearchTransformer === false) {
            throw new Exception('Transformer config must be of type SearchTransformer');
        }

        return $transformer->getEntryData($entry);
    }

    private static function _getSiteSearchConfig(): array
    {
        return [
            self::SECTION_NEWS => new SearchTransformerNewsPress([
                'type' => 'News',
                'topicFieldHandle' => 'newsTopics',
                'useTopicFacet' => true,
                'useLocationFacet' => true,
                'useYearFacet' => true,
            ]),
            self::SECTION_PRESS_RELEASES => new SearchTransformerNewsPress([
                'type' => 'Press Releases',
                'topicFieldHandle' => 'newsTopics',
                'useTopicFacet' => true,
                'useLocationFacet' => true,
                'useYearFacet' => true,
            ]),
            self::SECTION_RESOURCES => new SearchTransformer([
                'type' => 'Resources',
                'topicFieldHandle' => 'resourceTopics',
                'useTopicFacet' => true,
            ]),
            self::SECTION_EVENTS => new SearchTransformerEvents([
                'type' => 'Events',
                'useLocationFacet' => true,
                'useYearFacet' => true,
            ]),
            self::SECTION_CAMPAIGNS => new SearchTransformer([
                'type' => 'Campaigns',
                'useYearFacet' => true,
            ]),
            self::SECTION_STORIES => new SearchTransformer([
                'type' => 'Campaigns',
                'useYearFacet' => true,
            ]),
            self::SECTION_MAGAZINE_ARTICLES => new SearchTransformer([
                'type' => 'Magazine',
                'useYearFacet' => true,
            ]),
            self::SECTION_EQUALITY_INDEXES => new SearchTransformer([
                'eyebrow' => 'Equality Index'
            ]),
            self::SECTION_DATA_EXPLORERS => new SearchTransformer(),
            self::SECTION_STAFF => new SearchTransformer(),
            self::SECTION_RESOURCE_TOPICS => new SearchTransformer(),
            self::SECTION_PAGES => new SearchTransformer(),
        ];
    }

    private static function _getFoundationSearchConfig(): array
    {
        return [
            self::SECTION_FOUNDATION_PAGES => new SearchTransformer([
                'type' => 'Pages',
            ]),
            self::SECTION_FOUNDATION_PROGRAMS => new SearchTransformer([
                'type' => 'Programs',
            ]),
            self::SECTION_FOUNDATION_PROFESSIONAL_RESOURCES => new SearchTransformer([
                'topicFieldHandle' => 'professionalAudiences',
                'type' => 'Professional Resources',
            ]),
        ];
    }
}

@janhenckens janhenckens added the linear Created by Linear-GitHub Sync label Oct 10, 2023
@janhenckens janhenckens changed the title TypeError with getSiteById() on multi-site [STU-52] TypeError with getSiteById() on multi-site Oct 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
⚙️ CP Control Panel/Administration related linear Created by Linear-GitHub Sync Medium priority scout
Projects
None yet
Development

No branches or pull requests

2 participants