Skip to content

Commit 7111f06

Browse files
authored
Merge pull request #10 from wp-graphql/issue-4-hooks
First pass at creating a more extensible plugin
2 parents 9b99405 + a0e836f commit 7111f06

7 files changed

+110
-20
lines changed

ACTIONS_AND_FILTERS.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Actions & Filters
2+
3+
-> [Original documentation](https://www.wpgraphql.com/docs/customizing-wpgraphiql)
4+
5+
_legend_ 🎉 = new
6+
7+
## PHP Actions
8+
9+
- `wpgraphqlide_enqueue_script` ([enqueue_graphiql_extension](https://www.wpgraphql.com/docs/customizing-wpgraphiql#enqueue_graphiql_extension))
10+
11+
## PHP Filters
12+
13+
- `wpgraphqlide_capability_required` 🎉
14+
- `wpgraphqlide_context` 🎉
15+
- `wpgraphqlide_external_fragments` ([graphiql_external_fragments](https://www.wpgraphql.com/docs/customizing-wpgraphiql#graphiql_external_fragments))
16+
17+
## JavaScript Actions
18+
19+
- `wpgraphqlide_destroyed` 🎉
20+
- `wpgraphqlide_rendered` ([graphiql_rendered](https://www.wpgraphql.com/docs/customizing-wpgraphiql#graphiql_rendered))
21+
22+
## JavaScript Filters
23+
24+
...

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,7 @@ GraphiQL IDE has intentionally been updated to read "GraphQL IDE", which feels m
3131
```
3232

3333
Builds are only required for JS updates as the plugin's CSS is directly enqueued.
34+
35+
## Custom Hooks
36+
37+
See [ACTIONS_AND_FILTERS.md].

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
},
1818
"dependencies": {
1919
"@wordpress/element": "^5.23.0",
20+
"@wordpress/hooks": "^3.49.0",
2021
"graphiql": "^3.0.10",
2122
"graphql-ws": "^5.14.2",
2223
"vaul": "^0.7.9"

src/App.jsx

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,45 @@
1-
import { useState } from '@wordpress/element';
1+
import { useState, useEffect } from '@wordpress/element';
22
import { EditorDrawer } from './components/EditorDrawer';
33
import { Editor } from './components/Editor';
44

5+
// Assuming wp.hooks is globally available through WordPress's script enqueueing mechanism.
6+
const { doAction } = wp.hooks;
7+
8+
/**
9+
* The main application component.
10+
*
11+
* @returns {JSX.Element} The application component.
12+
*/
513
export function App() {
6-
const [ drawerOpen, setDrawerOpen ] = useState( false );
7-
8-
return (
9-
<div className="AppRoot">
10-
<EditorDrawer open={ drawerOpen } setDrawerOpen={ setDrawerOpen }>
11-
<Editor setDrawerOpen={ setDrawerOpen } />
12-
</EditorDrawer>
13-
</div>
14-
);
14+
const [drawerOpen, setDrawerOpen] = useState(false);
15+
16+
useEffect(() => {
17+
/**
18+
* Perform actions on component mount.
19+
*
20+
* Triggers a custom action 'wpgraphqlide_rendered' when the App component mounts,
21+
* allowing plugins or themes to hook into this event. The action passes
22+
* the current state of `drawerOpen` to any listeners, providing context
23+
* about the application's UI state.
24+
*/
25+
doAction('wpgraphqlide_rendered', drawerOpen);
26+
27+
/**
28+
* Cleanup action on component unmount.
29+
*
30+
* Returns a cleanup function that triggers the 'wpgraphqlide_destroyed' action,
31+
* signaling that the App component is about to unmount. This allows for
32+
* any necessary cleanup or teardown operations in response to the App
33+
* component's lifecycle.
34+
*/
35+
return () => doAction('wpgraphqlide_destroyed');
36+
}, [drawerOpen]);
37+
38+
return (
39+
<div className="AppRoot">
40+
<EditorDrawer open={ drawerOpen } setDrawerOpen={ setDrawerOpen }>
41+
<Editor setDrawerOpen={setDrawerOpen} />
42+
</EditorDrawer>
43+
</div>
44+
);
1545
}

src/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
/* global WPGRAPHQL_IDE_DATA */
22
import { createRoot } from '@wordpress/element';
3+
import { createHooks } from '@wordpress/hooks';
4+
35
import { App } from './App';
46

57
/**
@@ -18,5 +20,8 @@ if ( rootElement ) {
1820
root.render( <App /> );
1921
}
2022

23+
// Initialize hook system.
24+
App.hooks = createHooks();
25+
2126
// Expose app as a global variable to utilize in gutenberg.
2227
window.WPGraphQLIDE = App;

wpgraphql-ide.php

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,9 @@ function enqueue_react_app_with_styles(): void {
121121
'wp-i18n',
122122
];
123123

124-
$version = plugin_version();
124+
$app_context = get_app_context();
125+
126+
$version = get_plugin_header( 'Version' );
125127

126128
wp_enqueue_script(
127129
'wpgraphql-ide-app',
@@ -138,28 +140,52 @@ function enqueue_react_app_with_styles(): void {
138140
'nonce' => wp_create_nonce( 'wp_rest' ),
139141
'graphqlEndpoint' => trailingslashit( site_url() ) . 'index.php?' . \WPGraphQL\Router::$route,
140142
'rootElementId' => WPGRAPHQL_IDE_ROOT_ELEMENT_ID,
143+
'context' => $app_context,
141144
]
142145
);
143146

144147
wp_enqueue_style( 'wpgraphql-ide-app', plugins_url( 'build/index.css', __FILE__ ), [], $version );
145148
// Avoid running custom styles through a build process for an improved developer experience.
146149
wp_enqueue_style( 'wpgraphql-ide', plugins_url( 'styles/wpgraphql-ide.css', __FILE__ ), [], $version );
150+
151+
// Extensions looking to extend GraphiQL can hook in here,
152+
// after the window object is established, but before the App renders
153+
do_action( 'wpgraphqlide_enqueue_script', $app_context );
147154
}
148155
add_action( 'admin_enqueue_scripts', __NAMESPACE__ . '\\enqueue_react_app_with_styles' );
149156
add_action( 'wp_enqueue_scripts', __NAMESPACE__ . '\\enqueue_react_app_with_styles' );
150157

151158
/**
152-
* Retrieves the version of the current plugin.
159+
* Retrieves the specific header of this plugin.
153160
*
154-
* @return string The version number of the plugin. Returns an empty string if the version is not found.
161+
* @param string The plugin data key.
162+
* @return string|null The version number of the plugin. Returns an empty string if the version is not found.
155163
*/
156-
function plugin_version(): string {
164+
function get_plugin_header( $key = '' ): ?string {
157165
if ( ! function_exists( 'get_plugin_data' ) ) {
158166
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
159167
}
160168

169+
if ( empty( $key ) ) {
170+
return null;
171+
}
172+
161173
$plugin_data = get_plugin_data( __FILE__ );
162-
$version = $plugin_data['Version'];
163174

164-
return $version;
175+
return $plugin_data[ $key ] ?? null;
176+
}
177+
178+
/**
179+
* Retrieves app context.
180+
*
181+
* @return array The possibly filtered app context array.
182+
*/
183+
function get_app_context() {
184+
$context = apply_filters( 'wpgraphqlide_context', [
185+
'pluginVersion' => get_plugin_header( 'Version' ),
186+
'pluginName' => get_plugin_header( 'Name' ),
187+
'externalFragments' => apply_filters( 'wpgraphqlide_external_fragments', [] )
188+
]);
189+
190+
return $context;
165191
}

0 commit comments

Comments
 (0)