Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

move fetch-link-suggestions to a separate file and refactor it #28843

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 4 additions & 85 deletions packages/edit-navigation/src/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
/**
* External dependencies
*/
import { map, set, flatten, partialRight } from 'lodash';

import { set } from 'lodash';
/**
* WordPress dependencies
*/
Expand All @@ -12,17 +11,14 @@ import {
} from '@wordpress/block-library';
import { render } from '@wordpress/element';
import { createHigherOrderComponent } from '@wordpress/compose';
import { __ } from '@wordpress/i18n';
import apiFetch from '@wordpress/api-fetch';
import { addQueryArgs } from '@wordpress/url';
import { decodeEntities } from '@wordpress/html-entities';
import { addFilter } from '@wordpress/hooks';

/**
* Internal dependencies
*/
import Layout from './components/layout';
import './store';
import fetchLinkSuggestions from './utils/fetch-link-suggestions';

function disableInsertingNonNavigationBlocks( settings, name ) {
if ( ! [ 'core/navigation', 'core/navigation-link' ].includes( name ) ) {
Expand Down Expand Up @@ -66,81 +62,6 @@ const removeNavigationBlockEditUnsupportedFeatures = createHigherOrderComponent(
'removeNavigationBlockEditUnsupportedFeatures'
);

/**
* Fetches link suggestions from the API. This function is an exact copy of a function found at:
*
* packages/editor/src/components/provider/index.js
*
* It seems like there is no suitable package to import this from. Ideally it would be either part of core-data.
* Until we refactor it, just copying the code is the simplest solution.
*
* @param {string} search
* @param {Object} [searchArguments]
* @param {number} [searchArguments.isInitialSuggestions]
* @param {number} [searchArguments.type]
* @param {number} [searchArguments.subtype]
* @param {Object} [editorSettings]
* @param {boolean} [editorSettings.disablePostFormats=false]
* @return {Promise<Object[]>} List of suggestions
*/
const fetchLinkSuggestions = (
search,
{ isInitialSuggestions, type, subtype } = {},
{ disablePostFormats = false } = {}
) => {
const perPage = isInitialSuggestions ? 3 : 20;

const queries = [];

if ( ! type || type === 'post' ) {
queries.push(
apiFetch( {
path: addQueryArgs( '/wp/v2/search', {
search,
per_page: perPage,
type: 'post',
subtype,
} ),
} ).catch( () => [] ) // fail by returning no results
);
}

if ( ! type || type === 'term' ) {
queries.push(
apiFetch( {
path: addQueryArgs( '/wp/v2/search', {
search,
per_page: perPage,
type: 'term',
subtype,
} ),
} ).catch( () => [] )
);
}

if ( ! disablePostFormats && ( ! type || type === 'post-format' ) ) {
queries.push(
apiFetch( {
path: addQueryArgs( '/wp/v2/search', {
search,
per_page: perPage,
type: 'post-format',
subtype,
} ),
} ).catch( () => [] )
);
}

return Promise.all( queries ).then( ( results ) => {
return map( flatten( results ).slice( 0, perPage ), ( result ) => ( {
id: result.id,
url: result.url,
title: decodeEntities( result.title ) || __( '(no title)' ),
type: result.subtype || result.type,
} ) );
} );
};

export function initialize( id, settings ) {
if ( ! settings.blockNavMenus ) {
addFilter(
Expand Down Expand Up @@ -168,10 +89,8 @@ export function initialize( id, settings ) {
__experimentalRegisterExperimentalCoreBlocks();
}

settings.__experimentalFetchLinkSuggestions = partialRight(
fetchLinkSuggestions,
settings
);
settings.__experimentalFetchLinkSuggestions = () =>
fetchLinkSuggestions( settings );

render(
<Layout blockEditorSettings={ settings } />,
Expand Down
86 changes: 86 additions & 0 deletions packages/edit-navigation/src/utils/fetch-link-suggestions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/**
* WordPress dependencies
*/
import apiFetch from '@wordpress/api-fetch';
import { addQueryArgs } from '@wordpress/url';
/**
* External dependencies
*/
import { flatten, slice, map as _map, flow } from 'lodash';
import { decodeEntities } from '@wordpress/html-entities';
import { __ } from '@wordpress/i18n';

// curried map operator with flipped arguments
const map = ( mapFunction ) => ( array ) => _map( array, mapFunction );

const toSuggestionLinkObj = ( { id, url, title, subType, type } ) => ( {
id,
url,
title: decodeEntities( title ) || __( '(no title)' ),
type: subType || type,
} );
const toApiFetchBody = ( { search, subtype, perPage } ) => ( linkType ) => ( {
path: addQueryArgs( '/wp/v2/search', {
search,
per_page: perPage,
type: linkType,
subtype,
} ),
} );
// eslint-disable-next-line no-console
const exceptionHandler = ( e ) => ( console.error( e ), [] );
const getAllLinkTypes = ( disablePostFormats ) => {
const baseLinkTypes = [ 'post', 'term' ];
return disablePostFormats
? baseLinkTypes
: [ ...baseLinkTypes, 'post-format' ];
};
/**
* Fetches link suggestions from the API. This function is an exact copy of a function found at:
*
* packages/editor/src/components/provider/index.js
*
* It seems like there is no suitable package to import this from. Ideally it would be either part of core-data.
* Until we refactor it, just copying the code is the simplest solution.
*
* @param {string} search
* @param {Object} [searchArguments]
* @param {number} [searchArguments.isInitialSuggestions]
* @param {number} [searchArguments.type]
* @param {number} [searchArguments.subtype]
* @param {Object} [editorSettings]
* @param {boolean} [editorSettings.disablePostFormats=false]
* @return {Promise<Object[]>} List of suggestions
*/
export default (
search,
{ isInitialSuggestions, type, subtype } = {},
{ disablePostFormats = false } = {}
) => {
const perPage = isInitialSuggestions ? 3 : 20;
const typesOfLinksToFetch = type
? [ type ]
: getAllLinkTypes( disablePostFormats );

// assign piped functions producing api call
const toReqBody = flow( [
toApiFetchBody( { search, subtype, perPage } ),
apiFetch,
( promise ) => promise.catch( exceptionHandler ),
] );

// assign piped functions producing suggestion links objects from server response data
const toSuggestionLinksObjects = flow( [
flatten,
( x ) => slice( x, 0, perPage ),
toSuggestionLinkObj,
] );

// for each link type, build transformations describing how to make a call to API and then format response
const fromLinkTypeToSuggestionLinksObjects = map(
[ toReqBody, async ( x ) => await x, toSuggestionLinksObjects ],
map
);

return flow( fromLinkTypeToSuggestionLinksObjects )( typesOfLinksToFetch );
};