Practitioner-plugin (WordPress)
De Practitioner-plugin is een maatwerk-plugin die eind 2017 is ontwikkeld voor een specifiek project. Het betreft een CPT - Custom Post Type. De achterliggende principes zijn echter vrij universeel, vandaar deze documentatie: Hoe maak je gebruik van CPT's?
Onderdelen
Er komt nogal wat bij kijken:
- Plugin zelf
- Child-theme van het gebruikte theme Hoshi
- Advanced Custom Fields PRO-plugin
- CPT-objectdefinitie (JSON- of PHP-bestand)
- Ingevoerde data.
Deployment
Voorbeeld: Hoe migreer je de plugin naar een nieuwe locatie?
Bronlocatie
Doellocatie
|
Database-model
Tabel wp_posts - Publish-record
De belangrijkste tabel is wp_posts
. Hier worden per posting twee records aangemaakt. Het belangrijkste van de twee, is vermoedelijk het publish-record. Een impressie:
- ID - Dit is de primaire sleutel (bigint). Ik geloof dat-ie niet automatisch telt
- Date- & timestamp
- post_content: Wordt niet gebruikt
- post_title: Titel van het practitioner-record
- post_status: Published
- comment_status: Closed - In dit geval
- ping_status: Closed - In dit geval
- post_password: Leeg
- post_name: Gegenereerd door AFC. Wordt waarschijnlijk gebruikt voor de (interne?) URL
- post_parent: 0
- guid. Bv.
http://bsp.dvb/?post_type=practitioners&p=797
. De escape-string staat voor het '&'-symbool. Herschreven geeft dithttp://bsp.dvb/?post_type=practitioners&p=797
- Dus de practitioner met ID 797 (ofzo). Dit is inderdaad de waarde van het ID-veld - post_type:
practitioners
.
Tabel wp_posts - Revision-record
- post_status:
inherit
- post_name:
797-revision-1
- guid:
http://bsp.dvb/797-revision-v1/
- post_type:
revision
Export van data
- Ik weet niet hoe je CPT-gegevens gemakkelijk kunt exporteren - Ik heb het nog niet nodig gehad
- Op database-niveau is dit in ieder geval flink wat werk, omdat de data verspreid staat over twee tabellen, in meerdere velden.
Importeren
Hoe importeer je practitioners vanaf een externe bron (bv. tekstbestand of db) naar de betreffende WordPress-site? De twee aangewezen manieren zijn via plugins en via API-toegang. Maar er zijn meer mogelijkheden.
Mocht er een programmeertaal aan te pas komen, dan graag Python, en geen PHP.
Import-plugins
Import-plugins, zoals Ultimtate CSV Importer (zie hieronder - Geen succes)
Op db-niveau
In oktober 2018 heb ik ca. twee uurtjes besteed om de import helemaal zelf op db-niveau te doen. Na die twee uurtjes gestopt: Ongetwijfeld kan ik dit voor elkaar krijgen, maar het kost gewoon te veel tijd om dit goed te doen: Je moet aan allerlei dingen denken, die anders de API voor je doet.
PHP WPDB-klasse
PHP wpdb
-klasse [1] - Da's toegang op een lager niveau dan via een API. Dat sprak me aan, omdat ik geen zin heb om de API te leren gebruiken. Maar ik heb nog minder zin om PHP te leren programmeren.
API
Zie artikel WordPress API's en ihb. Database-API voor 'native' mogelijkheden. Dus allemaal in PHP
API - Python
Er zijn diverse manieren om API-toegang vanuit PHP te doen. Zo bestaat er een wrapper, maar die is niet compleet en alleen beschikbaar voor core en WooCommerce - Tricky.
API - XML-RPC
WordPress kent een XML-RPC-API. Da's programmeertaal-onafhankelijk, dus het kan ook in Python. Het werkt universeel, maar heeft beperkingen (je kunt bv. geen taxonomieën schrijvven) ⇒ Zie verderop in dit artikel.
Casus: Import mbv. Ultimate CSV Importer (zomer 2018)
- Dit heeft gewerkt, al was er wel een bug: Als ik alle velden 'gewoon' invulde, kreeg ik een offset-foutmelding (zie verderop). Ik geloof dat als ik een bepaald veld leegliet, het wel goed ging
- In de herfst van 2018, kon ik dit helaas niet hercreëren: Nu werden alleen de eerste letters van velden geïmporteerd + vage foutmeldingen.
Deze aanpak heb ik in de herfst van 2018 opgegeven: Het werkte niet en is om te kunnen werken, afhankelijk van diverse externe factoren (ihb.: deze plugin icm. met die advanced-nog-wat-plugin) die nog geld kosten ook → Zelf op db-niveau doen.
Opmaak importbestand
Dit betreft export vanuit LibreOffice Calc. Ongetwijfeld zijn er meer geldige mogelijkheden, maar dit werkt in ieder geval:
- UTF-8
- Tab-gescheiden of komma-gescheiden
- Alle velden omsloten met dubbele aanhalingstekens, of juist niet
Twee voorbeelden:
"Title" "firstname" "lastname" "description_short" "description_long" "city" "province" "website" "photo" "Jan1 Jan1 Achternaam" "Jan1" "Jan1 Achternaam" "Jan1 korte omschrijving" "Jan1 lange omschrijving" "Jan1 – Plaats" "Jan1 – Provincie" "Jan1 – Site" "Jan2 Jan2 Achternaam" "Jan2" "Jan2 Achternaam" "Jan2 korte omschrijving" "Jan2 lange omschrijving" "Jan2 – Plaats" "Jan2 – Provincie" "Jan2 – Site" "Jan3 Jan3 Achternaam" "Jan3" "Jan3 Achternaam" "Jan3 korte omschrijving" "Jan3 lange omschrijving" "Jan3 – Plaats" "Jan3 – Provincie" "Jan3 – Site"
en
Title firstname lastname description_short description_long city province website photo Jan1 Jan1 Achternaam Jan1 Jan1 Achternaam Jan1 korte omschrijving Jan1 lange omschrijving Jan1 – Plaats Jan1 – Provincie Jan1 – Site Jan2 Jan2 Achternaam Jan2 Jan2 Achternaam Jan2 korte omschrijving Jan2 lange omschrijving Jan2 – Plaats Jan2 – Provincie Jan2 – Site Jan3 Jan3 Achternaam Jan3 Jan3 Achternaam Jan3 korte omschrijving Jan3 lange omschrijving Jan3 – Plaats Jan3 – Provincie Jan3 – Site
Mapping - WordPress-velden
Cruciaal dat de kolom Title van een waarde is voorzien. Overige velden kun je negeren. Icm. de voorbeeldbestanden hierboven:
WP CSV ----------------- ----------------- Title Title Content -- Short Description --
Mapping - WordPress-WordPress Custom Fields
Dit zijn de velden die daadwerkelijk gebruikt worden.
WP CSV ----------------- ----------------- practitioner Title practitioner_city city practitioner_description_long description_long practitioner_description_short description_short practitioner_firstname firstname practitioner_lastname lastname practitioner_province province practitioner_website website
Image?
Geen idee.
Bug: Illegal string offset-error (zomer 2018)
Na import krijg ik bij alle velden (behalve titel) een illegal string offset-foutmelding:
- Alleen het naam-veld importeren (dus het enige verplichte niet-custom-veld): Gaat goed
- Naam-veld + customt naam-veld importeren: Foutmelding.
Casus: XML-RPC (okt. 2018)
Deze code maakt één record aan. Zie XML-RPC, WordPress & Python voor details:
#! /usr/bin/python ##################################################################################### # print(">>> 01.py") ##################################################################################### # Import libraties ##################################################################################### from wordpress_xmlrpc import Client, WordPressPost from wordpress_xmlrpc.methods.posts import GetPosts, NewPost from wordpress_xmlrpc.methods.users import GetUserInfo ##################################################################################### # Instantiate object ##################################################################################### # wp = Client('http://example.com/xmlrpc.php', 'xxx', 'yyy') ##################################################################################### # Create custom post type ##################################################################################### # # Initial stuff ############################## # practitioner = WordPressPost() practitioner.post_type = "practitioners" practitioner.title = "New practitioner (6)" practitioner.custom_fields = [] # Initialise custom fields ############################## # # All, except image # practitioner.custom_fields.append({ 'key': 'practitioner_firstname', 'value': 'firstname_01' }) practitioner.custom_fields.append({ 'key': 'practitioner_lastname', 'value': 'lastname_01' }) practitioner.custom_fields.append({ 'key': 'practitioner_description_short', 'value': 'descr_short_01' }) practitioner.custom_fields.append({ 'key': 'practitioner_description_long', 'value': 'descr_long_01' }) practitioner.custom_fields.append({ 'key': 'practitioner_city', 'value': 'city_01' }) practitioner.custom_fields.append({ 'key': 'practitioner_province', 'value': 'province_01' }) practitioner.custom_fields.append({ 'key': 'practitioner_website', 'value': 'site_01' }) wp.call(NewPost(practitioner)) ##################################################################################### # print("<<< 01.py")
Storing: Content verschijnt pas na edit (eind 2018)
Probleem
Importeren is gelukt, maar de content wordt pas getoond als ik opnieuw Edit » Publish kies. Dat probleem is onafhankelijk van de wijze van impoteren. Het betreft zowel de pagina van individuele practitioners, als de archiefpagina met alle practitioners
Aanvullende gegevens
- Een eventuele storing met aanmaken permalink [2] lijkt niet het geval te zijn: Na edit/publish verandert de permalink niet, en het probleem speelt ook voor de archiefpagina, en daar spelen permalinks geen rol, lijkt me. Aanpassen en weer terug-aanpassen van de permalink-settings, maakt geen verschil
- Ik kon geen cash oid. vinden, die ik anders zou kunnen doorspoelen
- WordFence-issue [3]: Maakt geen verschil + ligt niet voor de hand
- In bulk postings aanpassen, werkt niet. Alleen als ik het één-voor-één doe.
Unregister CPT-definitie? (feb. 2019)
Een site met deze plugin heb ik geklooned. In de nieuwe site heb ik geen Practitioner-objecten nodig. Als ik Advanced Custom Fields PRO verwijder, blijft het Practitioners-object in het menu staan, en de content blijft ook behouden. Hoe verwijder ik deze?
- Trash herhaaldelijk leegmaken: Nu is allle Practitioner-gerelateerde data verdwenen uit tabel
wp_postmeta
- Entiteit is er nog steeds - Custom Post Type Cleanup-plugin geïnstalleerd. Deze heeft 9 objecten verwijderd, maar het item in het linkermenu staat er nog steeds.
- Op db-niveau wp_posts, wp_postmeta en wp_term_relationships opschonen [4]:
delete from example_com.wp_posts where post_type like "practitioners"; delete from example_com.wp_postmeta where post_id not in (select id from wp_posts); DELETE FROM wp_term_relationships WHERE object_id NOT IN (SELECT id FROM wp_posts);
Een paar items zijn verwijderd, maar niet het item in het linkermenu.
Gelukt: Zie laatste afbeelding hiernaast (verwijzing naar php-bestand met objectdefinitie).
Zie ook
Bronnen
Content verschijnt pas na edit/publish
- https://premium.wpmudev.org/forums/topic/published-content-is-not-visible-until-open-again-and-update-it - Identieke probleem
- https://wordpress.stackexchange.com/questions/294575/how-to-force-update-all-posts-after-import
- https://wordpress.stackexchange.com/questions/185776/live-site-do-not-update-after-importing-sql-database
- https://wordpress.stackexchange.com/questions/221958/force-update-all-posts-in-custom-post-type-no-content-changes?rq=1
- https://wordpress.stackexchange.com/questions/177021/how-can-i-bulk-update-all-posts-without-making-changes?noredirect=1&lq=1
Unregistering CPT
Appendix: CPT-objectdefinitie
Het betreffende field group-exportbestand vanuit de Advanced Custom Fields PRO-plugin:
[ { "key": "group_5a44d8e93187a", "title": "Practitioners", "fields": [ { "key": "field_5a44db1c303ab", "label": "Practitioner", "name": "practitioner", "type": "group", "instructions": "", "required": 0, "conditional_logic": 0, "wrapper": { "width": "", "class": "", "id": "" }, "layout": "block", "sub_fields": [ { "key": "field_5a44d90110811", "label": "Firstname", "name": "firstname", "type": "text", "instructions": "", "required": 0, "conditional_logic": 0, "wrapper": { "width": "50", "class": "", "id": "" }, "default_value": "", "placeholder": "", "prepend": "", "append": "", "maxlength": "" }, { "key": "field_5a44da3910812", "label": "Lastname", "name": "lastname", "type": "text", "instructions": "", "required": 0, "conditional_logic": 0, "wrapper": { "width": "50", "class": "", "id": "" }, "default_value": "", "placeholder": "", "prepend": "", "append": "", "maxlength": "" }, { "key": "field_5a44da5110813", "label": "Description (short)", "name": "description_short", "type": "textarea", "instructions": "Displayed in the Overview\/table", "required": 0, "conditional_logic": 0, "wrapper": { "width": "", "class": "", "id": "" }, "default_value": "", "placeholder": "", "maxlength": "", "rows": "", "new_lines": "" }, { "key": "field_5a44da70303a6", "label": "Description (long)", "name": "description_long", "type": "wysiwyg", "instructions": "Displayed on the single page", "required": 0, "conditional_logic": 0, "wrapper": { "width": "", "class": "", "id": "" }, "default_value": "", "tabs": "all", "toolbar": "full", "media_upload": 1, "delay": 0 }, { "key": "field_5a44daaa303a7", "label": "City", "name": "city", "type": "text", "instructions": "", "required": 0, "conditional_logic": 0, "wrapper": { "width": "50", "class": "", "id": "" }, "default_value": "", "placeholder": "", "prepend": "", "append": "", "maxlength": "" }, { "key": "field_5a44dab4303a8", "label": "Province", "name": "province", "type": "text", "instructions": "", "required": 0, "conditional_logic": 0, "wrapper": { "width": "50", "class": "", "id": "" }, "default_value": "", "placeholder": "", "prepend": "", "append": "", "maxlength": "" }, { "key": "field_5a44dad6303a9", "label": "Website", "name": "website", "type": "text", "instructions": "", "required": 0, "conditional_logic": 0, "wrapper": { "width": "50", "class": "", "id": "" }, "default_value": "", "placeholder": "", "prepend": "", "append": "", "maxlength": "" }, { "key": "field_5a44daf7303aa", "label": "Photo", "name": "photo", "type": "image", "instructions": "", "required": 0, "conditional_logic": 0, "wrapper": { "width": "50", "class": "", "id": "" }, "return_format": "array", "preview_size": "thumbnail", "library": "all", "min_width": "", "min_height": "", "min_size": "", "max_width": "", "max_height": "", "max_size": "", "mime_types": "" } ] } ], "location": [ [ { "param": "post_type", "operator": "==", "value": "practitioners" } ] ], "menu_order": 0, "position": "normal", "style": "default", "label_placement": "top", "instruction_placement": "label", "hide_on_screen": [ "the_content" ], "active": 1, "description": "" } ]