I added simple Drush command to export all items from an entity instead of item with the ability to set defined criteria to limit exported items based on where conditions.
Use case:
I need to export all menu links for the main menu in order to deploy easily and limit the effort and time needed to create them from the interface or upload the database as I have 2 languages.
the command takes 3 parameters
entity_type: required
property name: optional
property name: optional
the below piece of code summerizes the idea, I also prevent export 0 $ids and superadmin uid=1
$properties = $property_name ? [$property_name => $property_value] : [];
$entities = \Drupal::entityManager()->getStorage($entity_type)->loadByProperties($properties);
drush_default_content_export_references($entity_type, $id);
Issue fork default_content-2786479
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 #2
pguillard commentedReally useful !
I had the same need, to have default content only for taxonomy terms from a specific vocabulary that had too much terms to export them individually.
However, it seems this patch doesn't apply, rerolled patch attached.
Comment #3
keesje commentedPromising, same usecase as pquillard.
Patch confirmed as working.
Quickstart:
export terms of given taxonomy:
$ drush default-content-export-all taxonomy_term vid yourvocab --folder=modules/custom/yourmodule/contentAn "import" drush command would be nice ;-)
Comment #4
badjava commentedThis is a very useful patch and works pretty well. However there are a few issues and I don't think it should be RTBC:
Comment #5
badjava commentedMade the following changes:
- Removed the code that is supposed to prevent admin user from being exported as it only works if the user entity_type is specified. This is to provide consistent behaviour between all entity types.
- Removed the try catch since this only works in certain situations as well when incorrect property type is specified. If you specified an incorrect entity_type, it would generate a PHP error. This is now consistent with the other default_content drush commands.
- Fixed code style issues.
Comment #6
badjava commentedMarking this as needs work because a test needs to be added.
Comment #7
badjava commentedI reworked the patch and simply integrated the property name and value parameters into the existing dcer command. So instead of:
You can now pass a property name and value such as:
Comment #9
badjava commentedLet's try this again.
Comment #10
ayalon commentedHere is an updated version for the latest version:
Comment #12
sutharsan commentedRe-rolling patch default_content-export-all-items-2786479-8.patch (from comment #9)
Comment #13
andypostComment #14
kenorb commentedI'm a bit confused. Initial issue is about exporting all items from an entity, patches till #5 doing that fine by adding `default-content-export-all` command. What happened since #7? Where this feature has gone? How patch #12 suppose to export all items from the entity? Can anybody give example how one can export all items (e.g. from the given vocabulary) using the latest patch?
Comment #15
kenorb commentedOk, I got it, applied patch from #12 and the following command seems to work (doesn't generate any errors), but giving the empty list:
drush dcer taxonomy_term vid action_codesI'm testing this right?
Comment #16
tacituseu commentedApplied #12 to dev, works fine.
@kenorb: add optional '--folder=' parameter to specify path, otherwise it will export to current directory.
Comment #17
ayalon commentedHere is an updated patch for the DRUSH 9 integration aswell.
Comment #19
socialnicheguru commentedcan this integrate with https://www.drupal.org/project/taxonomy_machine_name?
Comment #20
andypostComment #21
pguillard commentedJust did the reroll stuff
Comment #22
stephen-cox commentedThe patch from #21 works well for me when exporting entire vocabularies using Drush 9.
Comment #23
eelkeblokI'd say this needs changes for drush <9 and drush 9 consolidated in a single patch? Also, isn't there a way to share code between the two (DRY)?
Comment #24
larowlanFor #23
Needs tests too?
Comment #25
socialnicheguru commentedit should tell you if it can write to the file specified.
Comment #26
tallytarik commentedRe-rolling with Drush 8 support.
Comment #27
rajanvalecha12 commentedHere's the patch for the latest release 8.x-1.0-alpha8 of default_content.
Comment #28
flyke commentedThanks, this works great for exporting all terms in a vocabulary, like:
drush dcer taxonomy_term vid tags --folder=modules/custom/my_custom_module/contentHowever, I cannot figure out how to do this to export all menu items.
I do not get any error if I do this:
drush dcer menu_link_content id main --folder=modules/custom/my_custom_module/contentBut no menu link is exported.
If I replace 'main' with 'thereisnomenuwiththisid' then there is also no error, so its just not doing anything.
If I change the code to:
drush dcer menu id main --folder=modules/custom/my_custom_module/contentthen I get error:
Entity "menu" with ID "main" is not a content entityPlease help on exporting all menu links, as was mentioned in the very description of this issue.
UPDATE: never mind, figured it out:
drush dcer menu_link_content menu_name main --folder=modules/custom/my_custom_module/contentComment #29
komlenic commentedConfirming that this worked as expected for exporting all terms in a hierarchical taxonomy vocabulary.
Drush 10.2.0
Drupal 8.8.5
Default Content 8.x-1.0-alpha8
Comment #33
dasjoAdded merge requests both on 8.x-1.x and 2.0.x based on #27
Comment #34
dasjoI'm new to the mixed workflow between pull request and patches. For my composer.json file, I created a patch on top of the 2.0.0-alpha1 tag that seems to apply: https://git.drupalcode.org/issue/default_content-2786479/-/commit/b30f37...
Comment #35
eelkeblok@dasjo It's also possible to base a patch on an entire MR, see https://www.drupal.org/docs/develop/git/using-git-to-contribute-to-drupa...
I did just realize this probably means your pipeline will apply a different patch as soon as somebody changes the PR, which could be risky. It'd be nice to be able to easily get a patch based on two commits instead.
BTW, you do not need to bother with the git commit message format; it will be applied when merging an MR from the Drupal.org interface, which will do a rebase, apply the commit message template (or rather, apply the commit message that is also used for the "git command" box) and merge the result.
Comment #36
mbovan commentedUpdated the code accordingly as
::writeDefaultContentno longer exsists in2.0.xbranch.This patch is based on #31.
Comment #37
berdirThis changes how the command works, that seems problematic, even for an alpha release version.
We could keep support both in case property value is empty? or use parameters instead of arguments.
it would require fewer changes in the two drush commands if we just dynamically add a condition in the entity query, that's just what loadbyProperties() also does.
Comment #38
marios anagnostopoulos commentedChanged the code to use options for property queries.
I moved the logic that fetches the entities to be exported, into the exporter service.
This way we can call on this functionality on both the drush 8 and 10 commands, with the least possible duplicates. Furthermore, this way we don't have the problem mentioned in #37.
I did not add the resolveExportedEntities to the ExporterInterface, because I recon it will not be a mandatory implementation for someone who would want to create his own exporter and use the it in his own command for some reason.
I corrected a minor error in the comments, where the simplesitemap module was referenced :P.
I added some logic to export all entities for all entity types, if no entity type is provided.
I thought we could also try to allow property filtering with null entity_type_id by checking, if each entity type has the property in question, but concluded that it would become a true mess and it would be an overkill anyway, so I did not do it.
I have just tested this with drush 10, since I did not have the time to create a working environment atm for drush8, but it should be working fine. It would be great though, if someone could cross check it (Or I might find the time to do it myself).
In the drush 10 command i added a user prompt for the case of exporting the whole site content.
Finally I also provide a patch for the alpha1 tag, for the case that someone wishes to apply it before the 2.0.x is merged with the alpha1.
Edit: Just noticed the files should have been named ....-38 instead of ....-32, sorry for that :P
Edit2: The patch for alpha1 failed to apply, because i tested it agains 2.0. I don't know how to retest for the tag.
Comment #39
marios anagnostopoulos commentedComment #40
marios anagnostopoulos commentedReroll
Comment #42
marios anagnostopoulos commentedI remove the changes in the drush.inc files, since we discussed that they will be removed anyway in another issue.
I also abort the execution of the command, if no entity id is provided but properties were given.
I ended up not throwing an exception, since the check is made in the command itself, so I just stop the execution after displaying an error via the logger.
If this is not the best way to go about it, let me know and I'll change it.
Comment #43
berdirAdded two more comments, then I think it's ready to go.
Comment #44
marios anagnostopoulos commentedI made both the changes requested, changing it back to needs review.
Comment #45
marios anagnostopoulos commentedAlso I am not sure If I am the one who should mark the gitlab comments as resolved or the reviewer :)
Comment #46
marios anagnostopoulos commentedComment #47
delacosta456 commentedhi @flyke
i was reading this discussion to find a solution for my case and started being confuse when i read your comment.
Please what did you exactly mean by the below
I have this patch applied but not really sure on how to make your command work.
Thanks
Comment #48
flyke commentedHi @delacosta456,
In the 4 years since that comment of me, I haven't really used the default_content module anymore.
drush dcer menu_link_content menu_name main --folder=modules/custom/my_custom_module/contentYou need to literally use (copy/paste) this part:
drush dcer menu_link_content menu_nameYou need to replace
mainwith the actual menu id you want to export from.For example, If you edit the menu you like, and the url in your browser for the menu edit page is something like:
https://mywebsite.com/admin/structure/menu/manage/footer-mainThen the last part from that url,footer-main, is your menu id. So in the drush command you need to replacemainwithfooter-mainso it becomes:drush dcer menu_link_content menu_name footer-main --folder=modules/custom/my_custom_module/contentThe last part you need to replace is this:
--folder=modules/custom/my_custom_module/contentIf you have a custom module, located at modules/custom/my_custom_module, you need to create a folder 'content' in there. That is where the exported items will be placed after running the drush command.
Comment #49
delacosta456 commentedhi @flyke
Thanks for your clarification.
However following your suggestion returned an error of too many argument
Below is the drush command i try to use :
drush dcer menu_link_content menu_name main --folder=modules/custom/brains_mtcb_default_content/contentand this return the error message below
i am i missing something ?
Thanks
Comment #50
flyke commentedHi @delacosta456,
As I said, it's been four years, so I probably got it wrong.
I did retrieve my personal notes in a readme file from a custom module in one of our projects from years ago, maybe this still works and can help you:
EXPORT block content:
drush dcer block_content 1 --folder=modules/custom/my_custom_module/content
-> change '11' to the desired block id. You can see blockid in url when editing a block.
-> a file with a unique id string as filename will be generated, like: 55489d08-4eac-4818-9cea-e3cb38b70195.json
-> change file name to something more descriptive, likke: block-about-us.json
EXPORT menu items:
drush dcer menu_link_content 45 --folder=modules/custom/my_custom_module/content
-> change '45' to the desired menulink id. You can see the id in url when editing a menulink.
-> a file with a unique id string as filename will be generated, like: 55489d08-4eac-4818-9cea-e3cb38b70195.json
-> change file name to something more descriptive, like: menulink-contact.json
EXPORT node:
drush dcer node 1 --folder=modules/custom/my_custom_module/content
-> change '1' to the desired node id. You can see the id in url when editing a node.
-> a file with a unique id string as filename will be generated, like: 55489d08-4eac-4818-9cea-e3cb38b70195.json
-> change file name to something more descriptive, like: node-homepage.json
EXPORT user:
lando drush dcer user 14 --folder=modules/custom/my_custom_module/content
-> change '1' to the desired user id. You can see the id in url when editing a user.
-> a file with a unique id string as filename will be generated, like: 55489d08-4eac-4818-9cea-e3cb38b70195.json
-> change file name to something more descriptive, like: user-contentmanager.json
Export menu items:
- create the menuitem (locally)
- edit it to see menu item id: admin/structure/menu/item/20/edit -> id = 20
- drush dcer menu_link_content 45 --folder=modules/custom/my_custom_module/content
- If that does not work, you have an older version of default_content and you should use:
- drush dce menu_link_content 45 --file=modules/custom/my_custom_module/content/menu_link_content/menu-link-overzicht-tweedehands.json
- repeat for all the menulinks you want to have (do not add menulinks that are automatically added via views pages)
And then lastly, I had code for importing contant via a update hook like this, but remember, this is from some years ago:
Comment #54
berdirAnother review. I'm quite conflicted between this and #3001618: Add `drush dcer --bundles` option to limit export. It doesn't make sense to add both, and while this is more flexible, it doesn't support some things like multiple bundles that the other issue supports and it's more complex to use.
I think the menu use case is a good example why just bundles aren't sufficient, maybe we can expand it to also support comma separated values and add that as an IN condition to the entity query and take that from the other issue.
To be honest, not entirely sold on the new method. It needs a lot of work on docs, API changes on ExporterInterface and now that the old drush changes are removed, is really only used once. Instead of addressing all the review points, it might be easier to just inline the entity query into the drush command again and add the condition there. It doesn't even need a loop then since it really only supports a single condition.
@delacosta456: I recommend reading the built-in documentation that the drush command automatically provides, that would tell you that the property name and value are no longer arguments but options that you need to pass with --property-name and --property-value.
Comment #55
anpel commentedComment #56
marios anagnostopoulos commented@berdir would it be overkill to have a settings form with the entities / bundles machine names selectable? Then we could get the entity types / bundles to export with the command via the config and simplify the exporter.
Comment #57
thejimbirch commentedWith the current diff from MR 34, I can't get menu links of the main menu to work.
Command:
drush dcer menu_link_content menu_name main --folder=../recipes/menus/content/Error message:
Too many arguments to "dcer" command, expected arguments "entity_type_id" " entity_id".If I try dce
drush dce menu_link_content main --folder=../recipes/menus/content/I get the following error:
The "--folder" option does not existIf I drop the folder part, I get:
Entity "menu_link_content" with ID "main" does not existComment #58
johnlutzFor anyone that need any clarity on how to use the command:
drush dcer menu_link_content --property-name=menu_name --property-value=main --folder=location
Comment #59
phenaproximaThe ability to export with bundle filtering has now landed in core: #3554978: ContentExportCommand::loadEntities() should use loadByProperties()