Problem/Motivation
EntityStorageInterface::create() creates a full working entity object, filled up with default values.
This is fine most of the time, but there are usecases where you simply don't need these default values.
One example is: REST module wants to represents a diff entity, so it doesn't need to load default values.
By providing EntityManager::createInstance() we would not only provide such a lightweight function, but it would also
allow to have a valid implementation of the PluginManagerInterface
Proposed resolution
Remaining tasks
User interface changes
API changes
EntityManager is a plugin manager, which means its interface includes createInstance() and getInstance(). These are currently non-functional, because #1763974: Convert entity type info into plugins only addressed discovery, not the rest of plugin manager functionality.
Making them functional will allow classes that need to create and load entities to do so via an injected manager rather than by calling global functions. This is another step towards making things unit testable and better managed via the dependency injection container.
Comment | File | Size | Author |
---|---|---|---|
#116 | 1867228-116.patch | 13.76 KB | kgoel |
Issue fork drupal-1867228
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #1
effulgentsia CreditAttribution: effulgentsia commentedHere's a step towards this, with jsonld converted to use it. These tests cannot yet be converted to unit tests, because of other Drupal dependencies, but it's a step. Per the @todos, we'll be able to take another step after #1831264: Use the Entity manager to create new controller instances.
Comment #2
yched CreditAttribution: yched commentedSo :
- Manager::getInstance() = load from storage using the passed in entity id, NULL if not exists (= entity_load())
- Manager::createInstance() = create a fresh structure from scratch (=entity_create())
That's very different from the usual pattern where getInstance() is a wrapper around createInstance(). The contracts in the current phpdoc for the respective FactoryInterface::createInstance() & Mapperinterface::getInstance() are currently a bit blurry, but I guess getInstance() is intentionally loose for any plugin type to give it its own meaning & behavior.
This is actually quite similar from the ConfigMapper @EclipseGc adds in #1535868: Convert all blocks into plugins (gets a plugin based on configuration loaded from a config file, if found, nothing of not). That patch does take care of adjusting MapperInterface though:
(over there, FALSE is returned rather than NULL if not found in storage, though)
Other than that, I was a bit skeptical about making "node 1 is a plugin instance" turn into a reality. Mental bug.
OTOH, doing so means that if we solve #1863816: Allow plugins to have services injected, we solve "How to make entities receive injected objects from the container" as well.
Comment #3
sunHm - can you explain why entity_test needs this special treatment? (perhaps even in code)
Why isn't it using the regular EntityManager?
Comment #4
BerdirAlso, how does this relate to #1847002: Move entity type classes from Drupal\$provider\Plugin\Core\Entity to Drupal\$provider\Entity which I thought we kinda agreed on doing?
Comment #5
fubhy CreditAttribution: fubhy commentedAt some point we want to deprecate most of (if not all of) entity.inc and replace the entire entity eco-system with fully injectable OO. I am 100++ doing this rather early than late and really think we should start discussing this as a whole. There is no META issue for that yet. Instead of scattering single conversion issues all over the place we should maybe look at the big picture first. We need a thoroughly thought-through battleplan for this as a whole.
Comment #6
fagoTotally! So, +1 on having that EntityManager. But the question is: Should the EntityManager be a PluginManager also?
As we need to solve #1863816: Allow plugins to have services injected for entities also, the plugin system actually seems to be a good fit. However, entities have the extra requirement of serialization, which we'd have to manage for injected services..
Comment #7
tim.plunkettAt least for creating, we don't need a factory. If we wait on #1831264: Use the Entity manager to create new controller instances, this is all we need.
(Not 100% sure about loading yet, since getInstance() takes an array)
Comment #8
EclipseGc CreditAttribution: EclipseGc commented+100000000000 to this.
Eclipse
Comment #9
tim.plunkettNo need for the factory now.
Comment #10
EclipseGc CreditAttribution: EclipseGc commentedIf that passes tests RTBC
Eclipse
Comment #12
yched CreditAttribution: yched commentedThis means that the storage controller de facto is the factory ? Would it make sense to embrace that and make storage controller implement FactoryInterface ?
Comment #13
tim.plunkett#9: entity-1867228-9.patch queued for re-testing.
Comment #14
tim.plunkett#12, you could do that, but it doesn't really matter and would just complicate EntityStorageControllerInterface. The EntityManager implements FactoryInterface, and just because it decides to proxy its createInstance() call to another class doesn't mean that class needs to implement FactoryInterface itself.
Comment #16
tim.plunkettWhoops!
Comment #17
sunI agree with @yched.
Even though the override/interface situation is a bit weird here, since:
- EntityManager extends PluginManagerBase
- PluginManagerBase implements FactoryInterface already (but forwards all calls through $this->factory) [which is weird, since that essentially means that a plugin manager can fulfill the interfaces, even when not providing an actual factory]
...I still think it is technically correct that EntityManager should implement FactoryInterface, since it is explicitly taking over the interface method(s).
As such, the change mainly serves for long-term documentation and clarity purposes, but I think it's more correct.
Comment #18
yched CreditAttribution: yched commentedWell, my point was about having the storage controller implememt FactoryInterface, and in fact I think @tim's answer in #14 works for me.
Less sure about #17. PluginManagers *are* factories, that's the very design of the plugin API, I don't think we need to make that extra explicit in the specific case of EntityManager.
I have a feeling that this boils down to "does it make sense that the storage controller is the thing that ultimately is in charge of entity_create(), or does create() belong to a real, storage-agnostic factory" - which IIRC was discussed at some point, and I'm not sure where we stand on this.
At any rate, changing that design is not a topic for this patch.
Comment #19
BerdirYes, it was discussed in the Entity UUID issue where Dries thought that it's wrong that the storage controller is the factory.
Comment #20
sunWe also discussed this: #1893772: Move entity-type specific storage logic into entity classes
Comment #21
fagoI think this would at least deserve a comment that the "plugin configuration" are the entity values in the case of an "entity plugin".
Still, I must say I find that wording very confusing. But moreover, it doesn't work well with #1868004: Improve the TypedData API usage of EntityNG - what I still think is a good idea to do.
Making each entity type a proper data type of the typed data API would maked it a "type" plugin also, thus it would have to be create-able via the typed data manager, which uses "typed data definitions" as $configuration and provides another helper (TypedDataManager::create()) for instantiating objects + setting a value.
Likewise, I think the entity-factory should be used by the storage controller during load *and* create, while entity-create should be a separate helper using the factory *and* taking care of setting the values. So $configuration does not need to be $values - instead I think having an array including the $bundle would make sense here.
Comment #22
tim.plunkettThis is just redundant. What does it give us?
Comment #23
EclipseGc CreditAttribution: EclipseGc commentedRTBC #16 in my opinion. The rest of the conversation seems to be mostly documentational in nature, and can be done as a follow up. Unless fago feels like the entire entity system can be rewritten as TypedData Plugins very quickly, I'd suggest we not prevent this issue from getting committed. In fact, even with fago's issue, I'd suggest this go in now. it's minor and doesn't increase the work that would have to be done to move to what fago was hoping for.
Eclipse
Comment #24
tim.plunkettNote, #16 is RTBC not #17. Retitling to reflect the scope of the patch.
Comment #25
tim.plunkettJust reuploading the exact file, to make sure the right patch goes in :)
Comment #26
fagoThat's fine with me, however I still think entity values == $configuration is a major WTF we should not do.
Citing from above:
So what about load also? If we have a factory we should use it.
Comment #27
effulgentsia CreditAttribution: effulgentsia commentedI think the WTF is just the name $configuration. If FactoryInterface named the variable more generically, like $values or $data, then I don't think there's an architectural WTF in entity values equaling this argument. However, even though PHP allows it, we have no precedent elsewhere in core yet for renaming interface parameters in the implementation class, so instead this patch adds a 'values' subkey to $configuration. We may want to keep that, on its own merits, and especially considering future TypedData integration, but if not, we can discuss further in a followup.
I still think load() should be implemented as an implementation of MapperInterface::getInstance() per #1. But since given the other comments in this issue, I think it needs more discussion, so can we do that as a followup?
Comment #28
fagoI don't think getInstance() == load and createInstance() == create works out well. Both are supposed to get you a new instance, while get instance can determine the instance based upon various options. But loading is not about returning a new instance of an object, it's more. I still think entity_load() should stay separately and use the factory when it's about to initialize the entity object during load - that is what a factory is for - not?
True - but that's not the case. Likewise as for loading, it would make sense to me if we have StorageController's create to use the factory to initialize the entity object - just as load.
That would actually make $entity_manager->createInstance() a real factory which you can use to instantiate any kind of entity object. I've seen/fixed testing code in core that used entity_create() to instantiate an object although it is not new - so with that separation we could use $entity_manager->createInstance() in situations like that instead.
Thus, what about that?
Then, the question what $configuration isremains independently from that:
$configuration['values'] sounds better to me, but maybe it would be even better to re-name it to $data? Howsoever, at least it needs documentation.
Comment #29
effulgentsia CreditAttribution: effulgentsia commentedHere's the disconnect for me with #28. I think I've been assuming that the intended design of the plugin API is for Manager::createInstance() and Manager::getInstance() to return fully functional instances capable of being used by application code. In the case of instantiating an entity that does not yet exist in the database, that means invoking hook_entity_create() prior to EntityManager::createInstance() returning the instance. In the case of instantiating an entity that does exist in the database, that means not invoking hook_entity_create(), but instead invoking hook_entity_load() prior to (depending on your point of view, EntityManager::getInstance() or EntityManager::createInstance()) returning the instance.
So, the idea of EntityManager::createInstance() being something that only calls
new $class(...)
and nothing else, so that it can be used by both create() and load(), but consequently can only be used by the internals of StorageController, and not by application code, doesn't sit well with me.However, looking at our other plugins in HEAD, I don't see any preexisting evidence to support my perspective. The idea of there being something that needs to happen after
new $class(...)
, but before an instance is ready for use, might be something that EntityManager is the first core plugin manager to be confronting. So I guess it's up to us to decide whether in this situation, we want createInstance() to be raw and internal or complete and fully public. My bias is towards the latter but what do others think?If we want to go with my interpretation, then another way we can achieve fago's desire for there to be a factory that both create() and load() use is we can make a separate EntityFactory that just does the
new
and pass this factory to StorageController (EntityManager can be responsible for that injection), but meanwhile keep #27's behavior of EntityManager::createInstance() calling StorageController::create().Comment #30
EclipseGc CreditAttribution: EclipseGc commentedI'm basically ++ to effulgentsia's comments here. createInstance() is intended to be public api for all plugins, it's part of what makes them plugins. I'd prefer it be useful to application code regardless of how the rest of core may or may not be using that method, effulgentsia's interpretation is the intent of the plugin system. I think the entity manager has expanded on the typical manager paradigm in a lot of really good ways that support entities very nicely and locate their api in one place. This is nice, and it's why I've been reviewing and rtbcing these patches as they come through. I think we're very close to being able to point to entities as a good example of how plugins should be implemented.
Eclipse
Comment #31
fagoThe EntityFactory sounds like a good idea to me, but according to the interface createInstance() is already supposed to be a factory, see http://api.drupal.org/api/drupal/core!lib!Drupal!Component!Plugin!Factor.... I must say that an otherwise interpretation really confuses me?
Surely, it's public API - it's the factory. That does not mean you cannot use a higher-level factory in practice though. That's the pattern you suggested me doing for the TypedData API and which we have implemented there, e.g. it has TypedDataManager::getPropertyInstance() and create() what is higher-level API that gets used in practice.
Also, I think we'll need to to #1868004: Improve the TypedData API usage of EntityNG for cleanly integrating entities with the TypedData API and properly work with stuff like its validation. Thus, we'd get the "plain factory" at the typed data level there - what would free us to use the EntityManager as higher-level factory.
But still, having a factory doing entity_load() or entity_create() is confusing to me and not what I would expect a factory to do. To me a factory has to care about object instantiation and nothing more. But maybe it's just me who gets that wrong? - so I'd love to here more opinions on that.
Comment #32
tim.plunkettThis is why I now think this issue is won't fix. Entities aren't valid unless they've run through either one of those, just instantiating a new object of the right class isn't enough. You skip some important hooks and methods. At this point we don't need an Entity factory.
Comment #33
fagoOh, imo there are valid use cases for the factory. E.g. entity serialization API may want to create an entity without running create() or load(). Similarly, the use might be in test-cases where you create an entity with pre-defined values (maybe even including an ID) just for testing purposes - this manually created entity it's not necessarily new and thus should not be marked new or trigger creation hooks.
Comment #34
tstoecklerRe #33: Actually you can specify an ID in entity_create() and then (I think) isNew() will automatically realize that and return FALSE. Either way, the use-case you describe was specifically considered when designing the whole isNew() business. I don't know why we would ever want to work/code around entity_create().
Comment #35
EclipseGc CreditAttribution: EclipseGc commentedWe're not coding around entity_create() we're putting it in the centralize api on the same class as the rest of the relevant entity methods.
Comment #36
tstoecklerRight, that's not my problem. My problem is this:
Comment #37
jibran#27: entity-1867228-27.patch queued for re-testing.
Comment #39
BerdirTagging.
Comment #40
das-peter CreditAttribution: das-peter commentedHere's a new approach to this.
This is related to #1988492: Avoid having empty field items by default, since this will allow
EntityNormalizer
to identify non-modified fields, while we can provide sane empty values e.garray()
insteadNULL
for lists.I've some strange test-fails locally which I can't trace - let's see what the bot says.
Comment #42
tim.plunkettThis seems very confusing to have the same method name as Plugins, and having this whole effort based on making them true plugins, but then not actually calling the plugin code
Comment #43
das-peter CreditAttribution: das-peter commented#40: d8-entity-manager-entity-factory-1867228-40.patch queued for re-testing.
Comment #44
tim.plunkettThis seems weird, why not use createInstance()?
All of this should be in the entity manager.
This method should ONLY be called by EntityManager::createInstance()
This should be
return new static($values, $entity_type, $bundle, $translations);
Comment #46
das-peter CreditAttribution: das-peter commented@tim.plunkett Thanks four your feedback, I tried to incorporate your feedback. I hope this is closer to what we're looking for.
Comment #48
das-peter CreditAttribution: das-peter commented#46: d8-entity-manager-entity-factory-1867228-46.patch queued for re-testing.
Comment #49
fagoWhy not call this $entity_type here. $plugin_id makes no sense here.
Having that as the only API function as entity factory it's quite a WTF to call it $configuration.
Could we just rename $configuration to $values and pass it on as values + add additional parameters for $bundle and $translations?
I don't care about entities being plugins or not, but we should provide an entity factory with decent DX and that $configuration parameter is just confusing. Not sure what's the point of plugins forcing us to that method signature but that's probably another issue....
I could have lived with having the ugly createInstance() in addition to a proper API function like the previous instantiateEntity(), but just having the ugly method does not work out I think.
Unrelated?
Unrelated?
Comment #50
das-peter CreditAttribution: das-peter commentedAs of lack of knowledge of plugins and so on I don't feel entitled to have an opinion about the method names / signatures. Please let us meet, discuss that and find a conclusion. Then I'll happily convert that into code.
Ooops, that's stuff of #1988492: Avoid having empty field items by default - removed.
Fixed
ViewsUI
.Set to needs review to let the test bot do its work.
Comment #52
fagoDiscussed with tim.plunkett and daspeter that we should just fix the method signature of createInstance() to what makes sense - luckily we can do that as our second parameter is an array anyway. Also, we need to pass on the container to static createInstance() methods.
However opened #2100549: Plugin factories needlessly restrict configuration to arrays anyway.
Comment #53
damiankloip CreditAttribution: damiankloip commentedHang on, a very similar issue to this got closed (won't fix) a while ago. What's the difference now?
Comment #54
fagoWhich one? There are too many of those...
Comment #55
das-peter CreditAttribution: das-peter commentedI hope this reflects what we've discussed earlier.
I tried hard to follow berdirs suggestion and put the values passed into the constructor of
EntityNG
into the raw values property of the class instead relying on the magic setter.However, I miserably failed doing so - I wasn't able to get the tests working (e.g.
ContentTranslationWorkflowsTest
). However, the code of my attempts is still in the class but commented-out for the moment.If someone has an idea how to get this running please feel free to give it a try :)
Comment #56
damiankloip CreditAttribution: damiankloip commented@fago, I think it was https://drupal.org/node/1931894. Seems like almost the same thing that was rejected for making DI worse, not better.
EDIT: Tim this question is for you too :-) you were against creating entities from the manager originally, which is why we closed it. What's changed?
Comment #58
das-peter CreditAttribution: das-peter commentedSilly me, I forgot the actual fix that should avoid the fails :|
Comment #59
das-peter CreditAttribution: das-peter commentedBlargh, set issue status for bot.
Comment #61
EclipseGc CreditAttribution: EclipseGc commentedThis is just called create() everywhere else in core isn't it?
Docs seem wrong here, should probably be createEntity(). That being said, this is confusing. Why would we accept values here if we don't intend on using them? Following the flow of code, this ultimately runs through the Entity.php __construct() method which does indeed use the values, which for me calls into question the createEntity() method.
Looking at that method, this is all further confused by the fact that we use the storage controller in this case, but not in createInstance, nor within Entity::__construct(). That being said, this patch removes the __construct handling of $values, which again has me asking about createEntity vs createInstance. Seriously, W.T.F.? Please enlighten me.
In addition to all of this, I find the $bundle handling quite weird (and always have). Why don't we just add these parameters to $values since that's ultimately going to be what they represent on the entity anyway? If it's just a convenience thing, then that seems a perfect use case for createEntity() as a wrapper of createInstance() but none of that is happening here and I really don't understand why. I'm not trying to be antagonistic at all, but an explanation here would make this a whole lot easier.
Thanks!
Eclipse
Comment #62
das-peter CreditAttribution: das-peter commentedI'll try to explain why I started to work on this this might shed some light on it.
A while ago I started working on #1988492: Avoid having empty field items by default, which showed that we've some trouble to distinguish between empty / and not set values / fields in the
EntityNormalizer
.After some attempts to solve that - and breaking data type contracts while doing so (lists started to return NULL instead array()) we identified the fact that
entity_create()
applies default values to fields as a problem. Because of this we don't have a truly "unavailable" state of fields as required by theEntityNormalizer
to figure out what was "unset" and what was untouched when merging data.Now the idea came up to provide a low-level function to get an proper instance of an entity without default values applied:
createInstance()
was born.And since we thought it would be handy to have those functionality provided on central place while respecting the fact that every entity could have it's own special way to build itself we started working in this issue.
While working on this I realized that
DatabaseStorageControllerNG::create()
doesn't pass the provided pre-set values to entity class - what doesn't make sense. So I started to move the handling of values to pre-set intoEntityNG
and only left the part that applies default values inDatabaseStorageControllerNG::create()
.As far as I can see we've mainly a problem with naming methods and defining responsibilities. Unfortunately the only thing I can provide to support the decision making are my own goals:
EntityManager::createInstance()
?)EntityManager::create()
?)Entity::createInstance()
,Entity::create()
?)Can anyone please bring up other goals / requirements / limitations?
I think you miss-read the patch. Actually it brings back the values handling into the constructor of
EntityNG
, it's just different code and moved around within the constructor. The unpatched version of the create method in the storage controller simply never passes values into the constructor and does everything on its own.Comment #63
fagoNo, they are not. They document current behaviour: entity_create() != a factory. That's not touched by this patch and changing entity_create() is not the scope of it either, it's about introducing the long-missing factory *only*.
This part of the code was actually not used at all, but values sneaked in differently. Entity object instantiation is bit messy right now, this is why this patch has to clean it up. But yes, it should receive $values and apply them during construct.
In regard to the naming, there is no createEntity() (yet?). So far entity create() means the creation of new entities, not only new entity object instances.
We already use the static createInstance() for all entity controllers, so this patch just follows this pattern for now to avoid confusing with create(). I'm happy to discuss naming those things differently, but that discussion happens already over at #2015535: Improve instantiation of entity classes and entity controllers - so let's focus on it there?
Consequently, could we concentrate on adding a proper entity factory here, and settle on the names in #2015535: Improve instantiation of entity classes and entity controllers ? As das-peter points out we really need an entity factory - so let's do it with the names we have in place *now* and avoid derailing it on possible renames of entity_create().
Comment #64
damiankloip CreditAttribution: damiankloip commentedDid people see #56? :)
Comment #65
das-peter CreditAttribution: das-peter commentedHere's my next attempt.
I think I managed to get
entityNG
working with raw values instead the full fledged properties. Some really odd (magic) stuff related to languages / translations was happening here.If this works out it likely improves the performance of
entity_create()
EntityNG entities.By the way, does anybody have a feedback for Damian regarding #56?
Comment #66
fagodamiankloip, the issue linked was just about creating short-cuts. This one isn't, it introduces something we are missing right now: an entity factory. $storage_controller->create() is no factory, e.g. you would not use it to create entity objects during load...
Comment #67
fagoThanks daspeter for figuring that out, here a review:
Imo this patch should not change how entity-create operations are performed - it's out of scope for introducing a factory. As said, let's leave the re-naming discussion to #2015535: Improve instantiation of entity classes and entity controllers.
Looks good, but does this work for the bundle property if the $bundle is passed but not in $values?
I'd suggest
"Creates an entity object instance based on its values."
Better do not use "new" here as it is not necessarily $entity->isNew().
Should make use the usual dashes for the enumeration.
Misses a @throws for the exception thrown. The exception is not necessarily related to storage, maybe us "InvalidArgumentException" ?
out of scope?
Elsewhere we've been calling them "plain values", maybe go with that here also?
Lastly, should we add a unit test case for it?
Comment #69
yched CreditAttribution: yched commentedA bit lost between this and #2015535: Improve instantiation of entity classes and entity controllers - can we post an overall plan in a issue summary somewhere ?
Also, in Prague, it was mentioned that:
- we want to try to move away from direct $entity->property access on config entities in favor of getters / setters
- yet the current way we create entities (entity_create()) doesn't let IDEs get a proper type hint on the actual class/interface that is being created and is thus ruins method autocomplete.
Do we have a proposal to address that ?
Comment #70
Berdir@yched: #2096899: Add $EntityType::create() to simplify creating new entities
Comment #71
yched CreditAttribution: yched commented@Berdir: cool, thanks !
That's now three issues about entity factories though, so ++ on an overall plan somewhere :-)
Comment #72
das-peter CreditAttribution: das-peter commentedHere's another update.
#67:
\Drupal::entityManager()->createEntity()
and\Drupal::entityManager()->createInstance($entity_type, $values)
EntityManager::createInstance()
)While working on this if found some strange things:
$user->homepage
didn't have a property definition - changedEntityCrudHookTest
used "language" instead "langcode" what lead to overwriting the protected language property ofEntityNG
akaContentEntityBase
! Since I've changed the values handling now that shouldn't happen anymore.I'm afk until next Wednesday, so feel free to continue without me ;)
This patch wont pass all tests but it should be better than the last one.
PS: I've no clue why but I can't upload the patch as patch file (I get a 500 internal server error...). Thus I've attached it as zip archive.
Comment #73
BerdirRe-roll.
Comment #75
BerdirFixing tests.
Some interesting fails in there.
- Most test fails are related to isDefaultRevision not being set correct, added a hack, seems that should be handled in a better way, e.g. by an explicit call from the storage controller, but that is currently hard before we refactor that more
- Then I changed the $values wrapping in language code to only happen for defined fields, that fixed the menu breadcrumb test because otherwise $node->menu was suddenly an array with key LANGCODE_DEFAULT and the menu link entity within. No why nothing else exploded.
- Then there's the weird autocomplete code that I already noticed to be broken/weird in #2078387: Add an EntityOwnerInterface, which will properly fix this as a side effect, this is just bandaid.
- The TranslationTest is weird. I wasn't able to reproduce those php notices, but it blew up completely for me, and the code there is imho old and bogus. Changing the actual field name there resulted in an error because it got too long, so I shortened the suffix.
Comment #76
XanoI corrected spelling errors, all of them in documentation, with the exception of one in a translatable string.
Comment #77
BerdirThis is confusing and probably due to moving back and forth, but what now, bundle as part of $values or argument? :)
user's don't have a homepage. Only anonymous users on comments have.. yes, weird.
So, I think this is wrong. Let's remove it and see what happens, would like to see where this fails.
Ah, this I guess?
Hm, this seems a trick that comment.module uses to render that, and I would imagine that my fix in the constructor would fix that too.
Comment #78
BerdirOk, fixed the documentation so that it IMHO makes sense and reverted the homepage changes.
Comment #79
fagoI think we could do better with the differentiation. What about:
createInstance():
Instantiates an entity object based on its values.
(.i.e. avoid using the word "create" as creating involvnes something new, and people should not think about new entities here)
If you want to create a new entity, use EntityManager::create() instead.
(having EM::create() apply default values is one thing that both method differs, but it should not be the main reason to go with one method or the other. The mean reason should be what you are supposed to do: create a new entity, or instantiate an entity object)
I'd suggest stopping to "advertise" that function.
I'd suggest:
"Constructs an entity object for creating a new entity."
"Note that for the permanent creation of the new entity, the returned entity object needs to be saved first."
(imho it's enough to mention applied default values in the @return description)
Comment #80
EclipseGc CreditAttribution: EclipseGc commentedIs there a reason we need to be breaking the createInstance() signature? Seems like bundle could easily exist in the $values since that's what it ultimately gets merged into anyway.
Eclipse
Comment #81
Berdir78: entity-factory-1867228-78.patch queued for re-testing.
Comment #83
BerdirRe-roll, updated the comments.
@EclipseGc: We discussed this at length in Prague and agreed that this is the best approach. EntityManager still isn't really a plugin manager and there are still issues to move away further.
Comment #85
Berdir@plach: I'm completely lost in regards to the language related changes that happened and how it affects this issue. Care to have a look?
Comment #86
plachRerolled after #2005716: Promote EntityType to a domain object. This should also fix the language-related failures.
Comment #88
plachMmh, those exceptions might be related to #2156945: Clean up installer entity defaults following bugfix.
Comment #89
plachThis should be green.
Comment #90
fagoThe docs should be aligned with createEntity() docs.
nope, it's not necessarily empty - it depends on the value. It should say "The instantiated entity object."
same here.
Hm, we could just handle isDefaultRevision internally as a regular field? Not necessarily stuff for this issue though.
Comment #91
BerdirJust a re-roll for now, did not change anything I didn't have to. Had some noticed locally, let's try the testbot.
Comment #93
jibran91: entity-factory-1867228-91.patch queued for re-testing.
Comment #95
BerdirAnother re-roll, review still not addressed.
Comment #97
tim.plunkettThis will reduce *some* of the special casing and burden on storage controllers.
Comment #98
BerdirRe-roll.
Comment #100
BerdirTrying to fix that, but now we have the interesting problem that file normalization does no longer add default values, which is I think by design but the tests are expecting that. So someone else would need to do that?
Comment #102
Xano100: entity-factory-1867228-100.patch queued for re-testing.
Comment #104
Rajendar Reddy CreditAttribution: Rajendar Reddy commentedupdating the patch with reroll.
Comment #106
BerdirFixing a getStorageController() call.
Comment #108
Xano106: entity-factory-1867228-106.patch queued for re-testing.
Comment #112
dawehnerComment #113
fagoGiven the missing factory results in problems again and again (e.g. at #2458817: Creating new user entities for anonymous users is very slow), I think this easily qualifies as major.
Comment #114
XanoRe-roll.
Comment #116
kgoel CreditAttribution: kgoel at Forum One commentedRerolled. Looking into fails...
Comment #118
dawehner... Amateescu and I talked about the idea to compile the entity information into a class for each entity type, given that this class could then potentially
have the storage code, this could somehow invalidate some of the work of this issue as this compiled class could hold that factory.
@fago @entity_people
Feel free to tell my I'm thinking bullshit.
Comment #119
moshe weitzman CreditAttribution: moshe weitzman at Acquia commented#2553853: Optimize and/or cache dummy/empty entity creation will be closed in favor of this issue.
Comment #126
andypostProbably could be closed as outdated
there's 2 "creators" already, so having 3rd useless
Comment #127
Mile23EntityManager is deprecated, isn't it? https://www.drupal.org/node/2549139
Comment #128
BerdirSure, but that just means it moves to EntityTypeManager.
I think this is still relevant, because the method right now exists but is broken. This different to creating a new entity, it's about standardising on how an entity object is created, whether it is loading an existing one, creating a new example and special cases like content entity normalization for patching one, which is the best example why this would be nice to have.
Comment #133
bradjones1I think this would encapsulate/mark duplicated #2998471: Make the entity storage accessible from the entity object in so far as if entities have a factory, they could receive services from the dependency injection container such as the entity storage...right?
Comment #136
andypostas API change it should go to 10.1
also there's 3 TODOs
Comment #139
Bhanu951 CreditAttribution: Bhanu951 as a volunteer commentedComment #140
smustgrave CreditAttribution: smustgrave at Mobomo commentedThis issue is being reviewed by the kind folks in Slack, #needs-review-queue-initiative. We are working to keep the size of Needs Review queue [2700+ issues] to around 400 (1 month or less), following Review a patch or merge request as a guide.
Seems some failures in MR 3240