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

Fix: #127 - generate unique ID upon creation #128

Merged
merged 1 commit into from
Jul 13, 2016

Conversation

torleif
Copy link
Contributor

@torleif torleif commented Jun 20, 2016

Fixes front end components that require a unique ID. Duplicate IDs in the DOM is invalid HTML.

@helpfulrobot
Copy link

@torleif, thanks for your PR! By analyzing the blame information on this pull request, I identified @wilr to be a potential reviewer

@@ -109,6 +109,7 @@ public function editablesegment()
}
if (class_exists($className) && is_subclass_of($className, 'Widget')) {
$obj = new $className();
$obj->write();// generate new id
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you move the comment above the line? The indentation on this also needs to be fixed up to match the rest of the code style

@torleif
Copy link
Contributor Author

torleif commented Jun 20, 2016

Thanks for the feedback, I'll have to get into the habit of using spaces instead of tabs!

@stevie-mayhew
Copy link
Contributor

I'd be happy to merge this as it seems like a reasonable fix, but there is also a lot of handling for "new-" components already in place. If we make this change we should remove the "new-" handling from the code base and rely on the fact we always have an instantiated object.

However I feel like it might be better to not save these at this point and instead change the way we handle the IDs for the interior elements so that they reflect the "new" state. @dhensby any thoughts here?

@torleif
Copy link
Contributor Author

torleif commented Jun 21, 2016

@stevie-mayhew it looks like there's some JavaScript that uses maxid to work out the next id of the widget by referencing "new-". This could be dangerous as if two people create a widget at the same.

I'll try and figure out what this javascript does

@torleif
Copy link
Contributor Author

torleif commented Jun 21, 2016

From what I can tell WidgetAreaEditor.js checks if it's a new element and replaces the ID of what it thinks it is going to be. Though pretty poorly given #127 creates incorrect IDs for textareas.

The JavaScript doesn't break with the code given that there's no new elements, though it can be tidied up by removing the references of "new-":

            insertWidgetEditor: function(response) {
                $('#usedWidgets-'+$(this).attr('name')).append(response);
                this.rewriteWidgetAreaAttributes();
            },

Let me know if you want me to put this in the PR

@stevie-mayhew
Copy link
Contributor

If nobody else has any objections I'm going to merge this later today.

@dhensby
Copy link
Contributor

dhensby commented Jul 7, 2016

The risk here is if validation is on for the object and that fails, then no one can ever start creating a widget again...

@torleif
Copy link
Contributor Author

torleif commented Jul 11, 2016

@dhensby I've added a validation check before writing the dataobject. I guess there would be some people who don't want a blank DataObject written for validation purposes, but note this would enable duplicate IDs if the CMS author creates two or more objects that can't be blank.

@dhensby
Copy link
Contributor

dhensby commented Jul 11, 2016

this feels so nasty...

@tractorcow any thoughts?


NB: this is why using increment-ing DB IDs is not a good idea for models :(

@torleif
Copy link
Contributor Author

torleif commented Jul 12, 2016

A tidier solution would be to throw an exception if the blank object is invalid. This would prevent duplicate IDs and force the developer to use widgets that can't be blank.

Thoughts?

@tractorcow
Copy link
Contributor

tractorcow commented Jul 12, 2016

The trouble is an empty widget perhaps isn't valid... thus it could become impossible to create a valid widget in any context.

Have you explored perhaps dis-entangling HTML form ID from the dataobject ID? Why does it need to be that field, rather than say an automatically generated FormID property that can default to a uniqid() ?

That way it can exist (and be stored in a hidden field) prior to being written to the database.

@tractorcow
Copy link
Contributor

In Widget::CMSEditor() you can do something like

// ...
$this->FormID = $this->FormID ?: uniqid();
$outputFields->push(new HiddenField('Widget[' + $this->FormID + '][FormID]', $this->FormID));
foreach ($fields as $field) {
    // ...
    $name = preg_replace("/([A-Za-z0-9\-_]+)/", "Widget[" . $this->FormID . "][\\1]", $name); 
    // ...
}

@@ -109,6 +109,10 @@ public function editablesegment()
}
if (class_exists($className) && is_subclass_of($className, 'Widget')) {
$obj = new $className();
// generate new id
if(method_exists($obj, 'doValidate') && $obj->doValidate()->valid()) {
Copy link
Contributor

@tractorcow tractorcow Jul 12, 2016

Choose a reason for hiding this comment

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

Redundant check in any case... DataObject observably has a doValidate method :)

@torleif
Copy link
Contributor Author

torleif commented Jul 12, 2016

@tractorcow thanks, I've made a patch to do something similar to what you've suggested. Works as expected in MSIE, FFx and Chrome.

@tractorcow
Copy link
Contributor

How necessary is the ->write() that you've added? We still have the problem of writing invalid records before they are populated with content.

E.g. widgets that fail validation if Title is empty.

@torleif
Copy link
Contributor Author

torleif commented Jul 12, 2016

@tractorcow sweet - I didn't reset the patch before committing. ops.

@dhensby
Copy link
Contributor

dhensby commented Jul 13, 2016

Great, please can you squash the commits and check the indentation around CMSEditor declaration? then we are good to merge

Fixes front end components that require a unique ID. Duplicate IDs in the DOM is invalid HTML.

Fix: silverstripe#127 - code formatting

Check validation before writing

BUG fixes duplicate ID issue Fixes silverstripe#127

BUG fixes duplicate ID issue Fixes silverstripe#127

remove unneeded write()

Fix: silverstripe#127 - generate unique ID upon creation
@torleif
Copy link
Contributor Author

torleif commented Jul 13, 2016

@dhensby sweet, rebase has been completed and works as expected

dhensby added a commit to dhensby/silverstripe-widgets that referenced this pull request Jul 13, 2016
@dhensby
Copy link
Contributor

dhensby commented Jul 13, 2016

thanks

@dhensby dhensby merged commit 987d293 into silverstripe:master Jul 13, 2016
@torleif torleif deleted the patch-2 branch July 14, 2016 04:26
@tractorcow
Copy link
Contributor

Good job @torleif

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.

5 participants