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

NEW SingleRecordAdmin class for editing one record at a time #1842

Merged

Conversation

GuySartorelli
Copy link
Member

@GuySartorelli GuySartorelli commented Oct 25, 2024

Note that there may be some methods still on LeftAndMain that will be migrated into this class, such as save() which isn't used by CMSMain or ModelAdmin - but moving those will be handled by #1763 once the bulk of the other refactoring has been completed. This is to reduce the chance of regressions in areas that still need to be refactored.

TODO

  1. CMS 5 PR to deprecate SiteConfigLeftAndMain::save_siteconfig() and LeftAndMain.tree_config

Issue

Comment on lines -23 to +19
private static $tree_class = Member::class;
private static $model_class = Member::class;
Copy link
Member Author

Choose a reason for hiding this comment

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

See change in LeftAndMain

code/LeftAndMain.php Show resolved Hide resolved
Comment on lines -1227 to -1238
if ($record->hasMethod('getCMSCompositeValidator')) {
// As of framework v4.7, a CompositeValidator is always available form a DataObject, but it may be
// empty (which is fine)
$form->setValidator($record->getCMSCompositeValidator());
} elseif ($record->hasMethod('getCMSValidator')) {
// BC support for framework < v4.7
$validator = $record->getCMSValidator();

// The clientside (mainly LeftAndMain*.js) rely on ajax responses
// which can be evaluated as javascript, hence we need
// to override any global changes to the validation handler.
if ($validator) {
$form->setValidator($validator);
}
Copy link
Member Author

Choose a reason for hiding this comment

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

All of this boils down to $form->setValidator($record->getCMSCompositeValidator()), because all DataObject classes have that method, and $record will always be a DataObject.

} else {
$form->unsetValidator();
}
Copy link
Member Author

Choose a reason for hiding this comment

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

That method just sets it null anyway so even if somehow getCMSCompositeValidator() returned null (which it can't) the result would be the same.

Copy link
Member Author

Choose a reason for hiding this comment

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

Anything removed from this class was either not necessary (likely related to legacy CMS 3 or older code that no longer exists) or is already being done in one of the superclasses.

{
parent::init();
if (!$this->getResponse()->isRedirect()) {
$this->setCurrentPageID(Security::getCurrentUser()->ID);
Copy link
Member Author

Choose a reason for hiding this comment

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

Moving this into init instead of getEditForm so it takes affect for all actions on this controller (including any that might be added through extensions).

Skipping for redirects because at that point we're not doing anything in this controller anyway.

private static $tree_class = Group::class;
private static $model_class = Group::class;
Copy link
Member Author

Choose a reason for hiding this comment

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

I strongly suspect this config doesn't actually do anything for this class, but checking that is out of scope for this PR. I'm just updating it to the config that LeftAndMain expects.

Comment on lines 13 to 19
/**
* Determines if there should be a single record in the database that this admin edits.
*
* If this is not true, you need to provide a mechanism to tell the form which record it should be editing.
* This could be an action (e.g. edit/$ID), or could be based on something about the current member, etc.
*/
private static bool $only_one_record = true;
Copy link
Member Author

Choose a reason for hiding this comment

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

This is for SiteConfig style functionality - but since CMSProfileController is explicitly for the current member and not the one member in the database, it needs to be configurable.

code/SingleRecordAdmin.php Show resolved Hide resolved
@GuySartorelli GuySartorelli force-pushed the pulls/3/singlerecordadmin branch 2 times, most recently from bdb2aeb to 1f41d29 Compare October 30, 2024 03:00
code/LeftAndMain.php Show resolved Hide resolved
* If this is not true, you need to provide a mechanism to tell the form which record it should be editing.
* This could be an action (e.g. edit/$ID), or could be based on something about the current member, etc.
*/
private static bool $only_one_record = true;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
private static bool $only_one_record = true;
private static bool $single_record = true;

$only_one_record sounds weird to me, almost implying that it's a bad thing :-)

Copy link
Member Author

@GuySartorelli GuySartorelli Oct 30, 2024

Choose a reason for hiding this comment

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

Feel free to suggest an alternative name.

Copy link
Member

Choose a reason for hiding this comment

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

$single_record

Copy link
Member Author

@GuySartorelli GuySartorelli Oct 30, 2024

Choose a reason for hiding this comment

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

How about only_single_record? Or restrict_to_single_record? I want the name to be fairly clear that it's saying "there should only ever be one record of this type" when set to true.

Or maybe dynamic_current_record? As in "this will dynamically fetch the current record without you telling it what the ID is"?

Copy link
Member

Choose a reason for hiding this comment

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

$restrict_to_single_record sounds good

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

code/SingleRecordAdmin.php Show resolved Hide resolved
/**
* Determines if there should be a single record in the database that this admin edits.
*
* If this is not true, you need to provide a mechanism to tell the form which record it should be editing.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* If this is not true, you need to provide a mechanism to tell the form which record it should be editing.
* If false, you need to provide a mechanism to tell the form, usually via getEditForm(), which record it should be editing.

Copy link
Member Author

Choose a reason for hiding this comment

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

Will make the change, but won't add "usually via getEditForm()" because the only scenario we've actually implemented doesn't do it that way.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

}

// Get the current member locale so we can see if it changes
$member = Member::get()->byID($data['ID']);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
$member = Member::get()->byID($data['ID']);
$member = Member::get()->byID($id);

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

$this->httpError(404);
// Make sure the ID is a positive number
$id = $data['ID'] ?? null;
if (!is_numeric($id) || $id < 1) {
Copy link
Member

Choose a reason for hiding this comment

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

Should validate that it's an int (or string int), is_numeric() will allow a float

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

return parent::getRecord($id);
}

protected function getSingleRecord(): ?DataObject
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
protected function getSingleRecord(): ?DataObject
private function getSingleRecord(): ?DataObject

If we're providing only_one_record and allow_new_record and implementing logic to do stuff based on how they're set, why would anyone need to override this in a subclass? Things should be private unless there's an immediate need to make it protected.

Copy link
Member Author

Choose a reason for hiding this comment

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

Please see the docs where overriding this method is explicitly mentioned as a way to provide more complex behaviour for getting this record.

if (!$id) {
return $this->getSingleRecord();
}
return parent::getRecord($id);
Copy link
Member

Choose a reason for hiding this comment

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

What's the scenario where $id is truthy? Seems like we should be throwing an exception here instead?

Copy link
Member Author

@GuySartorelli GuySartorelli Nov 1, 2024

Choose a reason for hiding this comment

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

$id is truthy if an ID is passed in. So we either want the "single record" based on the configuration (where a null or 0 is passed in), or we want the specified record if a specific ID is passed in.

@GuySartorelli
Copy link
Member Author

GuySartorelli commented Oct 30, 2024

I've responded to the bits that are relevant for the CMS 5 PRs. I'll make the requested changes that are agreed upon after the CMS 5 PRs have been merged and I can rebase on top of them.

@GuySartorelli GuySartorelli force-pushed the pulls/3/singlerecordadmin branch 3 times, most recently from 880a411 to eddc85e Compare November 1, 2024 01:33
@GuySartorelli GuySartorelli marked this pull request as ready for review November 1, 2024 01:33
@GuySartorelli GuySartorelli force-pushed the pulls/3/singlerecordadmin branch from eddc85e to 23d0e89 Compare November 6, 2024 01:29
@emteknetnz emteknetnz merged commit f7ff272 into silverstripe:3 Nov 6, 2024
9 of 11 checks passed
@emteknetnz emteknetnz deleted the pulls/3/singlerecordadmin branch November 6, 2024 04:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants