Problem/Motivation
A created translatable content type added to the install config of a module or an install profile results in SQL error "Unknown column 'content_translation_source' in 'field list'" when attempting to add new content of that type.
Steps to replicate:
1. Create a content type with 'Enable translations' checked
2. Export content type as a feature
3. Add feature to install profile's info.yml dependencies along with language and content_translation modules
4. Install site profile
5. Log in, Add content of this type, Save
Error returned:
The website encountered an unexpected error. Please try again later.
Drupal\Core\Entity\EntityStorageException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'content_translation_source' in 'field list': INSERT INTO {node_field_data} (nid, vid, type, langcode, title, uid, status, created, changed, promote, sticky, revision_translation_affected, default_langcode, content_translation_source, content_translation_outdated) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6, :db_insert_placeholder_7, :db_insert_placeholder_8, :db_insert_placeholder_9, :db_insert_placeholder_10, :db_insert_placeholder_11, :db_insert_placeholder_12, :db_insert_placeholder_13, :db_insert_placeholder_14); Array ( [:db_insert_placeholder_0] => 2 [:db_insert_placeholder_1] => 2 [:db_insert_placeholder_2] => page [:db_insert_placeholder_3] => en [:db_insert_placeholder_4] => asdf [:db_insert_placeholder_5] => 1 [:db_insert_placeholder_6] => 0 [:db_insert_placeholder_7] => 1445445894 [:db_insert_placeholder_8] => 1445445901 [:db_insert_placeholder_9] => 0 [:db_insert_placeholder_10] => 0 [:db_insert_placeholder_11] => 1 [:db_insert_placeholder_12] => 1 [:db_insert_placeholder_13] => und [:db_insert_placeholder_14] => 0 ) in Drupal\Core\Entity\Sql\SqlContentEntityStorage->save() (line 757 of core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php).
Proposed resolution
Instead of manually creating/updating the content translation fields in a number of places (UI/Migration/Config Import) react to saving of the Content Language Settings config entity directly in content_translation.module
. This both allows removing/consolidating code as well as covers the previously missing case of installation of module/profile config.
Comment | File | Size | Author |
---|---|---|---|
#140 | 2599228-139-interdiff.txt | 1.15 KB | Berdir |
#140 | 2599228-139.patch | 21.15 KB | Berdir |
#136 | 2599228-128-135--interdiff.txt | 1.34 KB | tstoeckler |
#135 | 2599228-135.patch | 21.15 KB | tstoeckler |
#105 | 2599228-104-8.6.x.patch | 18.75 KB | GoZ |
Comments
Comment #2
polynya CreditAttribution: polynya as a volunteer commentedI have the same issue. The workaround is to go to
admin/config/regional/content-language
and click 'Save configuration'. This adds two columns, content_translation_source and content_translation_outdated, to the table node_field_data.Comment #3
vbouchetI noticed the exact same behavior. The workaround works.
Comment #4
andypostGot this issue, there's no way to ship
language.content_settings.taxonomy_term.navigation.yml
to enable translation of vocabularyComment #5
andypostSuppose config import event should fire table rebuild
Comment #7
agoradesign CreditAttribution: agoradesign commentedThat's one of these annoying little bugs, that only concerns developers and site builders, but in that case it's really annoying. This would surely be an easy fix. Does anyone have some time to isolate the bug in a test case?
Comment #8
BlacKICEUAMy 'solution' for this issue: after enable my custom module, run drupal update:entities in command promt (console). After that the missing fields are created in the database.
Comment #9
Ismail Cherri CreditAttribution: Ismail Cherri as a volunteer commentedHi,
For those coming to this issue looking for a code solution, create module.install file and add this to the hook_install():
Where MODULE should be replaced by your module name.
Hope this helps...
Comment #10
Ismail Cherri CreditAttribution: Ismail Cherri as a volunteer commentedComment #11
mpp CreditAttribution: mpp at AmeXio commentedBoth #8 and #9 prevent the error from occurring.
Comment #13
tstoecklerHit this as well, this seems to be working for me.
Comment #14
hchonovI think @see should contain the whole path to the method - inclusive the namespace of the class ?
This is a code duplication in both hooks - we should create a helper method instead.
Comment #15
tstoecklerRe #14:
1. I don't feel strongly about this, but since we're not allowed to do /** */-style comments in core anyway, you won't be able to click this in your IDE anyway, so I don't think there's much value to using the namespace.
2. Where would you propose to add such a method? And with which parameters?
Comment #16
tstoecklerThis fixes #14.1.
I also realized that since we are now hooking into the regular entity save process I think we no longer need to custom event subscriber for migration and config import. Both of those subsystems go through
$entity->save()
so we should be fine. Both of those things are tested, so let's see if anything blows up.This is the minimal change for now, I left the actual methods and everything in place, not sure how far we want to go in 8.2. That's also why I didn't implement 2. yet. The event subscribers are the only other usages of
ContentTranslationUpdateManager::updateDefinitions()
so with this we could deprecate that and provide a similar method with a different signature that is more easily used from the entity hooks á la #14.2. However, I am - again - not sure how far we actually can go with that in 8.2, so not doing any of that yet.Comment #17
hchonovI would put the new function into content_translation.module.
What about
content_translation_update_entity_type_definition($entity_type_id);
?Comment #19
tstoecklerOk, implementing
EventSubscriberInterface
and returningNULL
ingetSubscribedEvents()
really wasn't that smart... Let's see. Still leaving the actual subscribers around for BC. We can discuss that more once this is green...Comment #21
tstoecklerNot my day today.
Comment #22
tstoecklerOK, will try to find some time to write dedicated tests for this, but in the meantime tagging Needs release manager review so I know how we can proceed.
Here's the quick run-down of this issue in regards to release management
ContentTranslationUpdatesManager::applyUpdates()
)hook_entity_insert/update()
) so that all three current usages are obsolete. The usages are:ContentTranslationManager::setEnabled()
which in turn is only called from the UI and in tests. The behavior of calling::setEnabled()
does not change with this patch as the entity is saved and the new hook implementations are, thus, called.ContentTranslationUpdatesManager::onConfigImporterImport()
. This is obsolete with the patch as config import calls::save()
on config entities alreadyContentTranslationUpdatesManager::onMigrateImport()
). This is obsolete with the patch as migrations call::save()
on config entities already.Removing the
::updateDefinitions()
call fromContentTranslationManager::setEnabled()
is uncontroversial because it is neither an API nor a behavior change. For the event subscribers we can take a number of different routes to clean this up, now that they are obsolete. I'm not sure which are allowed (ordered by by ascending invasiveness and ascending cleanliness):getSubscribedEvents()
so that the methods are no longer calledgetSubscribedEvents()
,implements EventSubscriberInterface
and theevent_subscriber
tag from the serviceSince the newly introduced hooks are now the only usages of
ContentTranslationsUpdateManager::updateDefinitions()
we could consider renaming it and or changing its signature assuming that it's not considered an API function. Instead of::updateDefinitions(array $entity_type)
we could have::installFieldStorageDefinitions(string $entity_type_id)
or similar. That would allow nicely fixing the issue brought up in #14.4 which we could otherwise fix not so nicely by simply introducing a helper function.Comment #23
tstoecklerChatted with @catch in IRC and cleared up the path to go which I implemented now. There is slightly more duplication between the two hooks which @hchonov will not be happy about, but apart from @catch signing off on that the diff stat of the patch is still
55 insertions(+), 124 deletions(-)
, so I think that's acceptable. (That will of course change negatively with added test coverage, but still.)Note that the interdiff does not contain the deletion of
ContentTranslationUpdatesManager
because PhpStorm tried to be smart with the deletion.Still needs tests and needs an issue summary update for the proposed resolution.
Comment #25
tstoecklerSo one thing I did not mention is that
ContentTranslationUpdatesManager::updateDefinitions()
contained a check forEntityDefinitionUpdateManager::needsUpdates()
which seemes unnecessary to me, because we already check explicitly if field storage definitions are missing. That internally, though, reset's the static field storage definition cache by callingEntityFieldManager::useCaches(FALSE)
. Making this more explicit now.Comment #27
tstoecklerOK, this should be green.
Currently the tests that migrate the language settings (with Content Translation on) don't have the node schema installed. I was wondering how the tests pass currently and I found out that - while
updateDefinitions()
does get called correctly - the Content Translation fields are never installed due to some race condition in caching. So the fact that we have to modify those tests for this to pass is in fact a deficiency in those tests themselves.We can always add more assertions or improve the tests in other ways, but that's not in scope for this issue.
Comment #29
vegantriathleteI'd like to add a bit more information to this just to ensure the fix is complete, as I think I've found a related situation.
I have a content type that I'm defining in a custom module. I've got my_module/config/optional/language.content_settings.node.my_module.yml which contains
When I run my Functional test and create pieces of content I get the same error about the unknown column.
If I create a my_module.install that contains the my_module_install as suggested in #9 the error goes away.
Comment #30
dxvargas CreditAttribution: dxvargas commentedThis error happens only in some circumstances.
Right now I had this error after a git pull/drush fia. Patch #27 didn't fix the problem.
When I install everything from scratch, it happens without the patch #27, it does not happen if previously I apply #27.
This always fixes the problem:
$ drush entity-updates
About the patch, it works. Once it's there since the beginning the problem won't happen.
Comment #31
hchonovRe-roll only.
Comment #32
andypostremoval of service does not fits into BC
Comment #34
pektinasen CreditAttribution: pektinasen commentedhad the same issue when installing the site via config_install.
Just wanted to say thanks and the patch in #31 works for me.
Comment #35
Pasqualle#31 works for me also. Using it with a multilingual install profile, with content translation and various entity translations enabled.
Comment #36
slydevil CreditAttribution: slydevil commentedLooks good to me. Applied the patch cleanly and the error is gone.
Comment #37
catch@andypost #32 the service being removed is only an event subscriber, so it should be OK for bc.
Uploading a test-only patch since there isn't one here.
Comment #38
catchI don' think the test-only patch is testing anything other than the entity schema update, we should add an explicit test for the content creation (also uploading a patch with only the test changes this time).
Also the event subscriber being removed is injected into one class and used as an API, so there's an argument it's not just an event subscriber and we should deprecate it.
Comment #39
catchComment #41
sgurlt CreditAttribution: sgurlt commentedSame here, D8.4.x. heavy installation with multiple translatable entity types and 4 active languages.
After installation with "drush site-install --config-dir="../config"" I ran in the same error while creating new contents.
#31 solved it, thanks ! :)
Comment #42
TunprogI faced the same issue when importing page manager config using Drupal version 8.3.9 and #31 solved it for me thanks a lot.
Comment #43
nonAlgebraic CreditAttribution: nonAlgebraic commentedFor anyone who, like me, has been having trouble applying both this patch and the one from 2868294, here's a reroll that addresses the bugs raised in that issue.
Comment #44
tstoecklerHere's a patch that deprecates instead of removes
ContentTranslationUpdateManager
per #38.We still need to add a dedicated test for this per #38.
Also added a change notice (just created the node for now to get a nid for the patch, will fill with some text in a second).
Comment #45
tstoecklerWhen writing the change notice, I looked around the code again and realized that this leaves around some obsolete migration code.
Comment #47
tstoecklerAhh, too much copy-paste with the deprecation notices. Let's see.
Comment #49
tstoecklerFixed PHPCS errors. Sorry about that.
Comment #50
tstoecklerUpdated the issue summary
Comment #51
tstoeckler...and here's a dedicated test for the behavior. The tests-only patch is also the interdiff. We currently don't have a translatable test entity type with bundles, so I chose to make
entity_test_with_bundle
translatable rather than adding a whole new type.Comment #52
dxvargas CreditAttribution: dxvargas commentedI've tested 2599228-51.patch in #51. It fixes the problem.
Code and tests are satisfactory. Marking as RTBC.
Comment #53
nkoporecSame error here. I'm using a profile and was trying to import view config but the kernel test were failing. Applied the patch and it's working now. Thank you!
Comment #55
dwkitchen CreditAttribution: dwkitchen at Johnson & Johnson commentedI have also tested Patch 51 and working.
Comment #56
ieguskiza CreditAttribution: ieguskiza at European Commission and European Union Institutions, Agencies and Bodies commentedJust adding another +1 to the patch on #51. Tested on 8.7 and working properly.
Comment #58
vdacosta@voidtek.com CreditAttribution: vdacosta@voidtek.com as a volunteer commentedRollup the patch
Comment #59
tstoecklerUnless I'm missing something, the hunk in
core/modules/content_translation/migrations/d7_node_translation.yml
is missing from the patch.Comment #60
kmbremnerPatch on #58 applied cleanly on 8.5.6 for me, and fixed issue importing view config.
Comment #61
tstoecklerAlright, here's a re-roll.
git rebase
was nice enough to do the work for me. However, since #2073467: Migrate Drupal 7 Entity Translation settings to Drupal 8 there's another hunk we can remove. Going back to RTBC per #52.Comment #62
psf_ CreditAttribution: psf_ at SDOS commentedWe are developing a custom profile that enter in this error when call to:
If we call that after install modules in a bath process, it stop with:
but can continue if reload the page.
If we put the update at the end of install, in
hook_after_install_finished()
it stop too, but can't continue. The trace is:I changed the issue status to "Need work", please, If my use case is out of the scope of this issue then change status again.
Comment #63
psf_ CreditAttribution: psf_ at SDOS commentedIf I remove all entity updates in profile, and then call
drush entity-updates
I get the same error:Comment #64
tstoecklerHmm... calling
EntityDefinitionUpdateManager::applyUpdates()
(or the equivalentdrush entity-updates
) is really not supported outside of development, so #62 and #63 do not necessarily mean that something is wrong with the patch. I guess you have hit the situation caused by the bug, that Drupal thinks the field is installed, but it never actually created the respective database tables. You should be able to rectify this by manually disabling content translation for all node types, and then manually re-enabling it again afterwards.If you do not want to do it manually you could try to write an update hook that uninstalls the field storage definition using
EntityDefinitionUpdateManager::uninstallFieldStorageDefinition()
and then re-installs it (with the corresponding method) afterwards. That should also work.Let me know if that worked.
Comment #65
psf_ CreditAttribution: psf_ at SDOS commentedWithout the patch, if I disable translations in
admin/config/regional/content-language
and re-enable it again manually the problem persist:With the patch in #61, and manually disable and re-enable, I have the same problem:
:(
Comment #66
tstoecklerThanks @psf_ for testing that! That's unfortunate that it didn't work. I will try to reproduce the error and then see if I can manage to get back out of it. I still think the patch itself may be fine, but I still think we should have this figured this out before the patch gets in.
Comment #67
psf_ CreditAttribution: psf_ at SDOS commentedThanks, I see extrange that the definition is ok but the database it is not update too.
Comment #68
tim.plunkett@Berdir pointed me here via #2994398: Not properly clearing EntityFieldManager's fieldMap leads to fatals, often after migration or bundle creation.
From my testing, that issue solves this problem completely.
Running the test from this issue (without the other changes) but with the fix from that issue, everything passes.
So I'm postponing this one for now.
Comment #69
eiriksmJust for the record, here is a script that fixes it for me. In case this can help anyone:
Then I run entity updates.
Comment #70
johan.s CreditAttribution: johan.s as a volunteer commentedHello,
I've made some changes on this patch because, it is not really applied on the Drupal's version 8.6.x, and now, it's working fine.
Comment #71
tim.plunkettHere's this patch before and after rebasing now that #2994398: Not properly clearing EntityFieldManager's fieldMap leads to fatals, often after migration or bundle creation is in.
So while this test seems like good addition, this indicates there is no longer a bug here.
If there are still additional problems not resolved by the above issue, then this needs new tests.
Comment #72
tstoecklerLooked into this. Both the patch and test are fine, as far as I can tell, but it looks like #2994398: Not properly clearing EntityFieldManager's fieldMap leads to fatals, often after migration or bundle creation exposed a separate bug. Previously the test would fail because the field
content_translation_source
was unknown, because the list of field storage definitions was still cached. Now that that's being cleared, what should happen is that the test should fail because it tries to save a record to thecontent_translation_source
column which doesn't exist. The column does not, in fact, exist in the test. The reason that the test still passes is that - even though the field storage definitions inEntityFieldManager
are now rebuilt correctly, the storage handler itself still holds a reference to aDefaultTableMapping
object with the old storage definitions. So when saving the entity and building the database record to save inSqlContentEntityStorage::mapToStorageRecord()
,$table_mapping->getFieldNames($data_table)
will never contain the new field names.So attached is a hacked together interdiff to make the test fail by rebuilding the table mapping when a bundle is created (or deleted). Because re-initializing the table mapping requires fetching the field storage definitions from
EntityFieldManager
I also needed to twist the order of the cache clearing. This should be fixed in a separate issue, though. Attaching here for now, though, in case someone wants to tinker with this.I think we can still go ahead here independently of that, though, by simply extending the test. Since the translation metadata is never persisted to the database, we can trigger a test fail simply by asserting that the correct values are returned after saving and re-loading. So attached is a patch for that, that should fail. I didn't rebase the patch that includes the actual fix yet.
Comment #74
tstoecklerOpened #3002138: Table mapping is not re-initialized after bundles are created/deleted for #72 and rebased patch. This already includes the interdiff from #72, so should be RTBC-able as it was already reviewed above, but would be good to get some confirmation here that my thinking on #72 is accurate, so going to "needs review" for now.
Comment #75
mpp CreditAttribution: mpp at AmeXio commentedI encountered the same error after trying to install a site from config and the config contains a view with a dependency to a non-existing (content) term:
The error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'content_translation_source' in 'field list': INSERT INTO {taxonomy_term_field_data} (tid, vid, langcode, status, name, description__value, description__format, weight, changed, default_langcode, content_translation_source, content_translation_outdated, content_translation_uid, content_translation_created) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6, :db_insert_placeholder_7, :db_insert_placeholder_8, :db_insert_placeholder_9, :db_insert_placeholder_10, :db_insert_placeholder_11, :db_insert_placeholder_12, :db_insert_placeholder_13);
I tried fixing it with a hook_install() that creates the term with that specific uuid.
Comment #76
mpp CreditAttribution: mpp at AmeXio commentedNot sure what just happened but I did not mean to set this issue to needs rework nor did I want to re-add the label needs followup. Restoring both.
Comment #77
johan.s CreditAttribution: johan.s commentedPatch for work with this issue :
https://www.drupal.org/project/drupal/issues/2868294#comment-12645399
Comment #79
Shyghar CreditAttribution: Shyghar commentedHow can I runnapudate if in the update.php page I have this alert "No pending updates."
Comment #80
Shyghar CreditAttribution: Shyghar commentedHow can I runnapudate if in the update.php page I have this alert "No pending updates."?
Comment #81
poornachandran CreditAttribution: poornachandran as a volunteer and at Capgemini commentedI have re-created the patch to support Drupal 8.6.1 version.
Comment #82
poornachandran CreditAttribution: poornachandran as a volunteer and at Capgemini commentedComment #83
poornachandran CreditAttribution: poornachandran as a volunteer and at Capgemini commentedI have updated the patch for the version 8.6.1
Comment #84
nkoporecTested the #83 patch and it worked for me on 8.6.1. Setting this as Needs Review so other people can test it out.
Comment #85
poornachandran CreditAttribution: poornachandran as a volunteer and at Capgemini commentedThanks @nkoporec .
Comment #86
tstoecklerRe @psf_ and @Poornachandran: I have just tested the following:
content_translation_test
module so that I had a translatable entity bundle but not the database columns such ascontent_translation_source
(which is what this bug report is for)/admin/config/regional/content-language
and pressed Save configurationcontent_translation_source
were properly created in theentity_test_with_bundle_field_data
table.drush entity-updates
but there were no remaining updates.So as far as I can tell this patch solves both the original bug, but also allows people to recover a broken site by disabling and re-enabling the translatability of each bundle. If that's not the case for anyone please provide additional details.
Otherwise someone maybe can RTBC this one. ;-) Re-uploading the latest patch for 8.7.x for that purpose.
Comment #88
tstoecklerComment #89
BerdirLooks good to me. This also fixed a problem in my project where I have complex kernel tests that install a whole bunch of modules including content_moderation and those tests are failing on inconsistencies in field definitions when rebuilding views data.
Just wondering about whether we also need to take care of *uninstalling* those fields in case content moderation is disabled again? If this has been discussed before, just point me to the comment :)
Comment #90
tstoecklerRe #89:
s/content_moderation/content_translation/
?content_translation
module, all fields will be removed again byModuleInstaller::uninstall()
content_translation_entity_base_field_info()
:Does that answer your question?
Comment #91
BerdirYes, 2. is exactly what I was asking about, thanks.
Looks good then!
Comment #92
joey-santiago CreditAttribution: joey-santiago commentedHello,
tested the patch https://www.drupal.org/files/issues/2018-10-01/2599228-SQL_error_on_cont... against core at version 8.6.2. Unfortunately it doesn't work for me as somehow when content_translation_language_content_settings_update runs $installed_storage_definitions end up being exactly the same as the ones in $storage_definitions. Can't say yet where the problem is, but this is the field_data table i end up having for my custom entity:
so seems i am missing the columns content_translation_source and content_translation_outdated? or is there anything more i should i guess add manually with a hook update?
thanks for helping me out with this :)
edit: actually, when reading better at the error, the fields content_translation_uid, content_translation_status, content_translation_created, content_translation_changed are also missing, so, well... a lot of adds to be done!
edit again: disabling and re-enabling the custom module and then resaving the form at "admin/config/regional/content-language" fixed the issue. Leaving the comment here to add the suggestion then... if you still have problems, try to disable your custom entity module and redo the thing :)
Comment #93
neetu morwani CreditAttribution: neetu morwani as a volunteer and commentedRe-roll only patch for 31st comment . This is compatible with latest 8.6.x branch.
Thanks
Comment #95
borisson_Looks like this also fixes #2868294: Call to a member function getThirdPartySetting() on null in ContentTranslationManager. The latest patch has php errors, so should not be used.
Comment #96
vacho CreditAttribution: vacho at Skilld commentedSolved problem with duplicated methods in .module that causes that PHPLint failed.
Comment #97
andypostPatches in #93 and #96 are smaller in 5k comparing to #86
Comment #98
tstoecklerRe-uploading the RTBC patch.
Comment #100
tstoecklerHere's the properly-rerolled patch now that #3008740: ContentTranslationManager::setEnabled no longer clears the bundle info cache when changing a bundle's translation setting. already introduced the insert and update hooks for language content settings. I didn't look at the failures in #93 so I ignored #96 which fixed those - because my patch from ##86 still applied. That was ignorant of me, I'm sorry for that. Those patches did miss the additions to the
content_translation_test
module, though. Also #96 incorrectly removed the (now) pre-exixting hooks which caused the test failures. So theoretically this one should again be green, and - but for the rebase - is identical to #86, so I'm marking this RTBC again.Comment #101
alexpottThis code looks to be exactly the same. I wonder if for now we should add an _SOME_NAME_METHOD() to the module file as a bug in one is likely to be a bug in the other.
Also in the original code that does this has an @todo to https://www.drupal.org/node/2346013 which for me is still relevant.
Comment #102
tstoecklerGood point, that's a great idea to introduce a common function. Since the common logic only depends on the entity type ID I used that as an argument so that the new function does not need to know about the
LanguageContentSettings
entity.Also good point regarding the @todos. Moved the one that was still valid over and removed the other one. I think that can be seen as part of the deprecation done here, as it doesn't really make sense to have @todos on deprecated code, so I hope is not considered out of scope.
Comment #104
tstoecklerSorry.
Comment #105
GoZ CreditAttribution: GoZ at Iosan, Barbe-Rousse commentedI have the same issue on 8.6.x and #104 works fine with a re-work patch. DO NOT use this in production, it's a port patch for 8.6.x on an on progress issue.
Comment #106
tstoeckler@GoZ if you've verified that the patch was updated and correctly, maybe you can set it back to RTBC, since it was already reviewed multiple times above and the latest comments have been adressed? That would be awesome.
Comment #107
coach777 CreditAttribution: coach777 commentedThere is a piece of code, which can be put into /Drupal/Core/Database/Connection.php::handleQueryException() after $message=...;
It's a ugly part of code, highly misplaced, but it's doing one job - fixing broken database at first error encounter. This is not a solution, just workaround.
Note, that mysql database driver is using a quirk, to check that field exists in database, in web/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php::fieldExists(), which catch's exemption as a sign, that this field not exists.
Comment #108
GoZ CreditAttribution: GoZ at Iosan, Barbe-Rousse commentedLet's go RTBC
Comment #109
alexpottWe need a re-roll here.
@see's are best in the docblock
The formatting here is a bit off.
Two lines aren't necessary here.
We need to add this to the change record to say that this is no longer needed and is now ignored.
Comment #110
alexpottAlso we need to base this on 8.7.x first.
Comment #111
Martijn de WitSee comment from @Taran2L at "Call to a member function getThirdPartySetting() on null in ContentTranslationManager"
https://www.drupal.org/project/drupal/issues/2868294#comment-12919604
Comment #112
vacho CreditAttribution: vacho at Skilld commentedPorting this patch to 8.7.x and solving some problems comment at #109
Comment #113
Taran2LHere's an interdiff for the patch in #112
Comment #114
Taran2LSeems like this one has not been addressed yet:
Variable should go after type declaration
Should be 8.7.x now
Comment #115
Taran2LCR updated: https://www.drupal.org/node/2973222
I've addressed all issues from my previous comment and found one more migration that needed update. Please find updated patch
Comment #116
Taran2LComment #117
Taran2LArghh, another small update :/
Comment #119
tstoecklerI think #109 was a review of #105 and not #104, which confused me a bit. In any case the changes since then all look good to me and I did review the whole patch again to make sure that with all the back and forth between 8.6 and 8.7 everything is as it should be. The update to the change notice also looks good. Since I didn't work on this since it was last RTBC, I can safely RTBC this again.
Comment #121
tstoecklerOK, this conflicted with #2977107: Use more specific entity.manager services in module .services.yml files in a rather unfortunate way, which made the rebase a bit more involved. Thus, going back to needs review so that someone verifies that my thinking is correct on this.
Two points are noteworthy:
ContentTranslationUpdateManager
entirely I removed theDeprecatedServicePropertyTrait
and the deprecation messages in the constructor. I don't think it makes sense to warn people about the incorrect (deprecated) usage of something while at the same warning them that they shouldn't be using the thing in the first place. So I'm rather confident about this, but I'm still not 100% sure.ContentTranslationManager
and made it optional with a deprecated BC layer if it is not provided. This issue, however, removes the second parameter of the constructor, because that second parameter is a now-deprecated (and unused) service. So I first thought to minimize the amount of change introduced here, to support explicitly passingNULL
as the second parameter and throw a deprecation warning in case someone was still passing an actual instance ofContentTranslationUpdateManager
. However, that would mean that we would make passing an explicitNULL
as the second parameter the recommended way of using that service including in Drupal 9. Instead, the actually preferred way of instantiating the service should benew ContentTranslationManager($entity_type_manager, $entity_type_bundle_info)
as those are the services that are actually needed. So I implemented it in that way, which - together with backwards-compatibility for all previous instantiation patterns - lead to a couple of things:$updates_manager
as the second parameter we cannot typehintEntityTypeBundleInfoInterface
for$entity_type_bundle_info
.ContentTranslationUpdateManager
we should assume that either the third parameter is the entity type bundle info or there is no third parameter at all. This could have been solved with a third optional parameter which will be removed in Drupal 9, but I chose to implement thisfunc_get_args()
instead as - even though that might be regarded less elegant in terms of the code itself - I found it less confusing for the end user who is reading the documentation, especially together with the other change.Comment #122
tstoecklerAhh because of the "missing" typehint
EntityTypeBundleInfoInterface
is now unused inContentTranslationManager
, sorry. Will fix that once there is agreement regarding #121.Comment #123
Taran2LHi @tstoeckler, thanks for the updated patch! The sequence of events is a bit unfortunate, I totally agree!
I've spent some time checking it. Here's my outcome:
ContentTranslationManager
service should support only 2 instantiation patterns:['@entity_type.manager', '@content_translation.updates_manager']
['@entity_type.manager', '@entity_type.bundle.info']
ContentTranslationUpdateManager
and get correct service directly from the container, like other code doesComment #124
tstoeckler@Taran2L that's fine with me, your suggestion sounds sensible. I would like confirmation from a release manager, though, that this is in line with the release process. Tagging accordingly.
Comment #125
BerdirSorry :)
Yes, we definitely don't need to support the 8.7-8.7 change, so that's fine, no release manager feedback needed.
Officially we don't have to support BC for constructors, but I did spend a lot of time being extra nice and careful in my entity.manager issues to keep breaking contrib/custom due to such changes to an absolute minimum, it's pretty annoying, especially if you can't write code that works with *both* 8.6 and 8.7.
My suggestion would be to do something similar to what I tried for SystemManager: #3025152: Remove entityManager constructor argument from SystemManager:
Like #124 suggested, make the constructor:
['@entity_type.manager', '@entity_type.bundle.info']
but then don't add the type hint for the EntityTypeBundleInfo service and in the code, add if (!($entity_type_bundle_info instanceof ...)) { @trigger_error() + assign from \Drupal::service(). ).Comment #126
BerdirYou could even update the configuration for the DeprecatedServicePropertyTrait to not break a subclass that would still access the removed property.
Comment #127
tstoecklerOK, sounds good. Will implement unless someone beats me to it.
Comment #128
tstoecklerOK, here we go. Good idea in #126, I didn't think of that! 👍🏿
Comment #129
Taran2LThis does look good to me! Not sure, if I should set it to RTBC officially, but at least I can vote for it.
+1 to RTBC
Comment #130
ericdsd CreditAttribution: ericdsd commentedpatch #105 works for me against Core 8.6.9
I had to uninstall and reinstall content translation module
+ enable translation on a content type
+1 to RTBC
Comment #131
osmanre-rolled the patch from #105 against 8.6.x. simply formatting.
+1 RTBC
Comment #132
osmanalso see the combined patch at #2868294-61: Call to a member function getThirdPartySetting() on null in ContentTranslationManager
Comment #134
BerdirThe quick workaround for this bug has been to call $entity_definition_update_manager->applyUpdates(), that was for example done in multilingual_demo_install() and it was about to get into core with #3037111: Import multilingual content into Umami.
#2976035: Entity type CRUD operations must use the last installed entity type and field storage definitions broke that one-line workaround, now a workaround would need to explicitly install all the extra field storage definitions. As annoying as that might be right now, I think that is a good thing, it shows perfectly just how much applyUpdates() was misused to work around bugs and other weird things with possibly very problematic side effects.
I think it is important that this is fixed in 8.7.x, to unblock the umami issue so that it doesn't require those workarounds. Only getting it into 8.8 would also make the constructor changes that were done here much more complicated, they were changed in 8.7, we can just remove parts again, but we couldn't do that in 8.8.
I was wondering whether this should be on a service instead of adding new functions, but it is called by hooks, so if those ever become hooks, it would be easy to move the helper function to the same event listener instead of making it a public API (it is basically the whole point of this issue to avoid having an API that needs to be called).
I'm not sure if the @todo here is very helpful though. that issue hasn't been updated since 2015 and likely won't go anywhere anytime soon. work is happening in other issues, and if we do provide an improved API, we'll likely deprecate the old one, in which case we'd be forced to update this anyway.
So I'd suggest to just remove that.
since we touch it, maybe we should add the info that this should be done since 8.7.0 like more recent constructor deprecation messages.
Other than that, I think this looks great.
Comment #135
tstoecklerThanks for the review! Agree that it would be great to have this in 8.7.x. If I personally had a slot for marking an issue as critical without other people being allowed to challenge that decision, this issue would be it ;-)
Re 1.: @alexpott explicitly asked for "leaving" that todo in (i.e. moving it from its old location) in #101 so I am erring on the side of having it where we can always remove it rather that not having it.
Re 2.: I slightly changed the deprecation message, I hope that's what you meant.
Comment #136
tstoecklerOops, forgot to upload the interdiff.
Comment #137
BerdirThanks, lets get this in. No strong feelings on the @todo, just doesn't seem very useful to me but if others prefer it, fine.
Yes, not sure about critical or major. As I said, it is a good thing that the workaround is gone and we have to fix it now to unblock official initatives. The downside of official initiatives is that everything else becomes less important ;)
Comment #138
plachNice simplification!
Please let's add a unit test ensuring deprecation errors are triggered whenever we 1) pass the update manager to the CTM constructor, 2) the update manager is instantiated, 3) the service is retrieved, per https://www.drupal.org/core/deprecation.
Now we need an
instanceof
check to ensure that$entity_type_bundle_info
is actually a bundle info object.Can we retrieve the unchanged entity to avoid static caching?
Comment #139
plachI briefly discussed our deprecation testing policies with @catch and we're not sure this warrants a unit test. Moving back to RTBC, however a new patch addressing the nitpicks in #138 would be great to have :)
Comment #140
Berdir1. Yeah, As mentioned on slack, I've never done unit tests for constructor deprecations, I think you were the only one who ever did that :) I think that's overkill unless it's really complex/ a very common base class, it's pretty unlikely that someone subclassed this.
2. What about inverting the instanceof check to trigger if it's not the new interface instead of triggering on the old one?
3. I think that's not necessary because this is a kernel test, Static cache is automatically reset then, that stuff is just necessary for web tests. And now that we have a entity static cache service, I think it would be nice if we could implement a reset like we have for other static caches on POST requests.
Comment #141
tstoecklerThanks @Berdir! The interdiff looks good to me.
Comment #142
penyaskitoTested #140 for #3040859: Undefined index: content_translation_source (Failures in Drupal\paragraphs_demo\Tests\ParagraphsDemoTest) and #3040863: Failures in \Drupal\Tests\lingotek\Functional\LingotekNodeWithParagraphsManageTranslationTabTest on D8.7.x and above and it works.
Comment #143
alexpottCrediting @psf_, @dxvargas, @nkoporec, @joey-santiago for patch testing
@alexpott, @plach for patch review
@andy@andyhawks.com for creating the issue
Comment #144
alexpottCommitted and pushed 46424a89ef to 8.8.x and ad528c7375 to 8.7.x. Thanks!
Comment #146
Gábor HojtsyComment #147
penyaskitoSince this commit I'm getting 'LogicException: Getting the base fields is not supported for entity type Contact form.' when doing:
\Drupal::service('content_translation.manager')->setEnabled('contact_form', $this->contactForm->id(), TRUE);
This looks like the expected behavior as far as we cannot make contact forms translatable in the UI. We might be missing some checks somewhere else and that
setEnabled
did nothing, but didn't fail as it does after this commit. Just documenting it in case someone else gets this error now.Comment #148
Berdir@penyaskito contact_form is the config entity for the contact_message, that line never made any sense, no idea how it didn't fail before.
Comment #149
penyaskito@berdir I checked before this patch, and it failed if there was no entity definition with that name, but passed when a config entity id was passed. It didn't check which kind of entity that definition was.
Comment #151
anurag.s CreditAttribution: anurag.s commentedComment #9 Helped me resolve the issue.
Comment #152
quietone CreditAttribution: quietone at PreviousNext commentedPublish change record.