{"id":16355428,"url":"https://github.com/alexskrypnyk/generated_content","last_synced_at":"2025-08-04T09:32:35.135Z","repository":{"id":37015483,"uuid":"501619141","full_name":"AlexSkrypnyk/generated_content","owner":"AlexSkrypnyk","description":"Drupal module to programmatically generate content.","archived":false,"fork":false,"pushed_at":"2025-05-13T10:06:17.000Z","size":724,"stargazers_count":4,"open_issues_count":1,"forks_count":1,"subscribers_count":3,"default_branch":"1.x","last_synced_at":"2025-07-30T01:49:07.010Z","etag":null,"topics":["drupal","generate"],"latest_commit_sha":null,"homepage":"https://www.drupal.org/project/generated_content","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AlexSkrypnyk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"patreon":"alexskrypnyk"}},"created_at":"2022-06-09T11:11:16.000Z","updated_at":"2025-05-13T10:04:47.000Z","dependencies_parsed_at":"2023-12-15T12:31:17.953Z","dependency_job_id":"46493f37-c87b-4757-a67c-9ba1d3218f14","html_url":"https://github.com/AlexSkrypnyk/generated_content","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/AlexSkrypnyk/generated_content","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexSkrypnyk%2Fgenerated_content","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexSkrypnyk%2Fgenerated_content/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexSkrypnyk%2Fgenerated_content/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexSkrypnyk%2Fgenerated_content/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AlexSkrypnyk","download_url":"https://codeload.github.com/AlexSkrypnyk/generated_content/tar.gz/refs/heads/1.x","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexSkrypnyk%2Fgenerated_content/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268675515,"owners_count":24288285,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-04T02:00:09.867Z","response_time":79,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["drupal","generate"],"created_at":"2024-10-11T01:40:50.429Z","updated_at":"2025-08-04T09:32:35.125Z","avatar_url":"https://github.com/AlexSkrypnyk.png","language":"PHP","funding_links":["https://patreon.com/alexskrypnyk"],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"\" rel=\"noopener\"\u003e\n  \u003cimg width=200px height=200px src=\"https://placehold.jp/000000/ffffff/200x200.png?text=Generated+Content\u0026css=%7B%22border-radius%22%3A%22%20100px%22%7D\" alt=\"Generated Content\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eGenerated Content\u003c/h1\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n[![GitHub Issues](https://img.shields.io/github/issues/AlexSkrypnyk/generated_content.svg)](https://github.com/AlexSkrypnyk/generated_content/issues)\n[![GitHub Pull Requests](https://img.shields.io/github/issues-pr/AlexSkrypnyk/generated_content.svg)](https://github.com/AlexSkrypnyk/generated_content/pulls)\n[![CircleCI](https://circleci.com/gh/AlexSkrypnyk/generated_content.svg?style=shield)](https://circleci.com/gh/AlexSkrypnyk/generated_content)\n![GitHub release (latest by date)](https://img.shields.io/github/v/release/AlexSkrypnyk/generated_content)\n![LICENSE](https://img.shields.io/github/license/AlexSkrypnyk/generated_content)\n![Renovate](https://img.shields.io/badge/renovate-enabled-green?logo=renovatebot)\n\n![Drupal 9](https://img.shields.io/badge/Drupal-9-blue.svg)\n![Drupal 10](https://img.shields.io/badge/Drupal-10-009CDE.svg)\n![Drupal 11](https://img.shields.io/badge/Drupal-11-006AA9.svg)\n\n\u003c/div\u003e\n\nDrupal.org module page: https://www.drupal.org/project/generated_content\n\n## User stories\n\n    As a site owner\n    I want to see generated content before I have content\n    So that I can see how my site looks\n\n    As a Drupal developer\n    I want to control what is put into generated content\n    So that I have control over what is being generated\n\n    As a Drupal developer\n    I want to have a list of pre-generated pages with URLs\n    So that I can use them for Visual Regression testing during site releases\n\n## Installation\n\n    composer require drupal/generated_content\n\n## How it works\n\n1. The module provides callbacks system to generate content entities within a\n   code of a custom module sitting in `generated_content/{entity_type}/{entity_bundle}.inc`.\n2. The module provides a helper (singleton) class to generate random and static\n   content. It also supports extending this class in your custom module to\n   enhance with your site-specific generation helpers.\n3. Generated content entities are tracked in the Repository so that they could\n   be referenced from other generated entities (e.g., generated Articles\n   using generated Tags).\n4. Content can be generated from UI `/admin/config/development/generated-content`\n   or through a Drush command `drush generated-content:create-content {entity_type} {bundle}`.\n5. Content can also be generated on module install if `GENERATED_CONTENT_CREATE`\n   environment variable is set to `1`.\n   Generation can be further filtered by specified types in `GENERATED_CONTENT_ITEMS`\n   environment variable as a comma-separated list of `{entity_type}-{bundle}`\n   values:\n\n       # Generate all items in my_module module when it is enabled.\n       GENERATED_CONTENT_CREATE=1 drush pm-enable my_module\n\n       # Generate only selected items in my_module module when it is enabled.\n       GENERATED_CONTENT_CREATE=1 GENERATED_CONTENT_ITEMS=media-image,taxonomy_term-tags,node-page drush pm-enable my_module\n\nSee test [example module 1](modules/generated_content_example1) and [test example module 2](modules/generated_content_example2) for extensive examples.\n\nSee [`generated_content.api.php`](generated_content.api.php) for API of callbacks system.\n\n## Difference with Devel Generate\n\nDevel Generate and Generated Content are two different tools for creating\ncontent in Drupal. Devel Generate is mainly used for generating random dummy\ncontent, users, and taxonomy terms for testing and development. It allows you to\nspecify how many and what types of entities to create, but the content is\nrandom.\n\nOn the other hand, Generated Content is for creating specific sets of content\nbased on predefined settings. It is useful for ensuring the same content is\nproduced each time, which is helpful for tasks like Visual Regression testing\nwhere consistency is key. Unlike Devel Generate, which is more about quick,\nrandom content, Generated Content is about having control and reproducibility\nfor structured content setups.\n\nGenerated Content does not provide any generators itself, but it allows you to\ncreate your own generators and provides a harness to run them.\n\n## Example to generate Tags\n\n```php\n\n\u003c?php\n\n/**\n * @file\n * Create generated Tags terms.\n */\n\nuse Drupal\\Core\\Link;\nuse Drupal\\generated_content\\Helpers\\GeneratedContentHelper;\nuse Drupal\\taxonomy\\Entity\\Term;\n\n/**\n * Implements hook_generated_content_create_ENTITY_TYPE_BUNDLE_weight().\n */\nfunction generated_content_example2_generated_content_create_taxonomy_term_tags_weight() {\n  return 12;\n}\n\n/**\n * Implements hook_generated_content_create_ENTITY_TYPE_BUNDLE_tracking().\n */\nfunction generated_content_example2_generated_content_create_taxonomy_term_tags_tracking() {\n  return TRUE;\n}\n\n/**\n * Implements hook_generated_content_create_ENTITY_TYPE_BUNDLE().\n */\nfunction generated_content_example2_generated_content_create_taxonomy_term_tags() {\n  // Total number of terms to create.\n  $total_terms_count = 10;\n\n  /** @var \\Drupal\\generated_content\\Helpers\\GeneratedContentHelper $helper */\n  $helper = GeneratedContentHelper::getInstance();\n\n  $terms = [];\n\n  for ($i = 0; $i \u003c $total_terms_count; $i++) {\n    // Create a term instance.\n    $term = Term::create([\n      'vid' =\u003e 'tags',\n      'name' =\u003e 'Generated term ' . ($i + 1),\n    ]);\n\n    // Save term instance.\n    $term-\u003esave();\n\n    // Track saved term instance to return.\n    $terms[] = $term;\n\n    // Log creation of this entity.\n    $helper::log(\n      'Created \"%s\" term \"%s\" [ID: %s] %s',\n      $term-\u003ebundle(),\n      $term-\u003etoLink()-\u003etoString(),\n      $term-\u003eid(),\n      Link::createFromRoute('Edit', 'entity.taxonomy_term.edit_form', ['taxonomy_term' =\u003e $term-\u003eid()])-\u003etoString()\n    );\n  }\n\n  // Return created term instances.\n  return $terms;\n}\n```\n\n## Generation helper\n\nGeneration helper class `GeneratedContentHelper` is a Singleton class which\nprovides:\n\n1. Random non-Drupal scalar values generation.\n2. Static non-Drupal scalar values generation.\n3. Random asset generator (files of different types).\n4. Static asset generator (files from pre-defined assets).\n5. Random Drupal entity values generation.\n6. Static Drupal entity values generation.\n\n### Extending generation helper\n\nSee example of class extension: [`modules/generated_content_example2/src/GeneratedContentExample2Helper.php`](modules/generated_content_example2/src/GeneratedContentExample2Helper.php)\n\nSee example of class usage: [`modules/generated_content_example2/generated_content/node/article.inc`](modules/generated_content_example2/generated_content/node/article.inc)\n\n## Random vs Static content\n\nSometimes, it is sufficient to simply populate entities with random content\nto make the site look \"not empty\". Depending on your deployment strategy (if\nyou are enabling content generation modules on every deployment on top of the\nfresh database), this may change the content on every deployment.\n\nHowever, there are times when all generated content can still be a \"placeholder\"\ncontent, but it should be \"static\" between deployments, so that all content and\nit's aliases would not change. This is specifically important for Visual\nRegression testing during a release: the tool can compare generated pages with\nknown aliases in 2 environments and report differences, if any.\n\n## Roadmap\n\n1. Add more random and static generators.\n2. Add tests for existing random and static generators.\n3. [Suggest yours](https://www.drupal.org/project/issues/generated_content).\n\n## Local development\n\nProvided that you have PHP installed locally, you can develop an extension using\nthe provided scripts.\n\n### Build\n\nRun `.devtools/build.sh` (or `ahoy build`\nif [Ahoy](https://github.com/ahoy-cli/ahoy) is installed) to start inbuilt PHP\nserver locally and run the same commands as in CI, plus installing a site and\nyour extension automatically.\n\n### Code linting\n\nRun tools individually (or `ahoy lint` to run all tools\nif [Ahoy](https://github.com/ahoy-cli/ahoy) is installed) to lint your code\naccording to\nthe [Drupal coding standards](https://www.drupal.org/docs/develop/standards).\n\n```\ncd build\n\nvendor/bin/phpcs\nvendor/bin/phpstan\nvendor/bin/rector --clear-cache --dry-run\nvendor/bin/twig-cs-fixer\n```\n\n- PHPCS config: [`phpcs.xml`](phpcs.xml)\n- PHPStan config: [`phpstan.neon`](phpstan.neon)\n- Rector config: [`rector.php`](rector.php)\n- Twig CS Fixer config: [`.twig-cs-fixer.php`](.twig-cs-fixer.php)\n- Patches can be applied to the dependencies: add a patch to the\n    `patches` section of `composer.json`. Local patches will be sourced from\n    the `patches` directory.\n\n### Tests\n\nRun tests individually with `cd build \u0026\u0026 ./vendor/bin/phpunit` (or `ahoy test`\nif [Ahoy](https://github.com/ahoy-cli/ahoy) is installed) to run all test for\nyour extension.\n\n### Browsing SQLite database\n\nTo browse the contents of created SQLite database\n(located at `/tmp/site_[EXTENSION_NAME].sqlite`),\nuse [DB Browser for SQLite](https://sqlitebrowser.org/).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexskrypnyk%2Fgenerated_content","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexskrypnyk%2Fgenerated_content","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexskrypnyk%2Fgenerated_content/lists"}