Comments

sun’s picture

StatusFileSize
new29.71 KB

This patch introduces new #type 'machine_name'.

Motivation: It is our intention to make more APIs and modules implement machine-readable names, since that is required to make stored data exportable (e.g., to build Features). However, it is quite complex to implement a proper machine-readable name form element handling in modules currently. Thus, if we want to change the situation, then we have to make it easy.

This patch makes it trivial. And at the same time, it introduces a standard way to handle machine names.

A minimum implementation looks this way:

  $form['name'] = array(
    '#type' => 'textfield',
    '#title' => t('Name'),
    '#default_value' => $vocabulary->name,
  );
  $form['machine_name'] = array(
    '#type' => 'machine_name',
    '#default_value' => $vocabulary->machine_name,
    '#machine_name_exists' => 'taxonomy_vocabulary_machine_name_load',
  );

The second form element is entirely sufficient to get a fully-fledged "Machine name" form element in the form, which uses the 'name' field as source. That is, because the #type 'machine_name' element is expanded into the following:

  $form['machine_name'] = array(
    '#type' => 'machine_name',
    '#default_value' => $vocabulary->machine_name,
    '#title' => t('Machine-readable name'),
    '#description' => t('A unique machine-readable name. Can only contain lowercase letters, numbers, and underscores.'),
    '#required' => TRUE,
    '#maxlength' => 64,
    '#machine_name_source' => array('name'),
    '#machine_name_label' => t('Machine name'),
    '#machine_name_pattern' => '[^a-z0-9_]+',
    '#machine_name_replace' => '_',
    '#machine_name_exists' => 'taxonomy_vocabulary_machine_name_load',
  );

First hunk in this patch is a stop-gap variant of #763376: Not validated form values appear in $form_state, just to make this patch possible.

Status: Needs review » Needs work

The last submitted patch, drupal.machine.1.patch, failed testing.

sun’s picture

Category: task » bug
Status: Needs work » Needs review
StatusFileSize
new33.32 KB

The test failure for Date type configuration is a very nice example of even Drupal core getting machine names wrong. There's not even a single form validation handler for a date type's machine name currently. Which turns this issue into a bug report.

Status: Needs review » Needs work

The last submitted patch, drupal.machine.3.patch, failed testing.

sun’s picture

Status: Needs work » Needs review
StatusFileSize
new34.03 KB

wow, I didn't expect to reveal so many bugs with this issue.

tobiasb’s picture

Status: Needs review » Needs work
StatusFileSize
new40.82 KB

Now my version:

different to suns patch:

// Verify that using a menu_name that is too long results in a validation message.
    $this->assertRaw(t('!name cannot be longer than %max characters but is currently %length characters long.', array(
      '!name' => t('Menu name'),
      '%max' => MENU_MAX_MENU_NAME_LENGTH_UI,
      '%length' => drupal_strlen($menu_name),
    )));

// Verify that no validation error is given for menu_name length.
    $this->assertNoRaw(t('!name cannot be longer than %max characters but is currently %length characters long.', array(
      '!name' => t('Menu name'),
      '%max' => MENU_MAX_MENU_NAME_LENGTH_UI,
      '%length' => drupal_strlen($menu_name),
    )));
    // Unlike most other modules, there is no confirmation message displayed.

%max -> <em class="placeholder">27</em>

tobiasb’s picture

Status: Needs work » Needs review
sun’s picture

StatusFileSize
new34.03 KB

Thanks, but your patch contained other, unrelated changes.

jbrown’s picture

This is a really great idea!

sun’s picture

StatusFileSize
new34.47 KB

Removed debug code, clarified comments.

I think we should update all #process and #after_build callbacks in core accordingly, so that developers do not find deprecated examples.

Status: Needs review » Needs work

The last submitted patch, drupal.machine.10.patch, failed testing.

sun’s picture

Status: Needs work » Needs review
StatusFileSize
new44.99 KB
sun’s picture

moshe weitzman’s picture

Subscribe. I'll have more to say later. Looks nice so far.

sun’s picture

Title: Machine » Machine names

Actually, I hoped for a RTBC already. :) Happy to discuss any details or questions though, so please don't hesitate to post 'em!

fago’s picture

Interesting - making providing machine names simpler would be definitely useful.

I just had a short look at the patch:

* The naming of #machine_name_exists doesn't make clear it's a callback when reading the FAPI structure.

Question:

+ // Store a reference to the complete form in $form_state prior to building
+ // the form. This allows advanced #process and #after_build callbacks to
+ // perform changes elsewhere in the form.
+ $form_state['complete form'] = &$element;

Why is that necessary? The process / after_build callbacks are run on the cached copy again nevertheless.

sun’s picture

- re: #machine_name_exists: possible, though #process and #after_build and #pre_render don't make that clear either - any better suggestion?

- form_process_machine_name() is invoked for the #type 'machine_name' form element, but needs to add a #field_suffix to another element in the form (given with #machine_name_source). Therefore, it needs to be able to not only access the complete form, but also be able to alter the complete form. This may sound dangerous, but it's not really different to a regular hook_form_alter(), which is also by reference. I always wanted to do this, but wasn't able to - it seems like our Form API improvements for D7 finally allow to do it.

chx already asked me whether this isn't the same as #type 'filter_format'. I say it is not, because #type 'filter_format' has a unique presumption: The value and format may only ever exist together and form a compound user interface widget that can be understood as a single widget. That is not the case for machine names, as they are optional and only happen to use another field as source, but technically, they could even work without a source field. Furthermore, the inheritance of form element properties in filter_process_format() is really really ugly, error-prone, and not alterable in any way - you simply cannot set certain properties for the injected child elements.

Therefore, the idea is to have a #type 'machine_name' element, which can be loosely coupled with a source element, but otherwise fully customized to your needs, if required.

q0rban’s picture

Subscribe

bleen’s picture

very cool ... subscribing

sun’s picture

StatusFileSize
new45.07 KB
sun’s picture

Title: Machine names » Machine name form elements are too hard to implement + Date types are not validated at all
Issue tags: +JavaScript, +Killer Developer Features, +features, +D7CX
sun’s picture

StatusFileSize
new40.9 KB

Re-rolled against HEAD.

Status: Needs review » Needs work

The last submitted patch, drupal.machine.22.patch, failed testing.

sun’s picture

Status: Needs work » Needs review
StatusFileSize
new45.1 KB

Sorry, forgot the new .js.

moshe weitzman’s picture

Status: Needs review » Needs work
+++ includes/form.inc	17 Sep 2010 00:07:51 -0000
@@ -2911,7 +2916,111 @@ function form_process_tableselect($eleme
+  // Apply default form element properties.
+  $element += array(
+    '#title' => t('Machine-readable name'),
+    '#description' => t('A unique machine-readable name. Can only contain lowercase letters, numbers, and underscores.'),
+    '#machine_name_source' => array('name'),
+    '#machine_name_label' => t('Machine name'),
+    '#machine_name_pattern' => '[^a-z0-9_]+',
+    '#machine_name_replace' => '_',
+  );

any reason these are not in hook_element_info()?

+++ includes/form.inc	17 Sep 2010 00:07:51 -0000
@@ -2911,7 +2916,111 @@ function form_process_tableselect($eleme
+  $js_settings = array(
+    'type' => 'setting',
+    'data' => array(
+      'machineName' => array(
+        '#' . $source['#id'] => array(
+          'text' => $element['#machine_name_label'],
+          'target' => '#' . $element['#id'],
+          'pattern' => $element['#machine_name_pattern'],
+          'replace' => $element['#machine_name_replace'],
+          'suffix' => '#' . $suffix_id,
+        ),
+      ),
+    ),
+  );

are we worried about multiple machine name elements on same page. seems like their js settings would collide. this is a minor issue and not a new problem so should be addressed elsewhere (if needed).

once tests pass, this is rtbc IMO.

sun’s picture

Status: Needs work » Needs review

Thanks for the review, moshe!

1) I had the defaults in system_element_info() at first, but then figured that you most likely cannot alter those defaults anyway, and so it would make more sense to have them within the context of the #process and the #element_validate functions, where they are actually used and also documented. Additionally, I wasn't sure whether we'd keep the properties separate, or merge them into a single #machine_name property that would be an associative array of settings, perhaps even using the identical key names as the JS behavior. I've no strong preference myself, so happy to change it in any way. If you think that putting them into hook_element_info() would be better, since more consistent, then we can do that. Though not sure whether you still prefer it, given this reasoning. Just let me know.

2) I personally don't see a need for that, and it would only be an issue, if you'd have multiple machine name elements that try to use the same source element, so quite an edge-case. Also agreed on the separate issue, if needed.

3) Tests pass already :)

moshe weitzman’s picture

I do think it is more consistent to consolidate to a single #machine_name key with various properties. This would match how #cache and #attached look. I also think it is consistent to move to system_element_info(). Thanks.

sun’s picture

StatusFileSize
new45.26 KB

Turned #machine_name into an array, as suggested. However, I realized that form constructors would override/unset all other defaults in #machine_name, when defining them in hook_element_info(), so I kept the default values in the #process and added a code comment to explain why they are there.

Status: Needs review » Needs work
Issue tags: -JavaScript, -Killer Developer Features, -features, -D7CX

The last submitted patch, drupal.machine.28.patch, failed testing.

tobiasb’s picture

Status: Needs work » Needs review
Issue tags: +JavaScript, +Killer Developer Features, +features, +D7CX

#28: drupal.machine.28.patch queued for re-testing.

moshe weitzman’s picture

Status: Needs review » Reviewed & tested by the community

Looks good to me and to the bot.

To summarize, we have a bug where Date Type (whatever that is) has no machine name validation at all. Rather than add yet another custom implementation, sun made a generic #machine_name FAPI element and converted menu, vocab, etc. to use it. Thats a terrific bug fix in my book. It fixes the core bug and prevents many more in Contrib.

@tha_sun - a different issue related to element defaults is now at #914792: Custom element properties entirely override default element info properties

mlncn’s picture

Issue tags: +D7DX

++ Fantastic developer experience improvement and all-around code rationalization.

andypost’s picture

sun’s picture

StatusFileSize
new45.23 KB

Re-rolled against HEAD.

webchick’s picture

Version: 7.x-dev » 8.x-dev
Category: bug » feature

I see nothing in this issue that justifies API changes of this nature 12 months after API freeze. Sounds like a great feature for D8 though.

moshe weitzman’s picture

@webchick - i posted a summary in #31 where i try to answer that question. i can't tell if you missed it or you disagree.

webchick’s picture

I read it. It's very difficult for me to justify a 45K patch that changes multiple parts of the system when the actual fix for the bug that was accidentally found as a result of adding this feature 12 months after API freeze is like a line or two of code.

If Dries thinks otherwise, that's fine, but it's a no from me.

sun’s picture

Version: 8.x-dev » 7.x-dev
Category: feature » bug

mmm, can we revisit this decision? I've really worked hard to ensure to retain full API compatibility, so this patch does not break anything at all, while fixing a major bug in Drupal core that is too easily repeated in contributed modules. The patch removes more lines than it adds, and the removed lines are partially bogus, which only testifies that machine names are too hard to implement. (if not even Drupal core with hundreds of eyeballs reviewing gets it right, who will?)

In any case, I guess Dries won't notice if the version isn't 7.x.

alan d.’s picture

+1 for this feature. And a back port to 6 even if core doesn't use it ;)

webchick’s picture

I'm also curious why this couldn't be implemented in contrib, with hook_element_info()? Then Drupal 6 really could use it.

sun’s picture

@webchick: Currently, form #process callbacks are needlessly limited to perform changes on the passed in $element only. The essential change that allows this advanced #process callback to actually do its job is the ability to alter other form elements in $form_state['complete form'] by reference. This may sound anxious, but there is really no difference to hook_form_alter() and form element validation handlers, which are also altering things by reference already.

Effectively, by removing the needless limitation, this advanced #process callback is able to append a #field_suffix to the form element that is used as the source for the machine name (i.e., a placeholder for the "Machine name: foo_bar [edit]" markup):

  $form['name'] = array(
    '#type' => 'textfield',
    '#title' => t('Human-readable label'),
    // This #field_suffix is added by the #process callback invoked for #type 'machine_name':
    '#field_suffix' => '<span class="machine-name..."></span>',
  );
  $form['machine_name'] = array(
    '#type' => 'machine_name',
    '#machine_name' => array(
      'source' => array('name'),
    ),
    // This callback is defined via system_element_info() for #type 'machine_name',
    // and will append a #field_suffix to the 'source' element, as defined right above:
    '#process' => array('form_process_machine_name'),
  );

So after figuring this out and making it work, all existing machine name form elements throughout core have been standardized and simplified to use this new #type, allowing us to remove plenty of duplicate code. While doing so, I recognized that Date format types in HEAD do not implement any kind of machine name validation, and that's effectively what this patch solves: Don't make developers have to re-implement a complex construct of a textfield that requires lots of carefully crafted validation routines, a weird JavaScript settings definition, and for which there is not even a single valid code example throughout entire Drupal core.

I would not have worked on this patch for D7 if I would not see an urgent need to fix this issue. There are too many other critical and major issues on my plate.

sun’s picture

Title: Machine name form elements are too hard to implement + Date types are not validated at all » Machine names are too hard to implement. Date types and menu names are not validated

If you need yet another proof that this patch is badly needed: #292790: Menu machine-name validation error (The menu name can't be longer than 27 characters)

It is not clear to me why we prefer to waste lots of developer time instead of fixing the cause.

rickvug’s picture

The case as to why this patch is needed was made well in #41 and elsewhere in this issue. Can we get this in and move on to #903730: Missing drupal_alter() for text formats and filters before we're stuck with these problems for another release?

webchick’s picture

We have a period of the release, called "code thaw" to put in new features like this. That period lasted 18 months and ended last September. There was not then, and isn't now, an exception to code thaw to build exportable support into Drupal 7 core. We are currently actively trying to get Drupal 7.0 out the door, not keep stuffing more stuff in to an already over-stuffed release.

sun's argument for this patch seems to be "security," which is the only reason I'm leaving it for Dries to make a call on, and not immediately returning it to D8 where it actually belongs. The arguments for any other exportable-related patches are on incredibly shaky ground from my POV. If there are patches in the queue at this point that don't directly lead to Drupal 7.0 shipping faster and more bug-free, then they're all D8 as far as I'm concerned. Hopefully those concerned about core exportable support can rally quickly during the D8 code thaw to ensure it's fixed for good then.

So, no. We can't "get this in" and "move on" to other exportable issues. Unless you and Dries have some secret pact I don't know about that exempts exportable-related features from feature freeze.

rickvug’s picture

@webchick - I apologize if my comment came off as trying to skirt the rules of code freeze. I understand that freeze was ages ago. However, various other issues dealing with inconsistencies and "WTF" DX issues have been committed. I hope that an exception is made here based on the value of this fix relative to the extent of the changes. Contrib is hurting because core does not handle machine names in a consistent manner.

sun’s picture

We are currently actively trying to get Drupal 7.0 out the door, not keep stuffing more stuff in to an already over-stuffed release.

Do you realize that this patch fixes 2 major bugs in core and therefore massively helps to get D7 out of the door? Do you realize that this patch prevents hundreds of contributed modules to introduce the same bugs and mistakes that are currently in core?

If the answer to both is "yes", then I fail to see the logic in not committing this patch.

@rickvug: Other patches are never a reason to commit a patch.

nedjo’s picture

Yes, it's very late for API changes, and this issue and the accompanying #903730: Missing drupal_alter() for text formats and filters have the potential to further drag on D7 readiness. However useful , these changes should be considered only if there is a compelling case that D7 would be effectively broken without them.

Here's the case as I understand it.

Text formats are a key element of Drupal's security system. They are also one of the most complex, difficult, and error-prone areas of site configuration, particularly if a WYSIWYG editor is in use. Current stats for Fckeditor, Ckeditor, WYIWYG, and Drupal as a whole suggest that more than half of all D6 sites (~178,000) have a WYSIWYG editor in use. WYSIWYG editors generate a range of tags, some of which require specific attributes, some of which are not allowed by the drupal core tag filter. Configuring a rich text editor to work with an input format is difficult and frustrating, even with specialized contrib tools like WYSIWYG Filter.

As a result, an unknown but probably large number of site admins throw up their hands and abandon tag filtering altogether, allowing full HTML for the simple reason that they can't figure out how to get WYSIWYG to work without it. I know that I personally have encountered multiple sites with anonymous comment input on which full html had been set as the default input format purely because site admins couldn't figure out how to configure a filter for rich text editing.

The only effective way to address this issue is going to be through exportables. By enabling text formats to be exportable, we can provide polished configurations that achieve a high level of functionality without sacrificing security.

The Features module is the leading solution for distributing exportables, but input formats are not supported. Actually, the code is there in Features, but by design it is inactive. The reason is that input formats lack a machine name. This lack means not only that text formats themselves can't effectively be exported. Equally important, it means that associated data - WYSIWYG configurations, filter configurations, default formats per role, etc. - are keyed by format ID in numerous places throughout core and contrib.

There have been numerous efforts to solve this issue in contrib. None could be called successful. A recent article demoed WYSIWYG as a Feature, but a closer examination of the patch used leads to a tangled patchwork of half solutions.

Only a fix in core can provide a clean D7 solution to this significant security concern.

As a side benefit, exportable filter formats will help address a serious usability barrier, by making it possible to provide richly featured WYSIWYG and other text format-based Features.

And as for why this patch is so late coming, the reason is plain: sun was plenty busy with other contributions, and - despite the plethora of commentators - no one else had the clarity of thought to solve this issue at its source.

Does all this add up to sufficient basis for a code freeze exception? It's hard for me to judge. I am convinced, though, that once again sun has provided the combination of insight and excellent coding needed to fully address a glaring need in core.

Personally, I can commit to reviewing any follow up patches that may be required.

[Edited to finish an incomplete sentence.]

sun’s picture

Additionally, this patch along with the patch in #903730: Missing drupal_alter() for text formats and filters helps to unblock and do the remaining necessary follow-up changes for the critical issue #914458: Remove the format delete reassignment "feature"

sun’s picture

Issue tags: -JavaScript, -Killer Developer Features, -features, -D7CX, -D7DX

#34: drupal.machine.34.patch queued for re-testing.

Status: Reviewed & tested by the community » Needs work
Issue tags: +JavaScript, +Killer Developer Features, +features, +D7CX, +D7DX

The last submitted patch, drupal.machine.34.patch, failed testing.

sun’s picture

Version: 7.x-dev » 8.x-dev

Although badly needed, this is D8 material according to the rules (I had to learn today). It may be backported at a later point in time (though that's unlikely).

Someone needs to create a bug report to fix the currently not validated date type format machine names.

mlncn’s picture

This kick to 8.x is hard to watch. I hope Drupal adopts a philosophy of making code rationalization and API additions to major versions even after release, and we will see this - and other work, especially sun's, in 7.

sun++

nedjo’s picture

Re my comments in #47, today I posted an attempt at the best workaround available currently for D6/D7 to address WYSIWYG feature: Debut WYSIWYG. It's a good illustration of what we need to fix, but I guess it also demonstrates that, with many hacks and limitations, we can do something in the meantime.

[edited to correct the link]

sun’s picture

@webchick: Can we at least commit the Form API improvement of (optionally) allowing #process callbacks to alter elements (and therefore the complete form) by reference? Without that adjustment, it's close to impossible to implement this functionality from contrib. It does not change any functionality or API in Drupal core or any contributed module, and merely recommends #process callbacks to process elements by reference, but they are still able to return a new copy of $element, like they are now. That's all I'm asking for.

webchick’s picture

Yeah, I'd be willing to take a look at what a patch like that looks like. That sounds like a more under-the-hood change, as opposed to an API change that would affect module developers directly.

sun’s picture

Version: 8.x-dev » 7.x-dev
Status: Needs work » Needs review
StatusFileSize
new14.99 KB

Thanks for offering to review it.

Technically, only the changes for form_builder() are required, but the patch updates all #process and #after_build callbacks throughout core to make sure that developers only see the recommended way when searching for example callbacks.

Status: Needs review » Needs work

The last submitted patch, drupal.machine.57.patch, failed testing.

sun’s picture

Status: Needs work » Needs review
StatusFileSize
new15.47 KB

Sorry, removed one too many change.

sun’s picture

If this patch would have a chance, then I would add some tests to confirm and ensure that "old-school" #process and #after_build callbacks still work in the expected way (which I already tested manually). Alternatively, we could simply revert just any of the existing callbacks (e.g., form_process_password_confirm), which would lead to the testbot not being able to install, if it wouldn't work as expected.

mlncn’s picture

Status: Needs review » Reviewed & tested by the community

Looks good. Everything works, date type machine name doesn't let me use all caps, etc. Ready for webchick, at least!

sun’s picture

Issue tags: +API change
StatusFileSize
new31.62 KB

Hold on. I just realized that we don't have to change #process and #after_build callbacks at all. It is sufficient to keep the by-reference assignment change of 'complete form' internal to form_builder(), which recursively invokes itself.

So the only API change that remains is:

  1. #type 'machine_name' is introduced. Renders an element like #type 'textfield' would, but with additional, standardized machine name processing and validation.
  2. Existing forms throughout core that expose a textfield to configure a machine name are basically just changed from #type 'textfield' to 'machine_name'.
  3. The JavaScript Drupal.behaviors.machineName is moved from system.js into a dedicated misc/machine_name.js, which is consistent with other widget-alike core functionality.

Compared to how many existing bugs this patch fixes, and how many bugs it will prevent in core and contrib, and that the outlined API change only affects extreme edge-cases (as a module would actually have to rely on the form element #type, or expecting the JS behavior in system.js), and considering that any module that is affected by this API change will actually be happy about it in the first place (because it is implementing a machine name), and lastly, since existing machine name form elements will still work (only the JS is missing; but will not even break), it would be ridiculous to not do this for D7.

dagmar’s picture

Status: Reviewed & tested by the community » Needs review
moshe weitzman’s picture

Status: Needs review » Reviewed & tested by the community

OK, this one even more focused on the bug fix and standardizing these elements for Contrib. I much agree with Sun's case. Please take another look.

dixon_’s picture

subscribing

fago’s picture

Status: Reviewed & tested by the community » Needs work

The new patch looks better. Now there are effectively no FAPI changes, but a small improvement. Similarly the patch helps a lot when introducing machine names. As I've done some machine name form elements already for D7 I very much agree that *properly* doing this machine name form element is way too complicated now.

+    'pattern' => '[^a-z0-9_]+',

Hm, without reading the docs I'd assume this is the pattern for valid chars. But it is the pattern for finding non valid characters.

Looking up the docs, they are wrong:

+ *     - pattern: (optional) A regular expression (without delimiters) matching
+ *       valid characters in the machine name. Defaults to "[^a-z0-9_]+".

Anyway, what about using [a-z][a-z0-9_]* as default pattern for valid machine names? That way we'd ensure they start with a letter and disallow solely numeric machine names. First of numeric machine names don't make much sense. Secondly this allows for using a "magic" $identifier variable, which may contain either the machine name or the id + writing a loader function that just checks with is_numeric() whether to load by numeric id or machine name. Having this in place, any references to the entity can be easily changed to machine names or just kept by ids.

sun’s picture

Status: Needs work » Needs review
StatusFileSize
new30.03 KB

Thanks for reviewing, fago!

I think I've fixed the docs. But the additional point you are raising is valid, too. To make it obvious for everyone:

  • Currently, pattern should actually be renamed to antipattern or similar. The regular expression is primarily used by the JavaScript to find all characters that need to be transliterated.
  • The current [anti]pattern is also used by form_validate_machine_name() to validate whether a machine name is correct. Technically, that's an entirely different operation and the current pattern is not really sufficient. So fago just found even more issues with the current machine name validations throughout core:
    1. It is not validated, whether the machine name consists of transliterated replacement tokens only (i.e., ___).
    2. It is not and currently cannot be validated, whether the machine name starts with a nun-numeric letter (i.e., [a-z][a-z0-9]+). AFAIK, none of the core machine names has problems with a starting digit, but I think it is a valid use-case. Note that such an implementation would have to additionally implement server-side validators for the corresponding *_presave() operations, so as to prevent programmed saves from storing invalid machine names. Overall, that's out of scope for this issue.
  • Since I cannot think of a way to have a single regular expression that works both for client-side transliteration of disallowed characters and server-side form element value validation, this means that we could consider to have a separate antipattern (used for client-side transliteration) and pattern (used for server-side machine name value validation). Better name suggestions are highly welcome.
  • Regardless of the previous bullet, form_validate_machine_name() should definitely check whether the name consists of the replacement token only, and if it does, throw an error. Not contained in this patch yet.
sun’s picture

StatusFileSize
new5.37 KB
new30.71 KB

Implemented additional validation to ensure that a machine name does not only consist of the replacement token. Additionally fixed a few descriptions and error messages.

Status: Needs review » Needs work

The last submitted patch, machine.interdiff.68.patch, failed testing.

sun’s picture

Status: Needs work » Needs review
sun’s picture

StatusFileSize
new30.76 KB

Massively improved the code comments.

I'd like to propose to go with this path as is. Right now, I don't know of any code that tries to use a machine name directly in PHP function names, and even if such code exists, it's probably a good idea to use a MODULE_MACHINENAME() function name pattern anyway. Which means that point 2) of #67 does not have to be done for D7.

moshe weitzman’s picture

Status: Needs review » Reviewed & tested by the community

Summary is in #62

fago’s picture

Agreed that [a-z][a-z0-9]* is out of scope.

+  $element['#machine_name'] += array(
+    'source' => array('name'),
+    'target' => '#' . $element['#id'],
+    'label' => t('Machine name'),
+    'pattern' => '[^a-z0-9_]+',
+    'replace' => '_',
+  );

As said, I'd assume without reading the docs 'pattern' describes the regex for valid machine names. Perhaps better rename it to 'replace_pattern' to make this more clear?

Crell’s picture

"pattern" is the name of the HTML5 attribute that does the same thing (validate based on a regex), so I think it's fine to use the same name (especially if we are able to later expand that same property for more HTML5 goodness later).

fago’s picture

HTML 5 pattern does exactly what one would assume for "pattern", it states the pattern that the element has to fulfill. See here.

But the #machine_name pattern specifies the characters to remove/replace. Perhaps we can rewrite the JS to work like the HTML 5 pattern? That would be certainly the best DX and potentially allow use to make use of the mentioned HTML5 goodness later.

sun’s picture

I don't think that this documentation/comment change should hold up this patch. The current documentation for 'pattern' sufficiently describes its current usage and intention. The similarity with HTML5's 'pattern' attribute might be there, but in the end, there's no test and no code that proves that the current 'pattern' would actually work as HTML5 attribute. Figuring this out can happily left for http://drupal.org/project/html5 and other contributed attempts.

Crell’s picture

Hm. fago is correct; I misread the patch when I was just skimming the issue. Given that it is a post-process pattern rather than a validation pattern it may be wise to name it as such to avoid collision later (with the html5 project and similar efforts that would likely want to add such a property if they can).

sun’s picture

StatusFileSize
new32.13 KB

Changed 'pattern' into 'replace_pattern'. After closer inspection of the HTML5 docs about the 'pattern' attribute, it's definitely not the same -- rather what fago proposed above; i.e., a regular expression that precisely matches valid user input. 'replace_pattern' is more or less the opposite: A regular expression to match one or more subsequent characters that are *not* valid and need to be transliterated, resp., replaced with the replacement token.

Since I had to touch menu_edit_menu() for this once again, I tried to review and ensure that the applied changes in there are correct, but I was once again highly confused by the logic that is going on in there. So I additionally cleaned that code up, so as to ensure that resulting logic is correct.

sun’s picture

StatusFileSize
new32.15 KB

Additionally fixed the #maxlength mismatch for vocabulary machine names. The existing form defined 255, but the form validation handler manually limited to 21. Weird.

dries’s picture

This patch looks good.

+++ includes/form.inc
--- /dev/null
+++ misc/machine_name.js

The other files use dashes instead of underscores. For example misc/vertical-tabs.js.

sun’s picture

StatusFileSize
new32.15 KB

Renamed machine_name.js into machine-name.js.

fago’s picture

Patch looks good to me too. 'replace_pattern' is much better and tells me what it is about really, thanks.

jgraham’s picture

recap of #62:
1. appears to be done
2. This appears to be solved for menu. AFAICT the remaining work is deferred to other tickets waiting on this patch.
3. appears to be done

It appears that #75 is the only potential remaining issue, is that correct?

If so I think the rework from #78 avoids any ambiguity and should address the concerns presented by crell in #77. This appears to be a reasonable interim solution and if a better solution is desired we appropriately defer to contrib to flesh out the details.

sun’s picture

#75 has been resolved in #78. Unless you mean the suggested usage of HTML5 'pattern', which is definitely left to contrib and will not be tackled here.

sun’s picture

#81: drupal.machine.81.patch queued for re-testing.

dries’s picture

Status: Reviewed & tested by the community » Fixed

This patch fixes a bug, but is also a last minute clean-up that will help with better distribution support. We discussed this in #933846: Better distro support.

Committed to CVS HEAD. Thanks!

klausi’s picture

Priority: Major » Normal
Status: Fixed » Active
Issue tags: +Needs documentation
rfay’s picture

Title: Machine names are too hard to implement. Date types and menu names are not validated » [HEAD BROKEN] Machine names are too hard to implement. Date types and menu names are not validated
Priority: Normal » Critical

This broke HEAD - machine-name.js doesn't seem to have gotten committed.

webchick’s picture

Status: Active » Fixed

Oops. :P Committed that to HEAD.

A system module hunk flew by too. Hope that didn't break anything.

claar’s picture

Title: [HEAD BROKEN] Machine names are too hard to implement. Date types and menu names are not validated » Machine names are too hard to implement. Date types and menu names are not validated
Priority: Critical » Normal
Status: Fixed » Active

Resetting status back due to #87

jgraham’s picture

Just chatted with rfay in IRC and I am working on a patch for the documentation issues. Will post for feedback.

jgraham’s picture

Status: Active » Needs review
StatusFileSize
new24.39 KB
new21.77 KB

Adjustments to forms_reference_api.html to address #87

Attached is a diff and the complete html file please review.

Status: Needs review » Needs work

The last submitted patch, 902644_forms_api_reference.html_.patch, failed testing.

rfay’s picture

@jgraham, the patch is pretty hard to review. Could you just put the relevant updated HTML (the main content part) into this issue? Alternately, you could put the html file somewhere and give us a link to it.

Thanks!
-Randy

claar’s picture

@rfay: Here's a copy-paste from the zip file in #92 -- hope it helps.

@jgraham: I checked the below "Properties" against the above table and found some discrepancies:

  1. #required isn't checked in the table, but is listed under Properties
  2. #type is listed as a property, but I believe you meant #weight (edit: or perhaps you meant both #type and #weight? Anyway, #weight is checked in the top table)
  3. #title and #type are in <strong> tags

machine_name

Description: Provides a unique machine-readable name.

By default provides a machine name that is validated such that it contains only alphanumeric and '_'. All characters not meeting this criteria are replaced with '_'. The validation routines also fail if the element value is comprised solely of '_'.

Non-standard form element properties:

  • #machine_name: (array)
    • exists: A function name to invoke for checking whether a submitted machine name value already exists. The submitted value is passed as argument. In most cases, an existing API or menu argument function can be re-used. The callback is only invoked, if the submitted value differs from the element's #default_value
    • source: (optional) The #array_parents of the form element containing the human-readable name (i.e., as contained in the $form structure) to use as source for the machine name. Defaults to array('name').
    • label: (optional) A text to display as label for the machine name value after the human-readable name form element. Defaults to "Machine name".
    • replace_pattern: (optional) A regular expression (without delimiters) matching disallowed characters in the machine name. Defaults to '[^a-z0-9_]+'.
    • replace: (optional) A character to replace disallowed characters in the machine name via JavaScript. Defaults to '_' (underscore). When using a different character, 'replace_pattern' needs to be set accordingly.

Properties: #access, #after_build, #array_parents, #attached, #description, #disabled,#element_validate, #parents,#post_render, #prefix,#pre_render, #process,#required, #states,#suffix, #theme, #theme_wrappers,#title, #tree,#type

Usage example (menu.admin.inc):

$form['menu_name'] = array(
  '#type' => 'machine_name',
  '#title' => t('Menu name'),
  '#default_value' => $menu['menu_name'],
  '#maxlength' => MENU_MAX_MENU_NAME_LENGTH_UI,
  '#description' => t('A unique name to construct the URL for the menu. It must only contain lowercase letters, numbers and hyphens.'),
  '#machine_name' => array(
    'exists' => 'menu_edit_menu_name_exists',
    'source' => array('title'),
    'label' => t('URL path'),
    'replace_pattern' => '[^a-z0-9-]+',
    'replace' => '-',
  ),
  // A menu's machine name cannot be changed.
  '#disabled' => !empty($menu['old_name']) || isset($system_menus[$menu['menu_name']]),
);
jgraham’s picture

Status: Needs work » Needs review
StatusFileSize
new21.89 KB

@claar: thanks for making that more readable to everyone.

Adjusted as per claar's comments in #95
1. The table was an omission.
2. I meant #type and #weight
3. fixed

Status: Needs review » Needs work

The last submitted patch, 902644.95.patch, failed testing.

sun’s picture

Status: Needs work » Reviewed & tested by the community
StatusFileSize
new1.56 KB

Now we have some duplicate code. Please revert.

webchick’s picture

Status: Reviewed & tested by the community » Needs review

Well. That explains why I had extra hunks in that commit I did just before hopping on a phone call. :D Thanks!

Committed #98 to HEAD. Back to needs review for docs?

sun’s picture

Assigned: sun » Unassigned
Status: Needs review » Fixed
StatusFileSize
new26.06 KB

Some definitions were not correct. Most are actually identical to #type textfield, so I fixed that.

Thanks for reporting, reviewing, and testing! Committed to HEAD.

This change will be visible on api.drupal.org within the next 24 hours.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

traviscarden’s picture

Re-tagging.