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

Add some new url helper functions #10885

Merged
merged 4 commits into from
Oct 23, 2018
Merged

Add some new url helper functions #10885

merged 4 commits into from
Oct 23, 2018

Conversation

swissspidy
Copy link
Member

@swissspidy swissspidy commented Oct 21, 2018

Description

As discussed in #10862 and outlined in #10879, some more URL modification helpers might make sense. I figured when I add getQueryArg and hasQueryArg I might just as well complete the group with removeQueryArgs.

How has this been tested?

I included a few unit tests for each of the new functions.

Screenshots

Types of changes

Extends @wordpress/url package with new functions getQueryArg, hasQueryArg, and removeQueryArgs,

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows the accessibility standards.
  • My code has proper inline documentation.

Fixes #10879.

@gziolo
Copy link
Member

gziolo commented Oct 22, 2018

Are there any places in the existing codebase which could benefit from using those new methods?

Can we document those newly introduced methods in README file?

@gziolo gziolo added the [Package] Url /packages/url label Oct 22, 2018
@swissspidy
Copy link
Member Author

@gziolo Good input, updated the readme accordingly!

  • hasQueryArg()
    Could certainly be used in Add user locale api-fetch middleware #10862.
    Generally useful little helper for developers.
  • getQueryArg()
    PHP equivalent proposed for WordPress core, so here we'd have some parity.
    Generally useful little helper for developers.
  • removeQueryArgs()
    PHP equivalent exists in WordPress core, so here we'd have some parity.
    Generally useful little helper for developers, for example when someone wants to remove the query arg added by Add user locale api-fetch middleware #10862 or modify any other URL.

Perhaps there are more potential usages in Gutenberg, but it's tough to say after a quick glance.


Looking at getStablePath() in createPreloadingMiddleware(), that one could be added to this package too. The stringify method in qs even has a sort option, so this could be leveraged as well.

export function sortQueryArgs( url ) {
  const queryStringIndex = url.indexOf( '?' );
  const query = queryStringIndex !== -1 ? parse( url.substr( queryStringIndex + 1 ) ) : {};
  const baseUrl = queryStringIndex !== -1 ? url.substr( 0, queryStringIndex ) : url;

  return baseUrl + '?' + stringify( query, { sort: (a, b) => a.localeCompare( b ) } );
}

@chrisvanpatten
Copy link
Contributor

I wonder if getQueryArg and hasQueryArg could be used in the pagination middleware to detect per_page=-1? I think right now it's based on a string match, which is fine, but this is definitely nicer.

@swissspidy
Copy link
Member Author

Indeed requestContainsUnboundedQuery() could use getQueryArg() for sure:

const requestContainsUnboundedQuery = ( options ) => {
	const pathIsUnbounded = options.path && getQueryArg( options.path, 'per_page' ) === '-1';
	const urlIsUnbounded = options.url && getQueryArg( options.url, 'per_page' ) === '-1';

	return pathIsUnbounded || urlIsUnbounded;
};

It's actually safer than just using indexOf( 'per_page=-1' ), because that also matches my_custom_items_per_page=-1, which is what I'd consider a bug.

@gziolo gziolo requested a review from a team October 22, 2018 13:45
@gziolo
Copy link
Member

gziolo commented Oct 22, 2018

Let's make sure we open follow-up issue when this one lands. It should be labeled with Good first issue :)

* @return {boolean} Whether or not the URL contains the query aeg.
*/
export function hasQueryArg( url, arg ) {
return typeof getQueryArg( url, arg ) !== 'undefined';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: Comparing to undefined directly should work just as well, and saves some characters. typeof would be useful only if trying to reference a variable which hasn't been initialized, or if we were targeting pre-ES5 browsers (IE7) where undefined could be overwritten.

* @return {Array|string} Query arg value.
*/
export function getQueryArg( url, arg ) {
const queryStringIndex = url.indexOf( '?' );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given repetition in the file, seems we could do for an internal utility function(s) which return the parsed query and/or return the query fragment from a string.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it's not really nice at the moment. I think we should address this in a following PR.

* @return {Array|string} Query arg value.
*/
export function getQueryArg( url, arg ) {
const queryStringIndex = url.indexOf( '?' );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or just use a proper URL parsers, like require( 'url' ).parse( url ).search

https://nodejs.org/docs/latest/api/url.html#url_url_search

† I assume reason we haven't is due to size of the imported (stub) module.

* Determines whether the URL contains a given query arg.
*
* @param {string} url URL
* @param {...string} arg Query arg name
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not used as a spread parameter.

/**
* Determines whether the URL contains a given query arg.
*
* @param {string} url URL
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per standards examples, we've avoided bothering to align the @param type with @return.

https://make.wordpress.org/core/handbook/best-practices/inline-documentation-standards/javascript/#functions

const query = queryStringIndex !== -1 ? parse( url.substr( queryStringIndex + 1 ) ) : {};
const baseUrl = queryStringIndex !== -1 ? url.substr( 0, queryStringIndex ) : url;

args.forEach( ( arg ) => delete query[ arg ] );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Guess we've not brought in Lodash yet as a dependency of this one, but good use-case for omit.

https://lodash.com/docs/4.17.10#omit

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I looked into this one but since it's a one-liner it shouldn't be necessary to add a dependency just for this use case.

* Removes arguments from the query string of the url
*
* @param {string} url URL
* @param {string} args Query Args
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is used as a spread parameter.

@@ -25,6 +25,15 @@ const newURL = addQueryArgs( 'https://google.com', { q: 'test' } ); // https://

// Prepends 'http://' to URLs that are probably mean to have them
const actualURL = prependHTTP( 'wordpress.org' ); // http://wordpress.org

// Gets a single query arg from the given URL.
const foo = getQueryArg( 'https://wordpress.org?foo=bar&bar=baz' ); // bar
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Example is wrong; needs second parameter.

packages/url/src/test/index.test.js Show resolved Hide resolved
Copy link
Member

@aduth aduth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice utilities 👍

Meta-note: As best I can tell, this closes #10879, but we've not included magic keywords to automate the closure.

@swissspidy
Copy link
Member Author

See -> Fixes in PR description for auto closing 🙂

@aduth
Copy link
Member

aduth commented Oct 22, 2018

Oh, I missed it there at the bottom 👍

@aduth
Copy link
Member

aduth commented Oct 22, 2018

Oh, you changed it! 🤦‍♂️

@gziolo gziolo added this to the 4.2 milestone Oct 23, 2018
@gziolo gziolo merged commit 898f2f7 into master Oct 23, 2018
@gziolo gziolo deleted the add/url-helpers branch October 23, 2018 06:12
@gziolo
Copy link
Member

gziolo commented Oct 23, 2018

See -> Fixes in PR description for auto closing 🙂

It worked out 👍 Thanks for addressing my feedback 💯

daniloercoli added a commit that referenced this pull request Oct 23, 2018
…rnmobile/fix-validation-errorrs-after-block-splitting

* 'master' of https://github.com/WordPress/gutenberg:
  Add some new url helper functions (#10885)
  Components: Avoid SlotFill props destructuring (#10921)
  Update Package Changelogs (#10887)
  chore(release): publish
  Update plugin version to 4.1 RC2. (#10893)
swissspidy added a commit that referenced this pull request Oct 23, 2018
danielbachhuber pushed a commit that referenced this pull request Oct 23, 2018
* Add user locale api-fetch middleware

See #10811

* Don't modify existing _locale query arg

* Add changelog entry

* Update changelog

* Use new hasQueryArg helper function

See #10885.

* Match on simply the route path, instead of malformed query param

* Fully mock embedding test

* Skip the embedding test until we can make the travis env mock the requests

* Skip demo test too, for now
antpb pushed a commit to antpb/gutenberg that referenced this pull request Oct 26, 2018
* Add some new url helper functions

See WordPress#10879.

* Document new functions in readme

* Improve docs

* Add another test for removeQueryArgs()
antpb pushed a commit to antpb/gutenberg that referenced this pull request Oct 26, 2018
* Add user locale api-fetch middleware

See WordPress#10811

* Don't modify existing _locale query arg

* Add changelog entry

* Update changelog

* Use new hasQueryArg helper function

See WordPress#10885.

* Match on simply the route path, instead of malformed query param

* Fully mock embedding test

* Skip the embedding test until we can make the travis env mock the requests

* Skip demo test too, for now
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Package] Url /packages/url
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants