Code Monkey home page Code Monkey logo

wp-cli-fixtures's Introduction

wp-cli-fixtures

GitHub Workflow Status Packagist Downloads Packagist PHP Version Support

Inspired by Faker, this package provides an easy way to create massive and custom fake data for your WordPress installation. This package is based on nelmio/alice and fzaninotto/Faker. Please refer to these packages docs for advanced usage.

wp-cli-fixtures demo

WARNING: This package is mostly intented to be used for development purposes. Use it at your own risk, don't run it on a production database or make sure to back it up first.

Quick links: Install | Usage | Contribute

Install

wp package install [email protected]:nlemoine/wp-cli-fixtures.git

Requires PHP ^7.3.

Usage

Create fixtures

At the root of your project, create a fixtures.yml file (you can download it here):

#
# USERS
#
Hellonico\Fixtures\Entity\User:
  user{1..10}:
    user_login (unique): <username()> # '(unique)' is required
    user_pass: 123456
    user_email: <safeEmail()>
    user_url: <url()>
    user_registered: <dateTimeThisDecade()>
    first_name: <firstName()>
    last_name: <lastName()>
    description: <sentence()>
    role: <randomElement(['subscriber', 'editor'])>
    meta:
      phone_number: <phoneNumber()>
      address: <streetAddress()>
      zip: <postcode()>
      city: <city()>
    acf:
      facebook_url: <url()>
      twitter_url: <url()>

#
# ATTACHMENTS
#
Hellonico\Fixtures\Entity\Attachment:
  default (template): # templates can be extended to keep things DRY
    post_title: <words(2, true)>
    post_date: <dateTimeThisDecade()>
    post_content: <paragraphs(5, true)>
  images{1..15} (extends default):
    file: <image(<uploadDir()>, 1200, 1200, 'cats')> # <uploadDir()> is required, image() is the default faker provider and gets images from lorempixel.
  pics{1..15} (extends default):
    file: <picsum(<uploadDir()>, 1200, 1200)> # Alternatively we provide a picsum() provider which uses picsum for images. It's quicker but doesn't support image categories.
  documents{1..2} (extends default):
    file: <fileIn('relative/path/to/pdfs')>
  custom_images{1..10} (extends default):
    file: <fileIn('relative/path/to/images')>

#
# TERMS
#
Hellonico\Fixtures\Entity\Term:
  category{1..10}:
    name (unique): <words(2, true)> # '(unique)' is required
    description: <sentence()>
    parent: '50%? <termId(childless=1)>' # 50% of created categories will have a top level parent category
    taxonomy: 'category' # could be skipped, default to 'category'
  tag{1..40}:
    name (unique): <words(2, true)> # '(unique)' is required
    description: <sentence()>
    taxonomy: post_tag
  places{1..4}: # custom taxonomy
    name (unique): <words(2, true)> # '(unique)' is required
    description: <sentences(3, true)>
    taxonomy: place
    acf:
      address: <streetAddress>
      zip: <postcode()>
      city: <city()>
      image: '@custom_images*->ID'

#
# POSTS
#
Hellonico\Fixtures\Entity\Post:

  # TEMPLATE
  default (template):
    post_title: <words(2, true)>
    post_date: <dateTimeThisDecade()>
    post_content: <paragraphs(5, true)>
    post_excerpt: <paragraphs(1, true)>
    meta:
      _thumbnail_id: '@attachment*->ID'

  # POSTS
  post{1..30} (extends default):
    # 'meta' and 'meta_input' are basically the same, you can use one or both,
    # they will be merged, just don't provide the same keys in each definition
    meta:
      _thumbnail_id: '@attachment*->ID'
    meta_input:
      _extra_field: <paragraphs(1, true)>
    post_category: '3x @category*->term_id' # post_category only accepts IDs
    tax_input:
      post_tag: '5x @tag*->term_id'
      # post_tag: '5x <words(2, true)> # Or tags can be dynamically created

  # PAGES
  page{contact, privacy}:
    post_title: <current()>
    post_type: page

  # CUSTOM POST TYPE
  product{1..15}:
    post_type: product
    acf:
      # number field
      price: <numberBetween(10, 200)>
      # gallery field
      gallery: '3x @attachment*->ID'
      # oembed field
      video: https://www.youtube.com/watch?v=E90_aL870ao
      # link field
      link:
        url: https://www.youtube.com/watch?v=E90_aL870ao
        title: <words(2, true)>
        target: _blank
      # repeater field
      features:
        - label: <words(2, true)>
          value: <sentence()>
        - label: <words(2, true)>
          value: <sentence()>
        - label: <words(2, true)>
          value: <sentence()>
      # layout field
      blocks:
        - acf_fc_layout: text_image
          title: <words(4, true)>
          content: <sentences(8, true)>
          image: '@attachment*->ID'
        - acf_fc_layout: image_image
          image_left: '@attachment*->ID'
          image_right: '@attachment*->ID'

#
# COMMENTS
#
Hellonico\Fixtures\Entity\Comment:
  comment{1..50}:
    comment_post_ID: '@post*->ID'
    user_id: '@user*->ID'
    comment_date: <dateTimeThisDecade()>
    comment_author: <username()>
    comment_author_email: <safeEmail()>
    comment_author_url: <url()>
    comment_content: <paragraphs(2, true)>
    comment_agent: <userAgent()>
    comment_author_IP: <ipv4()>
    comment_approved: 1
    comment_karma: <numberBetween(1, 100)>
    # 'meta' and 'comment_meta' are basically the same, you can use one or both,
    # they will be merged, just don't provide the same keys in each definition
    comment_meta:
      some_key: <sentence()>
    meta:
      another_key: <sentence()>

#
#  NAV MENUS
#
Hellonico\Fixtures\Entity\NavMenu:
  header:
    name: header
    locations:
      - header
      - footer

#
#  NAV MENUS ITEMS
#
Hellonico\Fixtures\Entity\NavMenuItem:
  custom_menu:
    menu_item_url: <url()>
    menu_item_title: <words(4, true)>
    menu_id: '@header->term_id'
  categories{1..3}:
    menu_item_object: '@category*'
    menu_id: '@header->term_id'
  posts{1..3}:
    menu_item_object: '@post*'
    menu_id: '@header->term_id'
  page:
    menu_item_object: '@page*'
    menu_id: '@header->term_id'

The example above will generate:

  • 10 users
  • 15 attachments
  • 10 categories
  • 40 tags
  • 30 posts with a thumbnail, 3 categories and 5 tags
  • 10 pages
  • 15 custom post types named 'product'
  • 50 comments associated with post and user
  • 1 nav menu
  • 6 nav menu items

IMPORTANT: Make sure referenced IDs are placed BEFORE they are used.

Example: Term or Attachment objects must be placed before Post if you're referencing them in your fixtures.

Load fixtures

wp fixtures load

You can also specify a custom file by using the --file argument:

wp fixtures load --file=data.yml

Delete fixtures

wp fixtures delete

You also can delete a single fixture type:

wp fixtures delete post

Valid types are post, attachment, comment, term, user.

Add fake data to existing content

wp-cli-fixtures allows you to add/update content to existing entities by passing the ID as a constructor argument.

Add/update data to post ID 1:

Hellonico\Fixtures\Entity\Post:
  my_post:
    __construct: [1] # Pass your post ID as the constructor argument
    post_title: '<sentence()>'
    post_content: '<paragraphs(5, true)>'
    post_excerpt: '<paragraphs(1, true)>'

Add/update data to 10 random existing posts:

Hellonico\Fixtures\Entity\Post:
  post{1..10}:
    __construct: [<postId()>] # Use a custom formatters to return a random post ID as the constructor argument
    post_title: '<sentence()>'
    post_content: '<paragraphs(5, true)>'
    post_excerpt: '<paragraphs(1, true)>'

Entities

Post

Hellonico\Fixtures\Entity\Post can take any parameters available in wp_insert_post + meta and acf key.

Note: post_date_gmt and post_modified_gmt have been disabled, there are set from post_date and post_modified.

Attachment

Hellonico\Fixtures\Entity\Attachment can take any parameters available in wp_insert_attachment + meta, file and acf custom keys.

Note: parent must be passed with post_parent key.

Term

Hellonico\Fixtures\Entity\Term can take any parameters available in wp_insert_term + meta and acf custom keys.

Note: term and taxonomy must be respectively passed with name and taxonomy key.

User

Hellonico\Fixtures\Entity\User can take any parameters available in wp_insert_user + meta and acf custom keys.

Comment

Hellonico\Fixtures\Entity\Comment can take any parameters available in wp_insert_comment + meta custom key.

comment_date_gmt has been disabled, it is set from comment_date.

Nav menu

Hellonico\Fixtures\Entity\NavMenu is a term just like Hellonico\Fixtures\Entity\Term. It takes an addiotional locations parameter to set the menu location.

Hellonico\Fixtures\Entity\NavMenu:
  header:
    name: header
    locations:
      - header

Nav menu item

Hellonico\Fixtures\Entity\NavMenuItem takes the same parameters as $menu_item_data in wp_update_nav_menu_item

Note 1: replace dashes with underscore in keys (e.g. menu-item-object becomes menu_item_object).

Note 2: menu-item-object can also accept an entity object, if so, menu-item-type and menu-item-object-id will be filled automatically with appropriate values

ACF Support

Each ACF supported entity (post, term, user) can have an acf key, which works just like meta.

Hellonico\Fixtures\Entity\Post:
  post{1..30}:
    post_title: <words(3, true)>
    post_date: <dateTimeThisDecade()>
    acf:
      # number field
      number: <numberBetween(10, 200)>
      # repeater field
      features:
        - label: <words(2, true)>
          value: <sentence()
        - label: <words(2, true)>
          value: <sentence()>
        - label: <words(2, true)>
          value: <sentence()>

Be careful with duplicate field keys, if you have multiple field with the same key, prefer using ACF field key (field_948d1qj5mn4d3).

Custom formatters

In addition to formatters provided by fzaninotto/Faker, you can use custom formatters below.

postId($args)

Returns a random existing post ID. $args is optional and can take any arguments from get_posts

Example:

<postId(category=1,2,3)>

attachmentId($args)

Returns a random existing attachment ID. $args is optional and can take any arguments from get_posts

Example:

<attachmentId(year=2016)>

termId($args)

Returns a random existing term ID. $args is optional and can take any arguments from get_terms

Example:

<termId(taxonomy=post_tag)>

userId($args)

Returns a random existing user ID. $args is optional and can take any arguments from get_users

Example:

<userId(role=subscriber)>

fileContent($file)

Returns the content of a file.

Example:

<fileContent('path/to/file.html')>

fileIn($src, $target, false)

Wrapper around file provider because some Faker providers conflicts with PHP native . Returns file path or file name in a directory ($src relative to fixtures.yml).

Default target is the WordPress uploads.

Example:

<fileIn('my/set/of/images')>

Tips

While playing with fixtures, the database command package can be useful to reset database faster than wp fixtures delete and start over.

Contribute

This package follows PSR2 coding standards and is tested with Behat. Execute composer run test to ensure your PR passes.

You will need to run composer run prepare-tests before your first run.

wp-cli-fixtures's People

Contributors

dansmart-box avatar jphilung avatar nlemoine avatar vanwildemeerschbrent avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

wp-cli-fixtures's Issues

Translatable content and fixtures

Have you given any thought to how you might handle translations of fixtures?
For example how to handle fixtures on sites using WPML?

Given the following:

#
# TERMS
#
Hellonico\Fixtures\Entity\Term:
  focus_areas{1..4}: # custom taxonomy
    name (unique): <words(3, true)> # '(unique)' is required
    description: <sentences(1, true)>
    taxonomy: focus_area

#
# POSTS
#
Hellonico\Fixtures\Entity\Post:
  default (template):
    post_title: <words(2, true)>
    post_date: <dateTimeThisDecade()>
    post_content: <paragraphs(5, true)>
    post_excerpt: <paragraphs(1, true)>

  projects_with_focus_area_1_{1..5}:
      __construct: [<postId(post_type=projects&post_status=publish)>]
      tax_input:
        focus_area: '@focus_areas1->term_id'

I can relate the generated terms just fine to the existing posts, but the <postID()> function does not stick to fetching posts in the default language. It randomly fetches posts regardless of their language. Would you be interested in a fix for this?

I imagine checking if WPML is running, and if so, limit the post query to only fetch posts in the default language.

Feature request

Hi, first of all thank you for this awesome package.
My company is considering to adopt it for our local WP development and we'd like to have these features discussed:

  • a new Option entity. We heavily rely on the Advanced Custom Field plugin and while we can already easily set meta data for posts, users, and terms we would like to have the possibility to feed the wp_options table as well
  • the ability to keep pages when deleting posts. Usually when developing sites we always have a predetermined set of pages that should always exist. We would like to have a way to keep pages when deleting fake data and instead just delete their meta data and post_content

Picsum declaration incompatible

Hello, when I run wp fixtures load I am hitting the following error:

PHP Fatal error: Declaration of Hellonico\Fixtures\Provider\Picsum::imageUrl($width = 640, $height = 480, $filters = [], $format = 'jpg', $unused = false, $unused_ = false) must be compatible with Faker\Provider\Image::imageUrl($width = 640, $height = 480, $category = null, $randomize = true, $word = null, $gray = false, $format = 'png') in /var/www/html/sites/test/vendor/hellonico/wp-cli-fixtures/src/Provider/Picsum.php on line 19

Publish a new release?

It's been quite a while since you've published a new release (0.3.0...master) worth a 0.4.0?

We run wp package install hellonico/wp-cli-fixtures as part of our setup and would be good to be able to use wp package install hellonico/wp-cli-fixtures:@stable with the new features now in master.

Adding flexible content

Hi,

I have an ACF flexible content field to add "components", groups of acf fields, to a custom post type. All the fixtures I have made so far are working well. How would I add a flexible content field?

This is what I am trying so far:

Hellonico\Fixtures\Entity\Post:
    post{1..2}:
        post_type: 'blog'
        post_title (unique): '<words(4, true)>'
        post_date: '<dateTimeThisDecade()>'
        acf:
            byline: '<firstName()> <lastName()>'
            intro: '<words(20, true)>'
            add_image: 'true'
            featured_image:  '@featured_images*->ID'
            featured_image_alt_text: '<words(4, true)>'
            components:
                - 'text'
                - 'image'
            components_0_header: '<words(4, true)>'
            components_0_rich_text: <paragraphs(2, true)>
            components_0_add_image: 'true'
            components_0_image: '@pics*->ID'
            components_0_image_alt_text: '<words(4, true)>'
            components_0_placement: 'right'
            components_0_size: 'half'
            components_1_image: '@pics*->ID'
            components_1_image_alt_text: '<words(4, true)>'

and this is what a dump of the $post looks like:

  +ImageClass: "Timber\Image"
  +PostClass: "Timber\Post"
  +TermClass: "Timber\Term"
  +object_type: "post"
  +custom: array:32 [▼
    "_fake" => "1"
    "_wp_old_date" => "2021-10-28"
    "byline" => "Allison Runolfsson"
    "_byline" => "field_blog_byline"
    "intro" => "sed a nam et sint autem inventore aut officia aut aut blanditiis et ducimus eos odit amet et est ut"
    "_intro" => "field_blog_intro"
    "add_image" => "1"
    "_add_image" => "field_blog_add_image"
    "featured_image" => "76"
    "_featured_image" => "field_blog_featured_image"
    "featured_image_alt_text" => "nisi molestiae quidem ut"
    "_featured_image_alt_text" => "field_blog_featured_image_alt_text"
    "components" => array:2 [▼
      0 => "text"
      1 => "image"
    ]
    "_components" => "field_blog_components"
    "_edit_lock" => "1635428232:1"
    "_edit_last" => "1"
    "featured_image_caption" => ""
    "_featured_image_caption" => "field_blog_featured_image_caption"
    "components_0_header" => "header"
    "_components_0_header" => "field_blog_components_text_header"
    "components_0_hide_header" => "0"
    "_components_0_hide_header" => "field_blog_components_text_hide_header"
    "components_0_rich_text" => "rich text"
    "_components_0_rich_text" => "field_blog_components_text_rich_text"
    "components_0_add_image" => "0"
    "_components_0_add_image" => "field_blog_components_text_add_image"
    "components_1_image" => "76"
    "_components_1_image" => "field_blog_components_image_image"
    "components_1_image_alt_text" => "field"
    "_components_1_image_alt_text" => "field_blog_components_image_image_alt_text"
    "components_1_image_caption" => ""
    "_components_1_image_caption" => "field_blog_components_image_image_caption"
  ]```

Any guidance would be appreciated.

Feature Request: Delete content added to existing posts

Example use case:
Say I have an existing post, and I add a new ACF field to it.
I then populate the new field with fixtures during development.
Prior to deploying the new field, I remove the fixtures for the new field.

Would this be possible?

How to use before value in Yaml file

Please See this yml File:

Hellonico\Fixtures\Entity\User:
  user{1..10}:
    user_login (unique): <username()> # '(unique)' is required
    user_pass: 123
    user_email: <freeEmail()>
    user_url: <url()>
    user_registered: <dateTimeThisDecade()>
    first_name: <firstName()>
    last_name: <lastName()>
    description: <sentence()>
    role: <randomElement(['subscriber', 'editor'])>
    meta:
      show_admin_bar_front: 'false'
      billing_phone: <phoneNumber()>
      billing_country: 'IR'
      billing_state: <randomElement(['ABZ','ADL','EAZ','WAZ','BHR','CHB','FRS','GIL','GLS','HDN','HRZ','ILM','ESF','KRN','KRH','NKH','RKH','SKH','KHZ','KBD','KRD','LRS','MKZ','MZN','GZN','QHM','SMN','SBN','THR','YZD','ZJN'])>
      billing_city: <city()>
      billing_address_1: <streetAddress()>
      billing_postcode: <postcode()>
      billing_email: <freeEmail()>
      billing_first_name: <firstName()>
      billing_last_name: <lastName()>

I want to billing_first_name = first_name when creating this user in any loop?

Problem 2

#
# POSTS
#
Hellonico\Fixtures\Entity\Post:

  # TEMPLATE
  defaultpost (template):
    post_title: <words(5, true)>
    post_date: <dateTimeThisDecade()>
    post_content: <paragraphs(5, true)>
    post_excerpt: <paragraphs(1, true)>

  # CUSTOM POST TYPE
  product{1..15} (extends defaultpost):
    post_type: product
    meta:
      _thumbnail_id: '@custom_images*->ID'
    meta_input:
      _sku: <numberBetween(1000, 2000)>
      _regular_price: <numberBetween(10000, 20000)>
      _price: <numberBetween(10000, 20000)>
      _sale_price: <numberBetween(10000, 20000)>
      _stock_status: 'instock'
      _manage_stock: 'yes'
      _stock: <numberBetween(1, 10)>

I Want to _sale_price = _price. how to use before value in YAML?

thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.