diff --git a/inc/class-api.php b/inc/class-api.php new file mode 100644 index 0000000..18f4992 --- /dev/null +++ b/inc/class-api.php @@ -0,0 +1,264 @@ +register_route(); + } + + /** + * Get endpoint. + * + * @return string + */ + public function get_endpoint() { + return $this->namespace . '/' . $this->version; + } + + /** + * Register hooks and actions. + * + * @return void + */ + private function register_route() { + add_action( 'rest_api_init', array( $this, 'register_routes' ) ); + } + + /** + * Register REST API route + * + * @return void + */ + public function register_routes() { + $namespace = $this->namespace . '/' . $this->version; + + $routes = array( + 'send' => array( + 'methods' => \WP_REST_Server::CREATABLE, + 'args' => array( + 'step' => array( + 'required' => true, + 'type' => 'string', + ), + 'message' => array( + 'required' => false, + 'type' => 'string', + ), + ), + 'callback' => array( $this, 'send' ), + ), + 'status' => array( + 'methods' => \WP_REST_Server::READABLE, + 'args' => array( + 'thread_id' => array( + 'required' => true, + 'type' => 'string', + ), + 'run_id' => array( + 'required' => true, + 'type' => 'string', + ), + ), + 'callback' => array( $this, 'status' ), + ), + 'get' => array( + 'methods' => \WP_REST_Server::READABLE, + 'callback' => array( $this, 'get' ), + ), + 'images' => array( + 'methods' => \WP_REST_Server::READABLE, + 'args' => array( + 'query' => array( + 'required' => true, + 'type' => 'string', + ), + ), + 'callback' => array( $this, 'images' ), + ), + ); + + foreach ( $routes as $route => $args ) { + $args['permission_callback'] = function () { + return current_user_can( 'manage_options' ); + }; + + register_rest_route( $namespace, '/' . $route, $args ); + } + } + + /** + * Send data to the API. + * + * @param \WP_REST_Request $request Request. + * + * @return \WP_REST_Response + */ + public function send( \WP_REST_Request $request ) { + $data = $request->get_params(); + + $request = wp_remote_post( + QUICKWP_API . 'wizard/send', + array( + 'body' => array( + 'step' => $data['step'], + 'message' => $data['message'], + ), + ) + ); + + if ( is_wp_error( $request ) ) { + return new \WP_REST_Response( array( 'error' => $request->get_error_message() ), 500 ); + } + + /** + * Holds the response as a standard class object + * + * @var \stdClass $response + */ + $response = json_decode( wp_remote_retrieve_body( $request ) ); + + if ( ! isset( $response->id ) || ! $response->id ) { + return new \WP_REST_Response( array( 'error' => __( 'Error', 'quickwp' ) ), 500 ); + } + + return new \WP_REST_Response( $response, 200 ); + } + + /** + * Get status. + * + * @param \WP_REST_Request $request Request. + * + * @return \WP_REST_Response + */ + public function status( \WP_REST_Request $request ) { + $data = $request->get_params(); + + $request = wp_remote_get( // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.wp_remote_get_wp_remote_get + QUICKWP_API . 'wizard/status', + array( + 'body' => array( + 'thread_id' => $data['thread_id'], + 'run_id' => $data['run_id'], + ), + ) + ); + + if ( is_wp_error( $request ) ) { + return new \WP_REST_Response( array( 'error' => $request->get_error_message() ), 500 ); + } + + /** + * Holds the response as a standard class object + * + * @var \stdClass $response + */ + $response = json_decode( wp_remote_retrieve_body( $request ) ); + + if ( ! isset( $response->id ) || ! $response->id ) { + return new \WP_REST_Response( array( 'error' => __( 'Error', 'quickwp' ) ), 500 ); + } + + return new \WP_REST_Response( $response, 200 ); + } + + /** + * Get data. + * + * @param \WP_REST_Request $request Request. + * + * @return \WP_REST_Response + */ + public function get( \WP_REST_Request $request ) { + $data = $request->get_params(); + + $request = wp_remote_get(// phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.wp_remote_get_wp_remote_get + QUICKWP_API . 'wizard/get', + array( + 'body' => array( + 'thread_id' => $data['thread_id'], + ), + ) + ); + + if ( is_wp_error( $request ) ) { + return new \WP_REST_Response( array( 'error' => $request->get_error_message() ), 500 ); + } + + /** + * Holds the response as a standard class object + * + * @var \stdClass $response + */ + $response = json_decode( wp_remote_retrieve_body( $request ) ); + + if ( ! isset( $response->data ) || ! $response->data ) { + return new \WP_REST_Response( array( 'error' => __( 'Error', 'quickwp' ) ), 500 ); + } + + return new \WP_REST_Response( $response, 200 ); + } + + /** + * Get images. + * + * @param \WP_REST_Request $request Request. + * + * @return \WP_REST_Response + */ + public function images( \WP_REST_Request $request ) { + $data = $request->get_params(); + + $request = wp_remote_get(// phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.wp_remote_get_wp_remote_get + QUICKWP_API . 'wizard/images', + array( + 'body' => array( + 'query' => $data['query'], + ), + ) + ); + + if ( is_wp_error( $request ) ) { + return new \WP_REST_Response( array( 'error' => $request->get_error_message() ), 500 ); + } + + /** + * Holds the response as a standard class object + * + * @var \stdClass $response + */ + $response = json_decode( wp_remote_retrieve_body( $request ) ); + + if ( ! isset( $response->photos ) || count( $response->photos ) === 0 ) { + return new \WP_REST_Response( array( 'error' => __( 'Error', 'quickwp' ) ), 500 ); + } + + return new \WP_REST_Response( $response, 200 ); + } +} diff --git a/inc/class-main.php b/inc/class-main.php index 54aec2d..932ce52 100644 --- a/inc/class-main.php +++ b/inc/class-main.php @@ -7,16 +7,26 @@ namespace ThemeIsle\QuickWP; +use ThemeIsle\QuickWP\API; + /** * Main class. */ class Main { + /** + * API instance. + * + * @var API + */ + private $api; /** * Constructor. */ public function __construct() { $this->register_hooks(); + + $this->api = new API(); } /** @@ -62,5 +72,13 @@ public function enqueue_assets() { ); wp_set_script_translations( 'quickwp', 'quickwp' ); + + wp_localize_script( + 'quickwp', + 'quickwp', + array( + 'api' => $this->api->get_endpoint(), + ) + ); } } diff --git a/phpstan.neon b/phpstan.neon index 743b918..4b001c4 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -4,5 +4,6 @@ parameters: - %currentWorkingDirectory%/inc bootstrapFiles: - %currentWorkingDirectory%/tests/php/static-analysis-stubs/quickwp.php + checkGenericClassInNonGenericObjectType: false includes: - %currentWorkingDirectory%/vendor/szepeviktor/phpstan-wordpress/extension.neon \ No newline at end of file diff --git a/quickwp.php b/quickwp.php index c935f7e..0509da0 100644 --- a/quickwp.php +++ b/quickwp.php @@ -21,6 +21,7 @@ define( 'QUICKWP_URL', plugins_url( '/', __FILE__ ) ); define( 'QUICKWP_PATH', __DIR__ ); define( 'QUICKWP_VERSION', '1.0.0' ); +define( 'QUICKWP_API', 'https://4ab6-103-217-244-109.ngrok-free.app/api/' ); $vendor_file = QUICKWP_PATH . '/vendor/autoload.php'; diff --git a/src/App.js b/src/App.js index 3a32fa8..2538258 100644 --- a/src/App.js +++ b/src/App.js @@ -15,9 +15,21 @@ import Header from './parts/Header'; const App = () => { const isEditorLoading = useIsSiteEditorLoading(); - const currentStep = useSelect( ( select ) => - select( 'quickwp/data' ).getStep() - ); + const { + currentStep, + hasError + } = useSelect( select => { + const { + getStep, + hasError + } = select( 'quickwp/data' ); + + return { + currentStep: getStep(), + hasError: hasError() + }; + }); + const StepControls = currentStep?.view || null; if ( isEditorLoading ) { @@ -31,6 +43,22 @@ const App = () => { ); } + if ( hasError ) { + return ( +
+

+ { __( + 'There has been an error. Please refresh the page and try again.', + 'quickwp' + ) } +

+
+ ); + } + return (
{ const currentStep = useSelect( ( select ) => select( 'quickwp/data' ).getStep() ); - const { setStep } = useDispatch( 'quickwp/data' ); const currentPage = STEPS.findIndex( ( step ) => step.value === currentStep.value @@ -43,7 +42,7 @@ const PageControl = () => { } aria-label={ STEPS[ page ]?.label } className="text-fg h-6 w-6 !min-w-0 !min-h-0" - onClick={ () => setStep( STEPS[ page ]?.value ) } + onClick={ () => {} } /> ) ) } diff --git a/src/parts/ColorPalette.js b/src/parts/ColorPalette.js index 9f3f58a..2b74682 100644 --- a/src/parts/ColorPalette.js +++ b/src/parts/ColorPalette.js @@ -5,8 +5,7 @@ import { __ } from '@wordpress/i18n'; import { Button, - ColorIndicator, - TextControl + ColorIndicator } from '@wordpress/components'; import { @@ -19,80 +18,36 @@ import { */ import TemplatePreview from '../components/TemplatePreview'; -const palette = [ - { - slug: 'ti-bg', - color: '#FFFFFF', - name: 'Background' - }, - { - slug: 'ti-fg', - color: '#202020', - name: 'Text' - }, - { - slug: 'ti-accent', - color: '#325ce8', - name: 'Accent' - }, - { - slug: 'ti-accent-secondary', - color: '#1B47DA', - name: 'Accent Secondary' - }, - { - slug: 'ti-bg-inv', - color: '#1A1919', - name: 'Dark Background' - }, - { - slug: 'ti-bg-alt', - color: '#f7f7f3', - name: 'Background Alt' - }, - { - slug: 'ti-fg-alt', - color: '#FBFBFB', - name: 'Inverted Text' - } -]; - const ColorPalette = () => { const { onContinue } = useDispatch( 'quickwp/data' ); - const { template } = useSelect( ( select ) => { + const { + palette, + template + } = useSelect( ( select ) => { const { getBlocks } = select( 'core/block-editor' ); + const { getColorPalette } = select( 'quickwp/data' ); return { + palette: getColorPalette(), template: getBlocks() }; }); + const onSubmit = async() => { + onContinue(); + }; + return (

{ __( - 'Let\'s give your site a color that fits to your brand. What is your primary brand color?', + 'Let\'s give your site a color that fits to your brand.', 'quickwp' ) }

-
- - - {} } - /> -
-
{ palette.map( ( color ) => ( { ) ) }
-
diff --git a/src/parts/ImageSuggestions.js b/src/parts/ImageSuggestions.js index 12210d4..2484e70 100644 --- a/src/parts/ImageSuggestions.js +++ b/src/parts/ImageSuggestions.js @@ -15,25 +15,24 @@ import { Icon } from '@wordpress/components'; -import { useDispatch } from '@wordpress/data'; +import { + useDispatch, + useSelect +} from '@wordpress/data'; import { useState } from '@wordpress/element'; -const dummy = [ - 'https://mystock.themeisle.com/wp-content/uploads/2022/06/52172949534_aa8893fd8f_c.jpg?v=1', - 'https://mystock.themeisle.com/wp-content/uploads/2022/06/52171667257_e4c90f0a38_c.jpg?v=2', - 'https://mystock.themeisle.com/wp-content/uploads/2022/06/52172949534_aa8893fd8f_c.jpg?v=3', - 'https://mystock.themeisle.com/wp-content/uploads/2022/06/52172949534_aa8893fd8f_c.jpg?v=4', - 'https://mystock.themeisle.com/wp-content/uploads/2022/06/52172949534_aa8893fd8f_c.jpg?v=5', - 'https://mystock.themeisle.com/wp-content/uploads/2022/06/52171667257_e4c90f0a38_c.jpg?v=6', - 'https://mystock.themeisle.com/wp-content/uploads/2022/06/52171667257_e4c90f0a38_c.jpg?v=7', - 'https://mystock.themeisle.com/wp-content/uploads/2022/06/52172949534_aa8893fd8f_c.jpg?v=8', - 'https://mystock.themeisle.com/wp-content/uploads/2022/06/52171667257_e4c90f0a38_c.jpg?v=9' -]; - const ImageSuggestions = () => { const [ value, setValue ] = useState([]); + const { images } = useSelect( select => { + const images = select( 'quickwp/data' ).getImages() || []; + + return { + images: images.slice( 0, 9 ) + }; + }); + const { onContinue } = useDispatch( 'quickwp/data' ); return ( @@ -53,24 +52,24 @@ const ImageSuggestions = () => {
- { dummy.map( ( image, index ) => ( + { images.map( ( image, index ) => (
{ - if ( value.includes( image ) ) { - setValue( value.filter( ( item ) => item !== image ) ); + if ( value.includes( image.id ) ) { + setValue( value.filter( ( item ) => item !== image.id ) ); } else { - setValue([ ...value, image ]); + setValue([ ...value, image.id ]); } }} > - { value.includes( image ) && ( + { value.includes( image.id ) && (
{
) ) } diff --git a/src/parts/SiteDescription.js b/src/parts/SiteDescription.js index 0924054..82b6fab 100644 --- a/src/parts/SiteDescription.js +++ b/src/parts/SiteDescription.js @@ -3,23 +3,41 @@ */ import { __ } from '@wordpress/i18n'; -import { Button, TextareaControl } from '@wordpress/components'; +import { + Button, + TextareaControl +} from '@wordpress/components'; -import { useDispatch } from '@wordpress/data'; +import { + useDispatch, + useSelect +} from '@wordpress/data'; -import { useState } from '@wordpress/element'; - -import { ENTER } from '@wordpress/keycodes'; +/** + * Internal dependencies. + */ +import { generateImages } from '../utils'; const SiteDescription = () => { - const [ value, setValue ] = useState( '' ); + const { siteDescription } = useSelect( select => { + return { + siteDescription: select( 'quickwp/data' ).getSiteDescription() + }; + }); - const { onContinue } = useDispatch( 'quickwp/data' ); + const { + onContinue, + setSiteDescription + } = useDispatch( 'quickwp/data' ); - const onEnter = ( e ) => { - if ( ENTER === e.keyCode && !! value ) { - onContinue(); + const onSubmit = async() => { + if ( 4 > siteDescription?.length ) { + return; } + + generateImages(); + + onContinue(); }; return ( @@ -37,17 +55,16 @@ const SiteDescription = () => { 'e.g. Our brand, LifeUp, specializes in life coaching seminars targeted towards businesses in the UK. In addition to group seminars, we offer personal training and one-on-one calls to cater to a variety of needs.', 'quickwp' ) } - value={ value } - onChange={ setValue } - onKeyDown={ onEnter } + value={ siteDescription } + onChange={ setSiteDescription } hideLabelFromVision={ true } autoFocus={ true } /> diff --git a/src/parts/SiteTopic.js b/src/parts/SiteTopic.js index 5ae5259..067006b 100644 --- a/src/parts/SiteTopic.js +++ b/src/parts/SiteTopic.js @@ -3,22 +3,48 @@ */ import { __ } from '@wordpress/i18n'; -import { Button, TextControl } from '@wordpress/components'; +import { + Button, + TextControl +} from '@wordpress/components'; -import { useDispatch } from '@wordpress/data'; - -import { useState } from '@wordpress/element'; +import { + useDispatch, + useSelect +} from '@wordpress/data'; import { ENTER } from '@wordpress/keycodes'; +/** + * Internal dependencies. + */ +import { generateColorPalette } from '../utils'; + const SiteTopic = () => { - const [ value, setValue ] = useState( '' ); + const { siteTopic } = useSelect( select => { + return { + siteTopic: select( 'quickwp/data' ).getSiteTopic() + }; + }); - const { onContinue } = useDispatch( 'quickwp/data' ); + const { + onContinue, + setSiteTopic + } = useDispatch( 'quickwp/data' ); + + const onSubmit = async() => { + if ( 4 > siteTopic?.length ) { + return; + } + + // At this point, we start the color palette generation process. + generateColorPalette(); + onContinue(); + }; const onEnter = ( e ) => { - if ( ENTER === e.keyCode && !! value ) { - onContinue(); + if ( ENTER === e.keyCode && !! siteTopic ) { + onSubmit(); } }; @@ -37,8 +63,8 @@ const SiteTopic = () => { 'e.g. Web Agency, Tech Reviewer', 'quickwp' ) } - value={ value } - onChange={ setValue } + value={ siteTopic } + onChange={ setSiteTopic } onKeyDown={ onEnter } hideLabelFromVision={ true } autoFocus={ true } @@ -46,8 +72,8 @@ const SiteTopic = () => { diff --git a/src/store.js b/src/store.js index 578a8c1..8814c5a 100644 --- a/src/store.js +++ b/src/store.js @@ -1,7 +1,16 @@ /** * WordPress dependencies. */ -import { createReduxStore, register } from '@wordpress/data'; +import apiFetch from '@wordpress/api-fetch'; + +import { + createReduxStore, + dispatch, + register, + select +} from '@wordpress/data'; + +import { addQueryArgs } from '@wordpress/url'; /** * Internal dependencies. @@ -9,7 +18,24 @@ import { createReduxStore, register } from '@wordpress/data'; import STEPS from './steps'; const DEFAULT_STATE = { - step: 0 + step: 0, + processes: { + 'color_palette': { + 'thread_id': null, + 'run_id': null, + hasLoaded: false + }, + 'images': { + 'thread_id': null, + 'run_id': null, + hasLoaded: false + } + }, + images: [], + siteTopic: null, + siteDescription: null, + hasError: false, + colorPalette: [] }; const actions = { @@ -52,6 +78,57 @@ const actions = { return ({ dispatch }) => { dispatch( actions.nextStep() ); }; + }, + setSiteTopic( siteTopic ) { + return { + type: 'SET_SITE_TOPIC', + siteTopic + }; + }, + setSiteDescription( siteDescription ) { + return { + type: 'SET_SITE_DESCRIPTION', + siteDescription + }; + }, + setColorPalette( colorPalette ) { + return { + type: 'SET_COLOR_PALETTE', + colorPalette + }; + }, + setError( hasError ) { + return { + type: 'SET_ERROR', + hasError + }; + }, + setImages( images ) { + return { + type: 'SET_IMAGES', + images + }; + }, + setThreadID( item, threadID ) { + return { + type: 'SET_THREAD_ID', + item, + threadID + }; + }, + setRunID( item, runID ) { + return { + type: 'SET_RUN_ID', + item, + runID + }; + }, + setProcessStatus( item, hasLoaded ) { + return { + type: 'SET_PROCESS_STATUS', + item, + hasLoaded + }; } }; @@ -67,6 +144,64 @@ const store = createReduxStore( 'quickwp/data', { ...state, step }; + case 'SET_SITE_TOPIC': + return { + ...state, + siteTopic: action.siteTopic + }; + case 'SET_SITE_DESCRIPTION': + return { + ...state, + siteDescription: action.siteDescription + }; + case 'SET_COLOR_PALETTE': + return { + ...state, + colorPalette: action.colorPalette + }; + case 'SET_ERROR': + return { + ...state, + hasError: action.hasError + }; + case 'SET_IMAGES': + return { + ...state, + images: action.images + }; + case 'SET_THREAD_ID': + return { + ...state, + processes: { + ...state.processes, + [ action.item ]: { + ...state.processes[ action.item ], + 'thread_id': action.threadID + } + } + }; + case 'SET_RUN_ID': + return { + ...state, + processes: { + ...state.processes, + [ action.item ]: { + ...state.processes[ action.item ], + 'run_id': action.runID + } + } + }; + case 'SET_PROCESS_STATUS': + return { + ...state, + processes: { + ...state.processes, + [ action.item ]: { + ...state.processes[ action.item ], + hasLoaded: action.hasLoaded + } + } + }; } return state; @@ -77,6 +212,30 @@ const store = createReduxStore( 'quickwp/data', { selectors: { getStep( state ) { return STEPS[ state.step ]; + }, + getSiteTopic( state ) { + return state.siteTopic; + }, + getSiteDescription( state ) { + return state.siteDescription; + }, + getColorPalette( state ) { + return state.colorPalette; + }, + hasError( state ) { + return state.hasError; + }, + getImages( state ) { + return state.images; + }, + getThreadID( state, item ) { + return state.processes[ item ]?.thread_id; + }, + getRunID( state, item ) { + return state.processes[ item ]?.run_id; + }, + getProcessStatus( state, item ) { + return state.processes[ item ]?.hasLoaded; } } }); diff --git a/src/style.scss b/src/style.scss index d76976a..850684d 100644 --- a/src/style.scss +++ b/src/style.scss @@ -29,6 +29,10 @@ &:disabled { @apply opacity-50; } + + .components-spinner { + @apply m-0 ml-3; + } } &.is-secondary { diff --git a/src/utils.js b/src/utils.js index b5a7059..5047ec9 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,8 +1,17 @@ /** * WordPress dependencies */ +import apiFetch from '@wordpress/api-fetch'; + +import { + dispatch, + select +} from '@wordpress/data'; + import { SVG, Circle, G, Path } from '@wordpress/primitives'; +import { addQueryArgs } from '@wordpress/url'; + export const PageControlIcon = ({ isFilled = false }) => { return ( { ); }; + +const sendEvent = async( data ) => { + const { + setRunID, + setThreadID + } = dispatch( 'quickwp/data' ); + + const response = await apiFetch({ + path: `${ window.quickwp.api }/send`, + method: 'POST', + data: { ...data } + }); + + setThreadID( data.step, response.thread_id ); + + setRunID( data.step, response.id ); +}; + +const getEvent = async( type ) => { + const threadID = select( 'quickwp/data' ).getThreadID( type ); + + const response = await apiFetch({ + path: addQueryArgs( `${ window.quickwp.api }/get`, { + 'thread_id': threadID + }) + }); + + return response; +}; + +const getEventStatus = async( type ) => { + const threadID = select( 'quickwp/data' ).getThreadID( type ); + const runID = select( 'quickwp/data' ).getRunID( type ); + const { setProcessStatus } = dispatch( 'quickwp/data' ); + + const response = await apiFetch({ + path: addQueryArgs( `${ window.quickwp.api }/status`, { + 'thread_id': threadID, + 'run_id': runID + }) + }); + + if ( 'completed' !== response.status ) { + return false; + } + + setProcessStatus( type, true ); + + return true; +}; + +const extractPalette = response => { + const runID = select( 'quickwp/data' ).getRunID( 'color_palette' ); + const { setError } = dispatch( 'quickwp/data' ); + + const { data } = response; + + const target = data.find( item => item.run_id === runID ); + + const jsonString = target.content[0].text.value; + + let matches = jsonString.match( /\[(.|\n)*?\]/ ); + + if ( matches && matches[0]) { + let jsonArrayString = matches[0]; + + let jsonObject; + try { + jsonObject = JSON.parse( jsonArrayString ); + } catch ( error ) { + setError( true ); + return false; + } + + return jsonObject; + } else { + setError( true ); + return false; + } +}; + +const fetchImages = async( request ) => { + const runID = select( 'quickwp/data' ).getRunID( 'images' ); + const { setImages } = dispatch( 'quickwp/data' ); + + const { data } = request; + + const target = data.find( item => item.run_id === runID ); + + const query = target.content[0].text.value; + + const response = await apiFetch({ + path: addQueryArgs( `${ window.quickwp.api }/images`, { + query + }) + }); + + + setImages( response?.photos ); +}; + +const awaitEvent = async( type ) => { + const hasResolved = await getEventStatus( type ); + + if ( ! hasResolved ) { + await new Promise( resolve => setTimeout( resolve, 3000 ) ); + await awaitEvent( type ); + return; + } +}; + +export const generateColorPalette = async() => { + const siteTopic = select( 'quickwp/data' ).getSiteTopic(); + + const { + setColorPalette, + setProcessStatus + } = dispatch( 'quickwp/data' ); + + await sendEvent({ + step: 'color_palette', + message: siteTopic + }); + + await awaitEvent( 'color_palette' ); + + const response = await getEvent( 'color_palette' ); + + const palette = extractPalette( response ); + + setColorPalette( palette ); + setProcessStatus( 'color_palette', true ); +}; + +export const generateImages = async() => { + const siteDescription = select( 'quickwp/data' ).getSiteDescription(); + + const { + setImages, + setProcessStatus + } = dispatch( 'quickwp/data' ); + + await sendEvent({ + step: 'images', + message: siteDescription + }); + + await awaitEvent( 'images' ); + + const response = await getEvent( 'images' ); + + await fetchImages( response ); + + setProcessStatus( 'images', true ); +}; diff --git a/tests/php/static-analysis-stubs/quickwp.php b/tests/php/static-analysis-stubs/quickwp.php index 109fd56..7f6783e 100644 --- a/tests/php/static-analysis-stubs/quickwp.php +++ b/tests/php/static-analysis-stubs/quickwp.php @@ -8,4 +8,5 @@ define( 'QUICKWP_BASEFILE', __FILE__ ); define( 'QUICKWP_URL', plugins_url( '/', __FILE__ ) ); define( 'QUICKWP_PATH', dirname( __FILE__ ) ); -define( 'QUICKWP_VERSION', '1.0.0' ); \ No newline at end of file +define( 'QUICKWP_VERSION', '1.0.0' ); +define( 'QUICKWP_API', 'quickwp/v1' ); \ No newline at end of file