Skip to content
New issue

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

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

Already on GitHub? # to your account

Craft::$app->elementIndexes->saveSettings sources node not working as expected #3484

Closed
jlachancekffein opened this issue Nov 21, 2018 · 7 comments

Comments

@jlachancekffein
Copy link

jlachancekffein commented Nov 21, 2018

Description

I'm working on migrations for create section and fields related to that section. What I want to do is to automatically add that section under a tab in CP panel and show related fields in the listing automatically. (vs showing default fields -> title, date, etc.)

I can add the section under tab without trouble. The problem is the [sources] nodes that is not saved correctly with the saveSettings method. By looking at the source code of the service in the method, this line

$indexedBaseSources = $this->_indexSourcesByKey($baseSources)

cause the problem. By removing this line and the loop after, all works correctly.

I'm not sure to understand the reason why $baseSources are use. It sure that $baseSources will never contain the key section I'm trying to add. Maybe i'm not understand something with the settings...

Steps to reproduce

  1. $elementsIndex = Craft::$app->elementIndexes->getSettings('craft\elements\Entry');
  2. Append new section array after the heading with $elementsIndex['sourceOrder'];
  3. That work correctly if calling Craft::$app->elementIndexes->saveSettings('craft\elements\Entry', $elementsIndex);
  4. $newSources = $elementsIndex['sources'];
  5. Append new data to $newSources array :
    "section:999" => [
       "tableAttributes" => [
           "1":"field:6"
        ]
    ]
    
  6. calling Craft::$app->elementIndexes->saveSettings('craft\elements\Entry', $elementsIndex);
  7. calling again : Craft::$app->elementIndexes->getSettings('craft\elements\Entry');
  8. The node ['sources'] is now empty.

Additional info

  • Craft version: 3.0.26.1
  • PHP version: 7.2
  • Database driver & version: mysql
@brandonkelly
Copy link
Member

Can you post the full PHP code you're using in steps 5 and 6?

@jlachancekffein
Copy link
Author

jlachancekffein commented Nov 21, 2018

Thank you for your reply.

Quick explanation. I loop the $elementsIndex['sources'] array to find the section that I wan't to copy the settings. After that, I happen a new array with the new section key with the same data as the origin section.

$i18nCoreSection = Craft::$app->sections->getSectionByHandle(self::SECTION_I18NCORE_HANDLE);
$i18nCoreSectionKey = 'section:' . $i18nCoreSection->id;
$i18nCoreSectionSourceData = null;

// The new section ID
$sectionKey = 'section:' . $this->_newSectionModel->id;

// Get sources datas
$newSources = $elementsIndex['sources'];

// Find i18n_core_module info
foreach ($newSources as $key => $source) {
   if ($key === $i18nCoreSectionKey) {
      $i18nCoreSectionSourceData = $source;
            break;
       }
}

// Append new section source data to all section data
$elementsIndex['sources'][$sectionKey] = $i18nCoreSectionSourceData;

// Save the element Index
return Craft::$app->getElementIndexes()->saveSettings('craft\elements\Entry', $elementsIndex);

@brandonkelly
Copy link
Member

brandonkelly commented Nov 21, 2018

Looks right to me. Try adding this right before that last line:

Craft::dd($elementsIndex);

To verify that the data all looks correct. There should be a reference to the section in the sourceOrder key as well.

@jlachancekffein
Copy link
Author

jlachancekffein commented Nov 21, 2018

Here is the dump. Sorry for dirty dump, i'm dumping with the ./craft command :

array(2) {
  ["sourceOrder"]=>
  array(4) {
    [0]=>
    array(2) {
      [0]=>
      string(3) "key"
      [1]=>
      string(1) "*"
    }
    [1]=>
    array(2) {
      [0]=>
      string(7) "heading"
      [1]=>
      string(4) "I18n"
    }
    [2]=>
    array(2) {
      [0]=>
      string(3) "key"
      [1]=>
      string(9) "section:1"
    }
    [3]=>
    array(2) {
      [0]=>
      string(3) "key"
      [1]=>
      string(11) "section:203"
    }
  }
  ["sources"]=>
  array(2) {
    ["section:1"]=>
    array(1) {
      ["tableAttributes"]=>
      array(3) {
        [1]=>
        string(7) "field:6"
        [2]=>
        string(7) "field:7"
        [3]=>
        string(7) "field:8"
      }
    }
    ["section:203"]=>
    array(1) {
      ["tableAttributes"]=>
      array(3) {
        [1]=>
        string(7) "field:6"
        [2]=>
        string(7) "field:7"
        [3]=>
        string(7) "field:8"
      }
    }
  }
}

@brandonkelly
Copy link
Member

OK, and does the output of Craft::$app->elementIndexes->getSettings(\craft\elements\Entry::class); look right if you call it immediately after calling saveSettings() ?

@jlachancekffein
Copy link
Author

jlachancekffein commented Nov 22, 2018

// The dump is the same as the previous message
var_dump($elementsIndex);

// After saveSettings, the sources node is now empty
// ["sources"]=> array(0) {}
Craft::$app->getElementIndexes()->saveSettings('craft\elements\Entry', $elementsIndex);
var_dump(Craft::$app->elementIndexes->getSettings(\craft\elements\Entry::class));
die;

To debug the problem, i look into /vendor/craftcms/cms/src/services/ElementIndexes.php. The problem seem to been related with this method : line: 117

// Prune out any settings for sources that don't exist
$indexedBaseSources = $this->_indexSourcesByKey($baseSources);

Here is the dump of $baseSources :

array(1) {
  [0]=>
  array(4) {
    ["key"]=>
    string(1) "*"
    ["label"]=>
    string(11) "All entries"
    ["criteria"]=>
    array(2) {
      ["sectionId"]=>
      array(0) {
      }
      ["editable"]=>
      bool(true)
    }
    ["defaultSort"]=>
    array(2) {
      [0]=>
      string(8) "postDate"
      [1]=>
      string(4) "desc"
    }
  }
}

Like I said, the problem is that $baseSources not contains the existing sections + the new one. So it it unset by the loop just after that.

I don't know if the problem is cause by running the migration via the craft console vs normal http request ?

The only way to make it work is to comment this method. But it's not a solution because I have to change the craft core and this will be overriden by composer update.

@brandonkelly
Copy link
Member

OK I see what’s happening here. craft\services\Sections::getAllSections() wasn’t returning your newly-added section because saveSection() wasn’t clearing caches as it should have. Which is why craft\services\ElementIndexes::saveSettings() was pruning out your new section. As far as it could tell, that section key didn’t really exist.

Fixed for the next release.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants