├── .editorconfig ├── .gitignore ├── build ├── index.asset.php ├── index.js └── style-index.css ├── docker-compose.yml ├── package-lock.json ├── package.json ├── readme.txt ├── reveal-post-data.php └── src ├── index.js ├── store.js └── style.scss /.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs 2 | # editorconfig.org 3 | 4 | # WordPress Coding Standards 5 | # https://make.wordpress.org/core/handbook/coding-standards/ 6 | 7 | root = true 8 | 9 | [*] 10 | charset = utf-8 11 | end_of_line = lf 12 | insert_final_newline = true 13 | trim_trailing_whitespace = true 14 | indent_style = tab 15 | 16 | [*.{yml,yaml}] 17 | indent_style = space 18 | indent_size = 2 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Coverage directory used by tools like istanbul 9 | coverage 10 | 11 | # Compiled binary addons (https://nodejs.org/api/addons.html) 12 | build/Release 13 | 14 | # Dependency directories 15 | node_modules/ 16 | 17 | # Optional npm cache directory 18 | .npm 19 | 20 | # Optional eslint cache 21 | .eslintcache 22 | 23 | # Output of `npm pack` 24 | *.tgz 25 | 26 | # Output of `wp-scripts plugin-zip` 27 | *.zip 28 | 29 | # dotenv environment variables file 30 | .env 31 | 32 | wordpress_data/ -------------------------------------------------------------------------------- /build/index.asset.php: -------------------------------------------------------------------------------- 1 | array('wp-api-fetch', 'wp-components', 'wp-data', 'wp-edit-post', 'wp-element', 'wp-i18n', 'wp-plugins'), 'version' => '6cd7082a919a7dca42b8'); 2 | -------------------------------------------------------------------------------- /build/index.js: -------------------------------------------------------------------------------- 1 | (()=>{"use strict";var e,t={837:(e,t,a)=>{const l=window.wp.element,n=window.wp.plugins,r=window.wp.editPost,o=window.wp.components,s=window.wp.i18n,c=window.wp.data,m=window.wp.apiFetch;var d=a.n(m);const u="reveal-post-data",p={setPostData:(e,t)=>({type:"SET_POST_DATA",id:e,data:t})},i={posts:{}},E=(0,c.createReduxStore)(u,{reducer:(e=i,t)=>"SET_POST_DATA"===t.type?{...e,posts:{...e.posts,[t.id]:{...t.data}}}:e,actions:p,selectors:{getPostData(e,t){var a;return null!==(a=e.posts[t])&&void 0!==a?a:void 0}},controls:{API_FETCH:e=>d()(e.request)},resolvers:{*getPostData(e){const t=`/reveal-post-data/v1/post/${e}`,a=yield function(e){return{type:"API_FETCH",request:{path:e,method:"GET"}}}(t);return p.setPostData(e,a)}}});(0,c.register)(E),(0,n.registerPlugin)("reveal-post-data-panel",{render:()=>{const[e,t]=(0,l.useState)(!1),a=()=>t(!e),n=(0,c.useSelect)((e=>{const{getPostData:t}=e(u);return t(e("core/editor").getCurrentPostId())}));return(0,l.createElement)(r.PluginDocumentSettingPanel,{name:"reveal-post-data-panel",title:"Post Data",className:"reveal-post-data-panel"},(0,l.createElement)(o.__experimentalHStack,null,(0,l.createElement)(o.Button,{variant:"secondary",onClick:a},(0,s.__)("Show raw data","reveal-post-data")),e&&(0,l.createElement)(o.Modal,{className:"reveal-post-data-modal",title:(0,s.__)("Raw post data","reveal-post-data"),onRequestClose:a},(0,l.createElement)(o.TabPanel,{tabs:[{name:"post",title:"Post",className:"post"},{name:"taxonomy",title:"Taxonomies",className:"taxonomy"},{name:"meta",title:"Meta",className:"meta"}]},(e=>(0,l.createElement)(l.Fragment,null,"post"===e.name&&(0,l.createElement)(v,{data:n.post}),"taxonomy"===e.name&&(0,l.createElement)(_,{data:n.taxonomy}),"meta"===e.name&&(0,l.createElement)(w,{data:n.meta})))))))},icon:!1});const v=({data:e})=>(0,l.createElement)("table",null,(0,l.createElement)("thead",null,(0,l.createElement)("tr",null,(0,l.createElement)("th",null,(0,s.__)("Key","reveal-post-data")),(0,l.createElement)("th",null,(0,s.__)("Value","reveal-post-data")))),(0,l.createElement)("tbody",null,Object.entries(e).map((([e,t])=>(0,l.createElement)("tr",{key:e},(0,l.createElement)("td",null,e),(0,l.createElement)("td",null,JSON.stringify(t))))))),_=({data:e})=>(0,l.createElement)("table",null,(0,l.createElement)("thead",null,(0,l.createElement)("tr",null,(0,l.createElement)("th",null,(0,s.__)("Taxonomy","reveal-post-data")),(0,l.createElement)("th",null,(0,s.__)("Terms","reveal-post-data")))),(0,l.createElement)("tbody",null,Object.entries(e).map((([e,t])=>(0,l.createElement)("tr",{key:e},(0,l.createElement)("td",null,t.label),(0,l.createElement)("td",null,t.terms.join(","))))))),w=({data:e})=>(0,l.createElement)("table",null,(0,l.createElement)("thead",null,(0,l.createElement)("tr",null,(0,l.createElement)("th",null,(0,s.__)("Key","reveal-post-data")),(0,l.createElement)("th",null,(0,s.__)("Value","reveal-post-data")))),(0,l.createElement)("tbody",null,Object.entries(e).map((([e,t])=>(0,l.createElement)("tr",{key:e},(0,l.createElement)("td",null,e),(0,l.createElement)("td",null,t.map((e=>"object"==typeof e?(0,l.createElement)("div",null,JSON.stringify(e)):(0,l.createElement)("div",null,e)))))))))}},a={};function l(e){var n=a[e];if(void 0!==n)return n.exports;var r=a[e]={exports:{}};return t[e](r,r.exports,l),r.exports}l.m=t,e=[],l.O=(t,a,n,r)=>{if(!a){var o=1/0;for(d=0;d=r)&&Object.keys(l.O).every((e=>l.O[e](a[c])))?a.splice(c--,1):(s=!1,r0&&e[d-1][2]>r;d--)e[d]=e[d-1];e[d]=[a,n,r]},l.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return l.d(t,{a:t}),t},l.d=(e,t)=>{for(var a in t)l.o(t,a)&&!l.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},l.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={826:0,431:0};l.O.j=t=>0===e[t];var t=(t,a)=>{var n,r,o=a[0],s=a[1],c=a[2],m=0;if(o.some((t=>0!==e[t]))){for(n in s)l.o(s,n)&&(l.m[n]=s[n]);if(c)var d=c(l)}for(t&&t(a);ml(837)));n=l.O(n)})(); -------------------------------------------------------------------------------- /build/style-index.css: -------------------------------------------------------------------------------- 1 | .reveal-post-data-modal{min-height:90vh;min-width:90vw}.reveal-post-data-modal table{background-color:#eee;margin-top:6px;min-height:100%;padding:12px;width:100%}.reveal-post-data-modal table td,.reveal-post-data-modal table th{border-bottom:1px solid #ddd;border-collapse:collapse;padding:6px;text-align:left}.reveal-post-data-modal table tr:last-child td{border-bottom:none} 2 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | 3 | services: 4 | 5 | # WordPress 6 | ## PHP + Core 7 | wordpress: 8 | image: wordpress:latest 9 | ## Wait to start until database server is started. 10 | depends_on: 11 | wpdb: 12 | condition: service_healthy 13 | volumes: 14 | - ./wordpress_data:/var/www/html 15 | ## Map ./plugin directory into the plugin directory 16 | - ./:/var/www/html/wp-content/plugins/reveal-post-data 17 | ## Map ./logs directory 18 | - ./debug-log:/var/www/html/wp-content/logs 19 | ports: 20 | ## Port for WordPress 21 | - "8502:80" 22 | restart: always 23 | environment: 24 | WORDPRESS_DB_HOST: wpdb:3306 25 | WORDPRESS_DB_USER: wordpress 26 | WORDPRESS_DB_PASSWORD: wordpress 27 | WORDPRESS_DB_NAME: wordpress 28 | # This sets WP_DEBUG to true 29 | ## See: https://github.com/docker-library/wordpress/blob/de0693c1828391a509da9ee662798cbd1417bbe1/beta/php7.4/fpm/wp-config-docker.php#L110 30 | WORDPRESS_DEBUG: 1 31 | WORDPRESS_CONFIG_EXTRA: | 32 | /* WordPress logging, set path to root of plugin*/ 33 | define( 'WP_DEBUG_LOG', 'wp-content/logs/debug.log' ); 34 | define( 'WP_DEBUG_DISPLAY', true ); 35 | /* Other Constants */ 36 | define( 'SCRIPT_DEBUG', true ); 37 | 38 | ## Database for WordPress site 39 | wpdb: 40 | image: mariadb:10.5.8 41 | volumes: 42 | - db_data:/var/lib/mysql 43 | restart: always 44 | environment: 45 | MYSQL_ROOT_PASSWORD: wordpress 46 | MYSQL_DATABASE: wordpress 47 | MYSQL_USER: wordpress 48 | MYSQL_PASSWORD: wordpress 49 | healthcheck: 50 | test: "/usr/bin/mysql --user=wordpress --password=wordpress --execute \"SHOW DATABASES;\"" 51 | # test: "/usr/local/mysql/bin/mysql --user=wordpress --password=wordpress --execute \"SHOW DATABASES;\"" 52 | interval: 3s 53 | timeout: 1s 54 | retries: 5 55 | ## PHPmyadmin 56 | phpmyadmin: 57 | image: phpmyadmin/phpmyadmin 58 | depends_on: 59 | wpdb: 60 | condition: service_healthy 61 | restart: always 62 | ports: 63 | - "8602:80" 64 | links: 65 | - wpdb 66 | environment: 67 | PMA_HOST: wpdb 68 | PMA_PORT: 3306 69 | ## WPCli for WordPress site 70 | wpcli: 71 | image: wordpress:cli 72 | ## Wait to start until database server is started. 73 | depends_on: 74 | wpdb: 75 | condition: service_healthy 76 | volumes: 77 | - wordpress_data:/var/www/html 78 | ## Map this directory into the plugin directory 79 | - ./:/var/www/html/wp-content/plugins/trustedlogin-vendor 80 | - ./db:/var/www/html/db 81 | environment: 82 | WORDPRESS_DB_HOST: wpdb:3306 83 | WORDPRESS_DB_USER: wordpress 84 | WORDPRESS_DB_PASSWORD: wordpress 85 | WORDPRESS_DB_NAME: wordpress 86 | ABSPATH: /usr/src/wordpress/ 87 | 88 | # Integration Testing - Tests that run in phpunit with WordPress + MySQL 89 | ## Runner for phpunit 90 | phpunit: 91 | command: 92 | - bash 93 | ## Wait to start until the database server for testing is ready. 94 | depends_on: 95 | - testwpdb 96 | environment: 97 | DATABASE_PASSWORD: examplepass 98 | DATABASE_HOST: testwpdb 99 | image: futureys/phpunit-wordpress-plugin 100 | stdin_open: true 101 | tty: true 102 | volumes: 103 | ## Map src/plugin + tests directories into the test plugin directory 104 | - ./plugin:/plugin 105 | - ./tests:/plugin/tests 106 | ## Database for testing 107 | testwpdb: 108 | environment: 109 | MYSQL_ROOT_PASSWORD: examplepass 110 | image: mariadb:10.5.8 111 | volumes: 112 | db_data: {} 113 | wordpress_data: {} 114 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reveal-post-data", 3 | "version": "0.1.0", 4 | "description": "Adds a button in the editor sidebar to show the raw post data.", 5 | "author": "codeamp", 6 | "license": "GPL-2.0-or-later", 7 | "main": "build/index.js", 8 | "scripts": { 9 | "build": "wp-scripts build", 10 | "format": "wp-scripts format", 11 | "lint:css": "wp-scripts lint-style", 12 | "lint:js": "wp-scripts lint-js", 13 | "packages-update": "wp-scripts packages-update", 14 | "plugin-zip": "wp-scripts plugin-zip", 15 | "start": "wp-scripts start" 16 | }, 17 | "devDependencies": { 18 | "@wordpress/scripts": "^26.9.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | === Reveal Post Data === 2 | Contributors: codeamp 3 | Tags: block 4 | Tested up to: 6.4 5 | Stable tag: 0.1.3 6 | License: GPL-2.0-or-later 7 | License URI: https://www.gnu.org/licenses/gpl-2.0.html 8 | 9 | Adds a button in the editor sidebar to show the raw post data. 10 | 11 | == Description == 12 | 13 | Adds a button in the editor sidebar to show the raw post data including taxonomy and meta data - useful for debugging. 14 | 15 | [Official GitHub Repository](https://github.com/rmorse/reveal-post-data). 16 | 17 | == Installation == 18 | 19 | == Frequently Asked Questions == 20 | 21 | == Screenshots == 22 | 23 | 1. The button in the editor sidebar. 24 | 2. The post data displayed in a modal. 25 | 26 | == Changelog == 27 | 28 | = 0.1.3 29 | - Load scrips using `enqueue_block_editor_assets` so JS is only loaded on pages with the editor. 30 | - Add screenshots 31 | 32 | = 0.1.2 = 33 | - Update readme tested up to 34 | 35 | = 0.1.1 = 36 | - Prevent direct access to plugin file 37 | 38 | = 0.1.0 = 39 | - Release 40 | 41 | -------------------------------------------------------------------------------- /reveal-post-data.php: -------------------------------------------------------------------------------- 1 | \d+)', 52 | array( 53 | 'args' => array( 54 | 'id' => array( 55 | 'description' => __( 'ID of the post.', 'search-filter' ), 56 | 'type' => 'number', 57 | 'sanitize_callback' => 'absint', 58 | ), 59 | ), 60 | array( 61 | 'methods' => \WP_REST_Server::READABLE, 62 | 'callback' => 'reveal_post_data_get_post_data', 63 | 'permission_callback' => 'reveal_post_data_rest_api_permissions', 64 | ), 65 | ) 66 | ); 67 | } 68 | 69 | add_action( 'rest_api_init', 'reveal_post_data_add_routes' ); 70 | 71 | /** 72 | * Check if the user has the correct permissions. 73 | */ 74 | function reveal_post_data_rest_api_permissions() { 75 | return current_user_can( 'manage_options' ); 76 | } 77 | 78 | /** 79 | * Get the post data. 80 | */ 81 | function reveal_post_data_get_post_data( WP_REST_Request $request ) { 82 | $params = $request->get_params(); 83 | $id = $params['id']; 84 | $post = get_post( $id ); 85 | 86 | $taxonomies_list = get_object_taxonomies( $post->post_type ); 87 | $taxonomies = array(); 88 | foreach ( $taxonomies_list as $taxonomy_slug ) { 89 | // Get the taxonomy label. 90 | $taxonomy_object = get_taxonomy( $taxonomy_slug ); 91 | // Get the terms related to post. 92 | $terms = wp_get_post_terms( $id, $taxonomy_slug, array( 'fields' => 'names' ) ); 93 | $taxonomies[ $taxonomy_slug ] = array ( 94 | 'terms' => $terms, 95 | 'label' => $taxonomy_object->label, 96 | ); 97 | } 98 | 99 | $post_data = array( 100 | 'post' => $post, 101 | 'taxonomy' => $taxonomies, 102 | 'meta' => get_post_meta( $id ), 103 | ); 104 | return rest_ensure_response( $post_data ); 105 | } 106 | 107 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Registers a new block provided a unique name and an object defining its behavior. 3 | * 4 | * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/ 5 | */ 6 | import { registerPlugin } from '@wordpress/plugins'; 7 | import { PluginDocumentSettingPanel } from '@wordpress/edit-post'; 8 | import { Button, Modal, TabPanel, __experimentalHStack as HStack } from '@wordpress/components'; 9 | import { useState } from '@wordpress/element'; 10 | import { __ } from '@wordpress/i18n'; 11 | import { useSelect } from '@wordpress/data'; 12 | 13 | /** 14 | * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files. 15 | * All files containing `style` keyword are bundled together. The code used 16 | * gets applied both to the front of your site and to the editor. 17 | * 18 | * @see https://www.npmjs.com/package/@wordpress/scripts#using-css 19 | */ 20 | import './style.scss'; 21 | 22 | // The store for handling the fetching of the post data. 23 | import { STORE_NAME } from './store'; 24 | 25 | /** 26 | * Internal dependencies 27 | */ 28 | 29 | registerPlugin( 'reveal-post-data-panel', { 30 | render: () => { 31 | const [ isModalOpen, setIsModalOpen ] = useState( false ); 32 | const toggleModal = () => setIsModalOpen( ! isModalOpen ); 33 | 34 | const postData = useSelect( ( select ) => { 35 | const { getPostData } = select( STORE_NAME ); 36 | return getPostData( select( 'core/editor' ).getCurrentPostId() ); 37 | } ); 38 | return ( 39 | 44 | 45 | 46 | { isModalOpen && ( 47 | 52 | 73 | { ( tab ) => ( 74 | <> 75 | { tab.name === 'post' && } 76 | { tab.name === 'taxonomy' && } 77 | { tab.name === 'meta' && } 78 | 79 | ) } 80 | 81 | 82 | ) } 83 | 84 | 85 | ) 86 | 87 | }, 88 | icon: false, 89 | } ); 90 | 91 | const PostTable = ( { data } ) => { 92 | return ( 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | { Object.entries( data ).map( ( [ key, value ] ) => ( 102 | 103 | 104 | 105 | 106 | ) ) } 107 | 108 |
{ __( 'Key', 'reveal-post-data' ) }{ __( 'Value', 'reveal-post-data' ) }
{ key }{ JSON.stringify( value ) }
109 | ) 110 | } 111 | 112 | const TaxonomyTable = ( { data } ) => { 113 | return ( 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | { Object.entries( data ).map( ( [ key, object ] ) => ( 123 | 124 | 125 | 126 | 127 | ) ) } 128 | 129 |
{ __( 'Taxonomy', 'reveal-post-data' ) }{ __( 'Terms', 'reveal-post-data' ) }
{ object.label }{ object.terms.join( ',' ) }
130 | ) 131 | } 132 | 133 | const MetaTable = ( { data } ) => { 134 | return ( 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | { Object.entries( data ).map( ( [ key, arr ] ) => ( 144 | 145 | 146 | 153 | 154 | ) ) } 155 | 156 |
{ __( 'Key', 'reveal-post-data' ) }{ __( 'Value', 'reveal-post-data' ) }
{ key }{ arr.map( ( value ) => { 147 | if ( typeof value === 'object' ) { 148 | return
{ JSON.stringify( value ) }
; 149 | } 150 | return
{ value }
; 151 | } ) } 152 |
157 | ) 158 | } 159 | -------------------------------------------------------------------------------- /src/store.js: -------------------------------------------------------------------------------- 1 | /** 2 | */ 3 | /** 4 | * WordPress dependencies 5 | */ 6 | import apiFetch from '@wordpress/api-fetch'; 7 | import { createReduxStore, register } from '@wordpress/data'; 8 | 9 | export const STORE_NAME = 'reveal-post-data'; 10 | const actions = { 11 | setPostData( id, data ) { 12 | return { 13 | type: 'SET_POST_DATA', 14 | id, 15 | data, 16 | }; 17 | }, 18 | }; 19 | 20 | function getFromAPI( path ) { 21 | return { 22 | type: 'API_FETCH', 23 | request: { path, method: 'GET' }, 24 | }; 25 | } 26 | const DEFAULT_STATE = { 27 | posts: {}, 28 | }; 29 | export const defaults = DEFAULT_STATE; 30 | export const taxonomyStore = createReduxStore( STORE_NAME, { 31 | reducer( state = DEFAULT_STATE, action ) { 32 | switch ( action.type ) { 33 | case 'SET_POST_DATA': { 34 | return { 35 | ...state, 36 | posts: { 37 | ...state.posts, 38 | [ action.id ]: { ...action.data }, 39 | }, 40 | }; 41 | } 42 | } 43 | return state; 44 | }, 45 | actions, 46 | selectors: { 47 | getPostData( state, id ) { 48 | return state.posts[ id ] ?? undefined; 49 | }, 50 | }, 51 | controls: { 52 | API_FETCH( action ) { 53 | return apiFetch( action.request ); 54 | }, 55 | }, 56 | resolvers: { 57 | *getPostData( id ) { 58 | const path = `/reveal-post-data/v1/post/${ id }`; 59 | const post = yield getFromAPI( path ); 60 | return actions.setPostData( id, post ); 61 | }, 62 | }, 63 | } ); 64 | 65 | register( taxonomyStore ); 66 | -------------------------------------------------------------------------------- /src/style.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * The following styles get applied inside the editor only. 3 | * 4 | * Replace them with your own styles or remove the file completely. 5 | */ 6 | 7 | .reveal-post-data-modal { 8 | min-width: 90vw; 9 | min-height: 90vh; 10 | 11 | table { 12 | width: 100%; 13 | min-height: 100%; 14 | background-color: #eee; 15 | padding: 12px; 16 | margin-top: 6px; 17 | 18 | th, td { 19 | text-align: left; 20 | padding: 6px; 21 | border-bottom: 1px solid #ddd; 22 | border-collapse: collapse; 23 | } 24 | 25 | tr:last-child { 26 | td { 27 | border-bottom: none; 28 | } 29 | } 30 | } 31 | } 32 | --------------------------------------------------------------------------------