Skip to content

Commit

Permalink
Move the templates prePersist logic to core-data (#27464)
Browse files Browse the repository at this point in the history
  • Loading branch information
youknowriad authored Dec 7, 2020
1 parent d675049 commit 85173ee
Show file tree
Hide file tree
Showing 5 changed files with 226 additions and 109 deletions.
27 changes: 11 additions & 16 deletions packages/core-data/src/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -501,20 +501,15 @@ export function* saveEntityRecord(
yield receiveAutosaves( persistedRecord.id, updatedRecord );
}
} else {
// Auto drafts should be converted to drafts on explicit saves and we should not respect their default title,
// but some plugins break with this behavior so we can't filter it on the server.
let data = record;
if (
kind === 'postType' &&
persistedRecord &&
persistedRecord.status === 'auto-draft'
) {
if ( ! data.status ) {
data = { ...data, status: 'draft' };
}
if ( ! data.title || data.title === 'Auto Draft' ) {
data = { ...data, title: '' };
}
let edits = record;
if ( entity.__unstablePrePersist ) {
edits = {
...edits,
...entity.__unstablePrePersist(
persistedRecord,
edits
),
};
}

// Get the full local version of the record before the update,
Expand All @@ -536,7 +531,7 @@ export function* saveEntityRecord(
yield receiveEntityRecords(
kind,
name,
{ ...persistedEntity, ...data },
{ ...persistedEntity, ...edits },
undefined,
// This must be false or it will trigger a GET request in parallel to the PUT/POST below
false
Expand All @@ -545,7 +540,7 @@ export function* saveEntityRecord(
updatedRecord = yield apiFetch( {
path,
method: recordId ? 'PUT' : 'POST',
data,
data: edits,
} );
yield receiveEntityRecords(
kind,
Expand Down
75 changes: 65 additions & 10 deletions packages/core-data/src/entities.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,69 @@ export const kinds = [
{ name: 'taxonomy', loadEntities: loadTaxonomyEntities },
];

/**
* Returns a function to be used to retrieve the title of a given post type record.
*
* @param {string} postTypeName PostType name.
* @return {Function} getTitle.
*/
export const getPostTypeTitle = ( postTypeName ) => ( record ) => {
if ( [ 'wp_template_part', 'wp_template' ].includes( postTypeName ) ) {
return (
record?.title?.rendered || record?.title || startCase( record.slug )
);
}
return record?.title?.rendered || record?.title || String( record.id );
};

/**
* Returns a function to be used to retrieve extra edits to apply before persisting a post type.
*
* @param {string} postTypeName PostType name.
* @return {Function} prePersistHandler.
*/
export const getPostTypePrePersistHandler = ( postTypeName ) => (
persistedRecord,
edits
) => {
const newEdits = {};

// Fix template titles.
if (
[ 'wp_template', 'wp_template_part' ].includes( postTypeName ) &&
! edits.title &&
! persistedRecord.title
) {
newEdits.title = persistedRecord
? getPostTypeTitle( postTypeName )( persistedRecord )
: edits.slug;
}

// Templates and template parts can only be published.
if ( [ 'wp_template', 'wp_template_part' ].includes( postTypeName ) ) {
newEdits.status = 'publish';
}

if ( persistedRecord?.status === 'auto-draft' ) {
// Saving an auto-draft should create a draft by default.
if ( ! edits.status && ! newEdits.status ) {
newEdits.status = 'draft';
}

// Fix the auto-draft default title.
if (
( ! edits.title || edits.title === 'Auto Draft' ) &&
! newEdits.title &&
( ! persistedRecord?.title ||
persistedRecord?.title === 'Auto Draft' )
) {
newEdits.title = '';
}
}

return newEdits;
};

/**
* Returns the list of post type entities.
*
Expand All @@ -133,16 +196,8 @@ function* loadPostTypeEntities() {
selectionEnd: true,
},
mergedEdits: { meta: true },
getTitle( record ) {
if ( [ 'wp_template_part', 'wp_template' ].includes( name ) ) {
return (
record?.title?.rendered ||
record?.title ||
startCase( record.slug )
);
}
return record?.title?.rendered || record?.title || record.id;
},
getTitle: getPostTypeTitle( name ),
__unstablePrePersist: getPostTypePrePersistHandler( name ),
};
} );
}
Expand Down
142 changes: 141 additions & 1 deletion packages/core-data/src/test/entities.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
/**
* Internal dependencies
*/
import { getMethodName, defaultEntities, getKindEntities } from '../entities';
import {
getMethodName,
defaultEntities,
getKindEntities,
getPostTypeTitle,
getPostTypePrePersistHandler,
} from '../entities';
import { addEntities } from '../actions';

describe( 'getMethodName', () => {
Expand Down Expand Up @@ -79,3 +85,137 @@ describe( 'getKindEntities', () => {
expect( end ).toEqual( { done: true, value: fetchedEntities } );
} );
} );

describe( 'getPostTypeTitle', () => {
it( 'should prefer the rendered value for titles for regular post types', async () => {
const record = {
id: 10,
title: {
rendered: 'My Title',
},
};
expect( getPostTypeTitle( 'post' )( record ) ).toBe( 'My Title' );
} );

it( "should fallback to the title if it's a string", async () => {
const record = {
id: 10,
title: 'My Title',
};
expect( getPostTypeTitle( 'post' )( record ) ).toBe( 'My Title' );
} );

it( 'should fallback to the id if no title provided', async () => {
const record = {
id: 10,
};
expect( getPostTypeTitle( 'post' )( record ) ).toBe( '10' );
} );

it( 'should prefer the rendered value for titles for templates', async () => {
const record = {
slug: 'single',
title: {
rendered: 'My Template',
},
};
expect( getPostTypeTitle( 'wp_template' )( record ) ).toBe(
'My Template'
);
} );

it( "should fallback to the title if it's a string for templates", async () => {
const record = {
slug: 'single',
title: 'My Template',
};
expect( getPostTypeTitle( 'wp_template' )( record ) ).toBe(
'My Template'
);
} );

it( 'should fallback to the slug if no title provided', async () => {
const record = {
slug: 'single',
};
expect( getPostTypeTitle( 'wp_template' )( record ) ).toBe( 'Single' );
} );
} );

describe( 'getPostTypePrePersistHandler', () => {
it( 'set the status to draft and empty the title when saving auto-draft posts', () => {
let record = {
status: 'auto-draft',
};
const edits = {};
expect(
getPostTypePrePersistHandler( 'post' )( record, edits )
).toEqual( {
status: 'draft',
title: '',
} );

record = {
status: 'publish',
};
expect(
getPostTypePrePersistHandler( 'post' )( record, edits )
).toEqual( {} );

record = {
status: 'auto-draft',
title: 'Auto Draft',
};
expect(
getPostTypePrePersistHandler( 'post' )( record, edits )
).toEqual( {
status: 'draft',
title: '',
} );

record = {
status: 'publish',
title: 'My Title',
};
expect(
getPostTypePrePersistHandler( 'post' )( record, edits )
).toEqual( {} );
} );

it( 'should set the status of templates to publish and fix the title', () => {
let record = {
status: 'auto-draft',
slug: 'single',
};
const edits = {};
expect(
getPostTypePrePersistHandler( 'wp_template' )( record, edits )
).toEqual( {
status: 'publish',
title: 'Single',
} );

record = {
status: 'auto-draft',
};
expect(
getPostTypePrePersistHandler( 'wp_template_part' )( record, edits )
).toEqual( {
status: 'publish',
title: '',
} );

record = {
status: 'auto-draft',
slug: 'single',
title: {
rendered: 'My title',
},
};
expect(
getPostTypePrePersistHandler( 'wp_template' )( record, edits )
).toEqual( {
status: 'publish',
} );
} );
} );
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
/**
* WordPress dependencies
*/
import { EntitiesSavedStates, store as editorStore } from '@wordpress/editor';
import { EntitiesSavedStates } from '@wordpress/editor';
import { Button } from '@wordpress/components';
import { store as coreStore } from '@wordpress/core-data';
import { useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { useSelect, useDispatch } from '@wordpress/data';
import { useDispatch } from '@wordpress/data';

/**
* Internal dependencies
Expand All @@ -20,18 +19,6 @@ function TemplateSaveButton() {
setIsEntitiesReviewPanelOpen,
] = useState( false );
const { setIsEditingTemplate } = useDispatch( editPostStore );
const { editEntityRecord } = useDispatch( coreStore );
const { getTemplateInfo, getEditedEntityRecord } = useSelect(
( select ) => {
return {
getTemplateInfo: select( editorStore )
.__experimentalGetTemplateInfo,
getEditedEntityRecord: select( coreStore )
.getEditedEntityRecord,
};
},
[]
);
return (
<>
<Button onClick={ () => setIsEditingTemplate( false ) } isTertiary>
Expand All @@ -48,44 +35,6 @@ function TemplateSaveButton() {
<EntitiesSavedStates
isOpen={ isEntitiesReviewPanelOpen }
close={ ( entities ) => {
// The logic here should be abstracted in the entities save handler/component
// and not duplicated accross multi-entity save behavior.
if ( entities?.length ) {
entities.forEach( ( entity ) => {
const edits = {};
if (
entity.kind === 'postType' &&
entity.name === 'wp_template'
) {
const record = getEditedEntityRecord(
entity.kind,
entity.name,
entity.key
);
edits.title =
getTemplateInfo( record ).title ??
entity.title ??
record.slug;
}

if (
entity.kind === 'postType' &&
[
'wp_template',
'wp_template_part',
].includes( entity.name )
) {
edits.status = 'publish';
}

editEntityRecord(
entity.kind,
entity.name,
entity.key,
edits
);
} );
}
setIsEntitiesReviewPanelOpen( false );
if ( entities?.length ) {
setIsEditingTemplate( false );
Expand Down
Loading

0 comments on commit 85173ee

Please sign in to comment.