Όπως είπαμε πιο πριν, για κάθε αρχιτεκτονικό project θέλουμε να αποθηκεύουμε τις παρακάτω πληροφορίες: τοποθεσία, έτος και τύπος (studio, μεζονέτα κτλ.) και από εδώ και πέρα θα αναφερόμαστε σε αυτά ως project metadata. Πριν από την έλευση των blocks στο WordPress, θα έπρεπε να γράψουμε κώδικα για την προσθήκη των metadata στο custom post type, για τη δημιουργία των απαραίτητων πεδίων και για την προσθήκη τους σε κάποιο template ενός θέματος ή την προσθήκη τους μέσω ενός shortcode που θα αναπτύσσαμε. Η προσθήκη των πεδίων απαιτούσε και την χρήση filters για προσθήκη nonce στο backend περιβάλλον για λόγους ασφάλειας. Η πολυπλοκότητα της λύσης είχε οδηγήσει στην ύπαρξη κάποιων plugins, που μέσα από γραφικό περιβάλλον μπορούσε κάποιος να κάνει ακριβώς αυτή τη δουλειά εύκολα και γρήγορα.
Με τα blocks, τα παραπάνω έχουν αλλάξει, και σε πολλά σημεία έχουμε μια σαφή βελτίωση για τον προγραμματιστή, αλλά και μια λύση πολύ καλύτερη για τον τελικό χρήστη του backend περιβάλλοντος. Ξεκινώντας από την τεκμηρίωση για την κατασκευή ενός block που χειρίζεται metadata, καλό θα είναι επειδή τα blocks στηρίζονται στο WordPress REST API, να δούμε και κάποιες ακόμα πληροφορίες σχετικά.
Η δομή δεδομένων που θέλουμε, εκφρασμένη ως αντικείμενο JSON, είναι η ακόλουθη:
{ "dh_project_info": { "location": "string value", "year": "string value", "type": "string value" } }
και την επιλέγουμε γιατί έτσι μπορούμε να την χρησιμοποιούμε ως associative array στην PHP και ως αντικείμενο στην JavaScript.
Καταχώρηση της δομής
Το πρώτο βήμα είναι να ενημερώσουμε το WordPress για τα metadata που θέλουμε να προσαρτήσουμε στο custom post type. Χρησιμοποιούμε την register_post_meta. Στο αρχείο dh-architect-plugin.php προσθέτουμε το παρακάτω:
/* Register the project_info metadata for ArchitectureProject CPT */ add_action( 'init', ['DasodaHae\Architect\ArchitectureProject', 'RegisterProjectMeta'] );
και στο αρχείο src/ArchitectureProject.php το παρακάτω, μέσα στο σώμα της κλάσης (class) ArchitectureProject:
public static function RegisterProjectMeta() { register_post_meta( 'dh_at_archproj', 'dh_project_info', array( 'single' => true, 'type' => 'object', 'show_in_rest' => array( 'schema' => array( 'type' => 'object', 'properties' => array( 'location' => array( 'type' => 'string', ), 'year' => array( 'type' => 'string', 'minLength' => 4, 'maxLength' => 4, 'pattern' => '[0-9]{4}', ), 'type' => array( 'type' => 'string', ), ), ), ), 'auth_callback' => function() { return current_user_can('edit_architecture_projects'); }, ) ); }
Προσέχουμε ότι η show_in_rest δεν παίρνει απλά την τιμή true, αλλά περιγράφει την δομή μας σύμφωνα με το JSON Schema, που χρησιμοποιεί το WordPress στο REST API. Επειδή περιγράφουμε την δομή μας εδώ, γίνεται αυτόματα για εμάς ο έλεγχος ορθότητας των δεδομένων με βάση αυτή τη δομή (validation check) από το WordPress, χωρίς να χρειάζεται να παρέχουμε εμείς μια συνάρτηση ως τιμή της παραμέτρου sanitize_callback, η οποία και παραλείπεται. Στο παράδειγμά μας, για το έτος χρησιμοποιείται ένα regular expression, ώστε να ελέγχεται η τιμή ότι αποτελείται από ακριβώς 4 γράμματα, που είναι και τα 4 ψηφία (0 έως 9).
Επίσης, δίνουμε μια συνάρτηση ως τιμή στη auth_callback, που χρησιμοποιείται για να ελέγχει το WordPress, αν ο χρήστης έχει δικαίωμα να εισάγει, αλλάξει, ή και να διαγράψει τα metadata.
Καταχώρηση του block type
Σειρά έχει η καταχώρηση του block type. Εδώ απλά να σημειώσουμε ότι αναφέρεται ως καταχώρηση του block type (και όχι καταχώρηση του block), μια και το block type λειτουργεί ως μήτρα/καλούπι για τα block που προσθέτουμε στα post, με παρόμοιο τρόπο με τις κλάσεις (classes). Όπως προτείνεται, καλό είναι να χρησιμοποιήσουμε την register_block_type δίνοντας της ως παράμετρο ένα αρχείο block.json που περιγράφει το block type.
Καταχωρούμε το block type για το backend σε PHP. Στο αρχείο dh-architect-plugin.php προσθέτουμε το παρακάτω action hook:
/* Register the Architecture Project Info Block */ add_action( 'init', ['DasodaHae\Architect\ArchitectureProject', 'RegisterProjectMetaBlock'] );
και αντίστοιχα ορίζουμε την παρακάτω μέθοδο (method) στην κλάση (class) ArchitectureProject, προσθέτοντας το ακόλουθο στο αρχείο src/ArchitectureProject.php:
public static function RegisterProjectMetaBlock() { register_block_type( __DIR__ . DIRECTORY_SEPARATOR . 'archmeta-info-block', array( 'render_callback' => function($attributes) { return ArchitectureProject::MetaBlockFrontEndTemplatePartHTML($attributes); }, ) ); }
Σύμφωνα με το παραπάνω κώδικα, δημιουργούμε το φάκελο src/archmeta-info-block και μέσα σε αυτόν θα βρίσκεται το αρχείο block.json καθώς και άλλα αρχεία με τον κώδικα για το συγκεκριμένο block type.
Επίσης ορίζουμε και την render_callback, ως μια ανώνυμη συνάρτηση, που απλά καλεί μια άλλη συνάρτηση της κλάσης. Σε αυτή θα αναφερθούμε αναλυτικότερα παρακάτω.
Το αρχείο src/archmeta-info-block/block.json περιέχει τα ακόλουθα:
{ "$schema": "https://json.schemastore.org/block.json", "apiVersion": 2, "name": "dh-architect-plugin/archmeta-info-block", "version": "1.0.0", "title": "Architecture Project Information", "category": "dh-architect", "icon": "smiley", "description": "An example block viewing and saving post meta", "attributes": { "archprojectId": { "type": "string" } }, "supports": { "html": false, "multiple": true }, "textdomain": "dh-architect-plugin", "editorScript": "file:../../build/editor.js", "viewScript": "file:../../build/index.js" }
“supports”: {“multiple”:true}
Ένα παράδειγμα του πόσο πιο εύκολο έγινε το έργο μας στην όσον αφορά την διαχείρηση των post metadata, με την έλευση των blocks στο WordPress. Την τιμή της supports την ορίζουμε ανάλογα με κάποια χαρακτηριστικά που θέλουμε να υποστηρίζει το block type, και η εξ ορισμού τιμή της multiple είναι true. Στο παράδειγμα μας, μπορούμε να την παραλείψουμε, και έχει συμπεριληφθεί μόνο και μόνο για να τονίσουμε ότι στο περιβάλλον του block editor τα metadata του post ενημερώνονται σε όλα τα block που σχετίζονται με αυτά. Στο παράδειγμα μας, αν έχουμε συμπεριλάβει για κάποιο λόγο δύο block σχετικά με τα metadata του αρχιτεκτονικού project, και κάνουμε αλλαγές στο ένα, οι αλλαγές αυτές μεταφέρονται αυτόματα, και στο άλλο χωρίς την παρέμβαση του χρήστη. Ακολουθεί ένα βίντεο ως παράδειγμα