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

Update: Make template names and descriptions dynamic. #43862

Merged
merged 1 commit into from
Sep 21, 2022
Merged
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
227 changes: 227 additions & 0 deletions lib/compat/wordpress-6.1/block-template-utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,136 @@ function gutenberg_get_block_template( $id, $template_type = 'wp_template' ) {
return apply_filters( 'get_block_template', $block_template, $id, $template_type );
}

/**
* Builds the title and description of a post specific template based on the underlying referenced post.

Choose a reason for hiding this comment

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

"post-specific"

* Mutates the underlying template object.
*
* @access private

Choose a reason for hiding this comment

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

Add a @since 6.1.0 above the access.

* @internal
*
* @param string $post_type Post type e.g.: page, post, product.
* @param string $slug Slug of the post e.g.: a-story-about-shoes.
* @param WP_Block_Template $template Template to mutate adding the description and title computed.
*

Choose a reason for hiding this comment

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

Remove this extra line between params and return.

* @return boolean Returns true if the referenced post was found and false otherwise.
*/
function _gutenberg_build_title_and_description_for_single_post_type_block_template( $post_type, $slug, WP_Block_Template $template ) {
ntsekouras marked this conversation as resolved.
Show resolved Hide resolved

Choose a reason for hiding this comment

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

Update the function prefixes from gutenberg to wp.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the prefix has to be renamed in the backport PR, not the Gutenberg PR. This function will disappear from Gutenberg code when the minimum WP version for Gutenberg increases to 6.2

$post_type_object = get_post_type_object( $post_type );

$posts = get_posts(
array(
'name' => $slug,
'post_type' => $post_type,
)
);
if ( empty( $posts ) ) {
jorgefilipecosta marked this conversation as resolved.
Show resolved Hide resolved
$template->title = sprintf(
// translators: Represents the title of a user's custom template in the Site Editor referencing a post that was not found, where %1$s is the singular name of a post type and %2$s is the slug of the deleted post, e.g. "Not found: Page(hello)".
__( 'Not found: %1$s(%2$s)', 'gutenberg' ),

Choose a reason for hiding this comment

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

Remove the gutenberg domain, as this will fallback to Core domain.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the domain has to be removed in the backport PR, not the Gutenberg PR. This function will disappear from Gutenberg code when the minimum WP version for Gutenberg increases to 6.2

$post_type_object->labels->singular_name,
$slug
);
return false;
}

$post_title = $posts[0]->post_title;

$template->title = sprintf(
// translators: Represents the title of a user's custom template in the Site Editor, where %1$s is the singular name of a post type and %2$s is the name of the post, e.g. "Page: Hello".
__( '%1$s: %2$s', 'gutenberg' ),
$post_type_object->labels->singular_name,
$post_title
);
$template->description = sprintf(
// translators: Represents the description of a user's custom template in the Site Editor, e.g. "Template for Page: Hello".
__( 'Template for %1$s', 'gutenberg' ),

Choose a reason for hiding this comment

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

I think this can be just %s since there's only one replacement.

$post_title
);

$posts_with_same_title = get_posts(
array(
'title' => $post_title,
'post_type' => $post_type,
'post_status' => 'publish',
)
);
if ( count( $posts_with_same_title ) > 1 ) {
$template->title = sprintf(
// translators: Represents the title of a user's custom template in the Site Editor, where %1$s is the template title and %2$s is the slug of the post type, e.g. "Project: Hello (project_type)".
__( '%1$s (%2$s)', 'gutenberg' ),
$template->title,
$slug
);
}
return true;
}

/**
* Builds the title and description of a taxonomy specific template based on the underlying entity referenced.

Choose a reason for hiding this comment

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

"taxonomy-specific"

* Mutates the underlying template object.
*
* @access private

Choose a reason for hiding this comment

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

Add @since 6.1.0

* @internal
*
* @param string $taxonomy Identifier of the taxonomy, e.g.: category.
* @param string $slug Slug of the term, e.g.: shoes.
* @param WP_Block_Template $template Template to mutate adding the description and title computed.
*
* @return boolean True if an term referenced was found and false otherwise.

Choose a reason for hiding this comment

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

"an term" -> "a term"

*/
function _gutenberg_build_title_and_description_for_taxonomy_block_template( $taxonomy, $slug, WP_Block_Template $template ) {
$taxonomy_object = get_taxonomy( $taxonomy );

$terms = get_terms(
array(
'taxonomy' => $taxonomy,
'hide_empty' => false,
'slug' => $slug,
)
);

if ( empty( $terms ) ) {
$template->title = sprintf(
// translators: Represents the title of a user's custom template in the Site Editor referencing a taxonomy term that was not found, where %1$s is the singular name of a taxonomy and %2$s is the slug of the deleted term, e.g. "Not found: Category(shoes)".
__( 'Not found: %1$s(%2$s)', 'gutenberg' ),
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't there be a space before the opening parenthesis?

-Not found: %1$s(%2$s)
+Not found: %1$s (%2$s)

Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment for the other occurrence of %1$s(%2$s)

$taxonomy_object->labels->singular_name,
$slug
);
return false;
}

$term_title = $terms[0]->name;

$template->title = sprintf(
// translators: Represents the title of a user's custom template in the Site Editor, where %1$s is the singular name of a taxonomy and %2$s is the name of the term, e.g. "Category: shoes".
__( '%1$s: %2$s', 'gutenberg' ),
$taxonomy_object->labels->singular_name,
$term_title
);
$template->description = sprintf(
// translators: Represents the description of a user's custom template in the Site Editor, e.g. "Template for Category: shoes".
__( 'Template for %1$s', 'gutenberg' ),
$term_title
);

$terms_with_same_title = get_terms(
array(
'taxonomy' => $taxonomy,
'hide_empty' => false,
'name' => $term_title,
)
);
if ( count( $terms_with_same_title ) > 1 ) {
$template->title = sprintf(
// translators: Represents the title of a user's custom template in the Site Editor, where %1$s is the template title and %2$s is the slug of the taxonomy, e.g. "Category: shoes (product_tag)".
__( '%1$s (%2$s)', 'gutenberg' ),
$template->title,
$slug
);
}
return true;
}

/**
* Build a unified template object based a post Object.
*
Expand Down Expand Up @@ -305,6 +435,103 @@ function gutenberg_build_block_template_result_from_post( $post ) {
$template->area = $type_terms[0]->name;
}
}
// If it is a block template without description and without title or with title equal to the slug.
if ( 'wp_template' === $post->post_type && empty( $template->description ) && ( empty( $template->title ) || $template->title === $template->slug ) ) {
jorgefilipecosta marked this conversation as resolved.
Show resolved Hide resolved
$matches = array();
// If it is a block template for a single author, page, post, tag, category, custom post type or custom taxonomy.
if ( preg_match( '/(author|page|single|tag|category|taxonomy)-(.+)/', $template->slug, $matches ) ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should the reg. expr. start with ^?

$type = $matches[1];
$slug_remaining = $matches[2];
switch ( $type ) {
case 'author':
$nice_name = $slug_remaining;
$users = get_users(
Copy link
Contributor

Choose a reason for hiding this comment

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

I haven't checked the query well here, but in my testing when I updated a nicename of a contributor user, it didn't find the user.. Can you reproduce?

Copy link
Member Author

Choose a reason for hiding this comment

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

Issue fixed 👍

array(
'capability' => 'edit_posts',
'search' => $nice_name,
'search_columns' => array( 'user_nicename' ),
'fields' => 'display_name',
)
);

if ( empty( $users ) ) {
$template->title = sprintf(
// translators: Represents the title of a user's custom template in the Site Editor referencing a deleted author, where %s is the author's nicename, e.g. "Deleted author: jane-doe".
__( 'Deleted author: %s', 'gutenberg' ),
$nice_name
);
} else {
$author_name = $users[0];

$template->title = sprintf(
// translators: Represents the title of a user's custom template in the Site Editor, where %s is the author's name, e.g. "Author: Jane Doe".
__( 'Author: %s', 'gutenberg' ),
$author_name
);
$template->description = sprintf(
// translators: Represents the description of a user's custom template in the Site Editor, e.g. "Template for Author: Jane Doe".
__( 'Template for %1$s', 'gutenberg' ),
$author_name
);

$users_with_same_name = get_users(
array(
'capability' => 'edit_posts',
'search' => $author_name,
'search_columns' => array( 'display_name' ),
'fields' => 'display_name',
)
);
if ( count( $users_with_same_name ) > 1 ) {
$template->title = sprintf(
// translators: Represents the title of a user's custom template in the Site Editor, where %1$s is the template title of an author template and %2$s is the nicename of the author, e.g. "Author: Jorge (jorge-costa)".

Choose a reason for hiding this comment

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

I think we want to change the example author here to something anonymous, like the other references.

Let's use "Jane Doe (jane-doe)"

__( '%1$s (%2$s)', 'gutenberg' ),
$template->title,
$nice_name
);
}
}
break;
case 'page':
_gutenberg_build_title_and_description_for_single_post_type_block_template( 'page', $slug_remaining, $template );
break;
case 'single':
$post_types = get_post_types();
foreach ( $post_types as $post_type ) {
$post_type_length = strlen( $post_type ) + 1;
// If $slug_remaining starts with $post_type followed by a hyphen.
if ( 0 === strncmp( $slug_remaining, $post_type . '-', $post_type_length ) ) {
$slug = substr( $slug_remaining, $post_type_length, strlen( $slug_remaining ) );
$found = _gutenberg_build_title_and_description_for_single_post_type_block_template( $post_type, $slug, $template );
if ( $found ) {
break;
}
}
}
break;
case 'tag':
_gutenberg_build_title_and_description_for_taxonomy_block_template( 'post_tag', $slug_remaining, $template );
break;
case 'category':
_gutenberg_build_title_and_description_for_taxonomy_block_template( 'category', $slug_remaining, $template );
break;
case 'taxonomy':
$taxonomies = get_taxonomies();
foreach ( $taxonomies as $taxonomy ) {
$taxonomy_length = strlen( $taxonomy ) + 1;
// If $slug_remaining starts with $taxonomy followed by a hyphen.
if ( 0 === strncmp( $slug_remaining, $taxonomy . '-', $taxonomy_length ) ) {
$slug = substr( $slug_remaining, $taxonomy_length, strlen( $slug_remaining ) );
$found = _gutenberg_build_title_and_description_for_taxonomy_block_template( $taxonomy, $slug, $template );
if ( $found ) {
break;
}
}
}
break;
}
}
}
return $template;
}

Expand Down
97 changes: 9 additions & 88 deletions packages/edit-site/src/components/add-new-template/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -253,29 +253,10 @@ export const usePostTypeMenuItems = ( onClickMenuItem ) => {
};
},
getSpecificTemplate: ( suggestion ) => {
let title = sprintf(
// translators: Represents the title of a user's custom template in the Site Editor, where %1$s is the singular name of a post type and %2$s is the name of the post, e.g. "Page: Hello".
__( '%1$s: %2$s' ),
labels.singular_name,
suggestion.name
);
const description = sprintf(
// translators: Represents the description of a user's custom template in the Site Editor, e.g. "Template for Page: Hello"
__( 'Template for %1$s' ),
title
);
if ( _needsUniqueIdentifier ) {
title = sprintf(
// translators: Represents the title of a user's custom template in the Site Editor, where %1$s is the template title and %2$s is the slug of the post type, e.g. "Project: Hello (project_type)"
__( '%1$s (%2$s)' ),
title,
slug
);
}
const templateSlug = `${ templatePrefixes[ slug ] }-${ suggestion.slug }`;
return {
title,
description,
slug: `${ templatePrefixes[ slug ] }-${ suggestion.slug }`,
title: templateSlug,
slug: templateSlug,
templatePrefix: templatePrefixes[ slug ],
};
},
Expand Down Expand Up @@ -417,29 +398,10 @@ export const useTaxonomiesMenuItems = ( onClickMenuItem ) => {
};
},
getSpecificTemplate: ( suggestion ) => {
let title = sprintf(
// translators: Represents the title of a user's custom template in the Site Editor, where %1$s is the singular name of a taxonomy and %2$s is the name of the term, e.g. "Category: shoes".
__( '%1$s: %2$s' ),
labels.singular_name,
suggestion.name
);
const description = sprintf(
// translators: Represents the description of a user's custom template in the Site Editor, e.g. "Template for Category: shoes"
__( 'Template for %1$s' ),
title
);
if ( _needsUniqueIdentifier ) {
title = sprintf(
// translators: Represents the title of a user's custom template in the Site Editor, where %1$s is the template title and %2$s is the slug of the taxonomy, e.g. "Category: shoes (product_tag)"
__( '%1$s (%2$s)' ),
title,
slug
);
}
const templateSlug = `${ templatePrefixes[ slug ] }-${ suggestion.slug }`;
return {
title,
description,
slug: `${ templatePrefixes[ slug ] }-${ suggestion.slug }`,
title: templateSlug,
slug: templateSlug,
templatePrefix: templatePrefixes[ slug ],
};
},
Expand Down Expand Up @@ -480,26 +442,6 @@ export const useTaxonomiesMenuItems = ( onClickMenuItem ) => {
return taxonomiesMenuItems;
};

function useAuthorNeedsUniqueIndentifier() {
const authors = useSelect(
( select ) =>
select( coreStore ).getUsers( { who: 'authors', per_page: -1 } ),
[]
);
const authorsCountByName = useMemo( () => {
return ( authors || [] ).reduce( ( authorsCount, { name } ) => {
authorsCount[ name ] = ( authorsCount[ name ] || 0 ) + 1;
return authorsCount;
}, {} );
}, [ authors ] );
return useCallback(
( name ) => {
return authorsCountByName[ name ] > 1;
},
[ authorsCountByName ]
);
}

const USE_AUTHOR_MENU_ITEM_TEMPLATE_PREFIX = { user: 'author' };
const USE_AUTHOR_MENU_ITEM_QUERY_PARAMETERS = { user: { who: 'authors' } };
export function useAuthorMenuItem( onClickMenuItem ) {
Expand All @@ -510,7 +452,6 @@ export function useAuthorMenuItem( onClickMenuItem ) {
USE_AUTHOR_MENU_ITEM_TEMPLATE_PREFIX,
USE_AUTHOR_MENU_ITEM_QUERY_PARAMETERS
);
const authorNeedsUniqueId = useAuthorNeedsUniqueIndentifier();
let authorMenuItem = defaultTemplateTypes?.find(
( { slug } ) => slug === 'author'
);
Expand Down Expand Up @@ -542,30 +483,10 @@ export function useAuthorMenuItem( onClickMenuItem ) {
};
},
getSpecificTemplate: ( suggestion ) => {
const needsUniqueId = authorNeedsUniqueId(
suggestion.name
);
const title = needsUniqueId
? sprintf(
// translators: %1$s: Represents the name of an author e.g: "Jorge", %2$s: Represents the slug of an author e.g: "author-jorge-slug".
__( 'Author: %1$s (%2$s)' ),
suggestion.name,
suggestion.slug
)
: sprintf(
// translators: %s: Represents the name of an author e.g: "Jorge".
__( 'Author: %s' ),
suggestion.name
);
const description = sprintf(
// translators: %s: Represents the name of an author e.g: "Jorge".
__( 'Template for Author: %s' ),
suggestion.name
);
const templateSlug = `author-${ suggestion.slug }`;
return {
title,
description,
slug: `author-${ suggestion.slug }`,
title: templateSlug,
slug: templateSlug,
templatePrefix: 'author',
};
},
Expand Down