110 lines
2.9 KiB
JavaScript
110 lines
2.9 KiB
JavaScript
/**
|
|
* External dependencies
|
|
*/
|
|
import { select, dispatch } from '@wordpress/data-controls';
|
|
import { addQueryArgs } from '@wordpress/url';
|
|
|
|
/**
|
|
* Internal dependencies
|
|
*/
|
|
import { receiveCollection, receiveCollectionError } from './actions';
|
|
import { STORE_KEY as SCHEMA_STORE_KEY } from '../schema/constants';
|
|
import { STORE_KEY, DEFAULT_EMPTY_ARRAY } from './constants';
|
|
import { apiFetchWithHeaders } from './controls';
|
|
|
|
/**
|
|
* Check if the store needs invalidating due to a change in last modified headers.
|
|
*
|
|
* @param {number} timestamp Last update timestamp.
|
|
*/
|
|
function* invalidateModifiedCollection( timestamp ) {
|
|
const lastModified = yield select( STORE_KEY, 'getCollectionLastModified' );
|
|
|
|
if ( ! lastModified ) {
|
|
yield dispatch( STORE_KEY, 'receiveLastModified', timestamp );
|
|
} else if ( timestamp > lastModified ) {
|
|
yield dispatch( STORE_KEY, 'invalidateResolutionForStore' );
|
|
yield dispatch( STORE_KEY, 'receiveLastModified', timestamp );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Resolver for retrieving a collection via a api route.
|
|
*
|
|
* @param {string} namespace
|
|
* @param {string} resourceName
|
|
* @param {Object} query
|
|
* @param {Array} ids
|
|
*/
|
|
export function* getCollection( namespace, resourceName, query, ids ) {
|
|
const route = yield select(
|
|
SCHEMA_STORE_KEY,
|
|
'getRoute',
|
|
namespace,
|
|
resourceName,
|
|
ids
|
|
);
|
|
const queryString = addQueryArgs( '', query );
|
|
if ( ! route ) {
|
|
yield receiveCollection( namespace, resourceName, queryString, ids );
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const {
|
|
items = DEFAULT_EMPTY_ARRAY,
|
|
headers,
|
|
} = yield apiFetchWithHeaders( route + queryString );
|
|
|
|
if ( headers && headers.get && headers.has( 'last-modified' ) ) {
|
|
// Do any invalidation before the collection is received to prevent
|
|
// this query running again.
|
|
yield invalidateModifiedCollection(
|
|
parseInt( headers.get( 'last-modified' ), 10 )
|
|
);
|
|
}
|
|
|
|
yield receiveCollection( namespace, resourceName, queryString, ids, {
|
|
items,
|
|
headers,
|
|
} );
|
|
} catch ( error ) {
|
|
yield receiveCollectionError(
|
|
namespace,
|
|
resourceName,
|
|
queryString,
|
|
ids,
|
|
error
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Resolver for retrieving a specific collection header for the given arguments
|
|
*
|
|
* Note: This triggers the `getCollection` resolver if it hasn't been resolved
|
|
* yet.
|
|
*
|
|
* @param {string} header
|
|
* @param {string} namespace
|
|
* @param {string} resourceName
|
|
* @param {Object} query
|
|
* @param {Array} ids
|
|
*/
|
|
export function* getCollectionHeader(
|
|
header,
|
|
namespace,
|
|
resourceName,
|
|
query,
|
|
ids
|
|
) {
|
|
// feed the correct number of args in for the select so we don't resolve
|
|
// unnecessarily. Any undefined args will be excluded. This is important
|
|
// because resolver resolution is cached by both number and value of args.
|
|
const args = [ namespace, resourceName, query, ids ].filter(
|
|
( arg ) => typeof arg !== 'undefined'
|
|
);
|
|
//we call this simply to do any resolution of the collection if necessary.
|
|
yield select( STORE_KEY, 'getCollection', ...args );
|
|
}
|