PRO: Generate Custom Post, Custom Post Fields, Taxonomies with Twig and JSON

Howto create and update Custom Posts out of JSON

You can create “Custom Post Pages” out of “Custom Post Types” and JSON by putting together a Shortcode: This is described here: Shortcode for creating Custom Post Pages out of Custom Post Types out of JSON.
Here we do it in another way: The big advantage is the easier and flexible way to update Custom Pages, avoiding complex Shortcode-Building. The “disadvantage” of having all under control:  This is a “programming way” to do that.

Step 1: Create a Custom Post Type (=CPT)

You can create CPTs in many ways. In this example we use the free Plugin “Custom Post Type UI“.
With that plugin we create a CPT with slug (=”Singular Label”) “meetup”., which is connected to the Taxonomy with slug (=”Singular Label”) “meeetuptax”.
And with Advanced Custom Fields (ACF) we add the Custom Post Fields (CPF) with slug “nameofevent”, “statusofevent” and “venueofevent” as simple text. And “dateofevent” as “Date Picker”.

The result of this: You should have a CPT “meeetup” in the menu. If you add one you can add content, CPF and a Taxonomy. For further details see the manual of the two plugins “Custom Post Type UI” and ACF used (this step is completely without JCI). “Pods” and “Toolset” are two other Plugins also very good for creating CPT.

Step 2: Create a new page as blueprint for all meetup-pages

The pagetitle, URL etc. of the to be created pages will be defined in the JCI-template. But what about the design of the page?
Create a page for that and put some placeholders for JSON-data into it. This can be a “ordinary” page or even an Elementor-Page.
Here we use https://api.json-content-importer.com/generate-meetup-blueprint/ where only the “Content” is of interest. The placeholders “##…##” will be replaced by JSON-data.
What we need here for doing this is the pageID of this page: Here this is “10912”.

Step 3: Create a JCI-Template which is using the JSON to create Custom Pages, CPF and entries in the Taxonomy

The JSON we use in this example is https://api.json-content-importer.com/extra/json/meetup/create-cpt.json, a list of several events.
Create a new JCI-template:
URL: See above
Name of template: “generate-meetup”
twig-template:

{% set contentmasterpageid = 10912 %} {# pageID of blueprint-page #}
{% set masterprop = wp_get_page_properties(FALSE, contentmasterpageid) %}
{# masterprop:  {{ masterprop.get_post.ID }} #}
{% set mastercontent =  masterprop.get_post.post_content %}
{#  mastercontent: {{masterprop | json_encode | htmlentities }} <hr> #}

{% set cpt_slug = 'meetup' %} {# slug of CPT #}
{% set taxonomyslug = 'meetuptax' %}

{# each CustomPostPage (CPP) createad out of the CustomPostType (CPT) gets a CustomPostField (CPF) with a key:value pair this pair identifies all CPP created by this script  #}
{% set cpt_cpfkey = "cptidentifier" %} 
{% set cpt_cpfval = "uniqueidentifierforallpages" %}

{# delete all previous created pages - if needed #}
{% if FALSE %} {# switch on / off deleteing CPP by setting to TRUE or FALSE #}
    {# get all CPP from that CPT with the key:value pair #}
    {% set getallcreatedpages = wp_get_cp_by_cpf_keyvalue(cpt_slug, cpt_cpfkey, cpt_cpfval) %}
    {% for crpg in getallcreatedpages %}
        {% set delflag = wp_delete_custom_post(crpg) %}
    {% endfor %}
    all {{getallcreatedpages | length }} old pages deleted<hr>
{% endif %}

{# we need to build a list of all pageIDs which are created with the current JSON. later we also get a list of pageIDs created with previous JSON. If there is a pageID, which is not in the current JSON we delete it #}
{% set list_of_pageIDs_out_of_json = [] %}

{% for f in _context %}
    {% if f.name %} {# check if the JSON-item is one to create a CPP #}
        name: {{f.name}} - id: {{f.id}} -
        {% set title = f.name ~ ' ' ~ (f.local_date | date("d.m.Y")) %}
        {% set pageslug = title ~ ' ' ~ f.local_date  %}

        {# set content: replace the placeholders with JSON-data #}
        {% set content = mastercontent %}
        {% set content = ( content | preg_replace("/##description##/i", f.description)) %} 
        {% set content = ( content | preg_replace("/##date##/i", f.local_date)) %} 
        {% set content = ( content | preg_replace("/##venue##/i", f.venue.id)) %} 

        {% set excerpt = "this is excerpt" %}
        {% set publishdate = ("now" | date("d.m.Y")) %} {# mind the us- (month-day-year) and eu- (day-month-year) date-formatting #}
        {% set postStatusUsed = "draft" %} {# publish, future, draft, pending, private #}
        {% set authorid = "" %}
        {% set debug = FALSE %}

        {# set the CPF values #}
        {% set cpf_nameofevent = f.name %}
        {% set cpf_statusofevent = f.status %}
        {% set cpf_dateofevent = f.local_date %} {# mind the us- (month-day-year) and eu- (day-month-year) date-formatting #}
        {% set cpf_venueofevent = f.venue.id %}
        {% set taxonomyValue = 'tax-' ~ f.status %}

        {# if any of the JSON-data of updatehash changes, the md5-hash changes. this hash is also added to the CPP: in case of update we check if an update is really needed or not. #}
        {% set updatehash = ((contentmasterpageid ~ f.name ~ f.local_date ~ content ~ cpf_statusofevent ~ cpf_dateofevent ~ cpf_venueofevent) | md5) %}

        {# each data-items has to have an unique id as identifier: each CPP also has a key:value pair with this id with that we can check, if a data-item already has it's CPP (then update the CPP, othereise create a CPP) #}
        {% set checkidentifier = wp_get_cp_by_cpf_keyvalue(cpt_slug, "identifier", f.id) %}
        {% if checkidentifier %}
            {# update #}
            {% set pageid_to_be_updated = checkidentifier.0 %} {# pageID found for update #}
            pageID for Update: {{pageid_to_be_updated}} - 
            {% set list_of_pageIDs_out_of_json = list_of_pageIDs_out_of_json | merge([pageid_to_be_updated]) %}
            {% set storedupdatehash = wp_get_custom_field_value(pageid_to_be_updated, "updatehash") %}
            {% if storedupdatehash.0==updatehash %}  
                no update needed - 
            {% else %} 
                do update - 
                {% set update = wp_update_custom_post(pageid_to_be_updated, title, pageslug, content, excerpt, publishdate, postStatusUsed, authorid, debug) %}
                {% set tax = wp_insert_taxonomy(pageid_to_be_updated, taxonomyslug, taxonomyValue) %}
                {# update CPF #}            
                {% set newcpf = wp_insert_custom_field_keyvalue(pageid_to_be_updated, "nameofevent", cpf_nameofevent) %}
                {% set newcpf = wp_insert_custom_field_keyvalue(pageid_to_be_updated, "statusofevent", cpf_statusofevent) %}
                {% set newcpf = wp_insert_custom_field_keyvalue(pageid_to_be_updated, "dateofevent", cpf_dateofevent) %}
                {% set newcpf = wp_insert_custom_field_keyvalue(pageid_to_be_updated, "venueofevent", cpf_venueofevent) %}
                {# update updatehash #}
                {% set updateinfo = wp_insert_custom_field_keyvalue(pageid_to_be_updated, "updatehash", updatehash) %}
            {% endif %}
        {% else %} 
            {# create  #}
            {% set newpageid = wp_new_custom_post(cpt_slug, title, pageslug, content, excerpt, publishdate, postStatusUsed, authorid, debug) %}
            new CPP created: {{newpageid}} -
            {% set list_of_pageIDs_out_of_json = list_of_pageIDs_out_of_json | merge([newpageid]) %}
            {# set the cPF to identify the CPP #}
            {% set cpf = wp_insert_custom_field_keyvalue(newpageid, cpt_cpfkey, cpt_cpfval) %}
            {% set cpfidenbtifier = wp_insert_custom_field_keyvalue(newpageid, "identifier", f.id) %}
            {% set updateinfo = wp_insert_custom_field_keyvalue(newpageid, "updatehash", updatehash) %}

            {# insert taxonomy #}            
            {% set tax = wp_insert_taxonomy(newpageid, taxonomyslug, taxonomyValue) %}
            {# insert CPF #}            
            {% set newcpf = wp_insert_custom_field_keyvalue(newpageid, "nameofevent", cpf_nameofevent) %}
            {% set newcpf = wp_insert_custom_field_keyvalue(newpageid, "statusofevent", cpf_statusofevent) %}
            {% set newcpf = wp_insert_custom_field_keyvalue(newpageid, "dateofevent", cpf_dateofevent) %}
            {% set newcpf = wp_insert_custom_field_keyvalue(newpageid, "venueofevent", cpf_venueofevent) %}
        {% endif %}
        <br>
    {% endif %}
{% endfor %}
{# <hr>list_of_pageIDs_out_of_json: {{list_of_pageIDs_out_of_json | json_encode }}#}

{# get all pageIDs of the CPT #} 
{% set getallcreatedpages = wp_get_cp_by_cpf_keyvalue(cpt_slug, cpt_cpfkey, cpt_cpfval) %}
{# <hr>getallcreatedpages: {{getallcreatedpages | json_encode }} #}
{# loop through all existing pages: if one is not in the JSON delete it #}
{% for existingPage in getallcreatedpages %}
    {# existingPage: {{existingPage}} - #}
    {% if existingPage in list_of_pageIDs_out_of_json %}  
        {# ok #}
    {% else %} 
        delete {{existingPage}}<br>
        {# not ok: this pageID is not in the current JSON #}
        {% set delflag = wp_delete_custom_post(existingPage) %}
    {% endif %}
{% endfor %}

The above code is doing this:

  • Load the blueprint-content
  • Set the parameter for the CPT (and a unique “uniqueidentifierforallpages” – change that if you generate more than 1 pages in this way).
  • Optional: delete all existing pages of that type
  • Loop through JSON and create or update the pages incl. adding CPF and Taxonomy.
  • Check and delete previously created pages, which are not in the current JSON any more.

Remarks:

  • If you use a CPT created by Toolset add “wpcf-” to the CPF-slug

Step 4: Use the JCI-Template and create the Custom Pages

Then you can use the following Shortcode on a WP-Page:

[[jsoncontentimporterpro nameoftemplate="generate-meetup"]]

When executing this Shortcode you should get 8 Custom Posts in the Menu for “meetup”.
Executing again tells you, that all 8 pages are already there.
You can run auto-updates with the Plugin GetURLCron.