Updated: Comment #N

Problem/Motivation

Path alias information can not be attached as a field to any entity type after #1980822: Support any entity with path.module, but path.module still has one-off form alters for node and taxonomy.

There's also the question of who should add it to the entity type, right now path.module alters it in for node and taxonomy, should it be condition in node/taxonomy instead? Would be a bit ugly, but that is what other entities would have to do anyway.

Proposed resolution

Convert it into a field widget, which would allow to easily attach it to any entity. This isn't about making it configurable (yet?), you'd still define it in code.

Remaining tasks

User interface changes

API changes

Comments

andypost’s picture

If we going to make it configurable field that we should care about cardinality then better to reopen #1751210-125: Convert URL alias form element into a field and field widget
The path module can provide widget and alter field info by allowing widget use.

berdir’s picture

StatusFileSize
new8.34 KB

I just want to convert it to a widget here and not get derailed about configurable and UI and problems that come with that.

Here's a first patch.

berdir’s picture

Status: Active » Needs review

Status: Needs review » Needs work

The last submitted patch, 2: path-widget-2201051-1.patch, failed testing.

The last submitted patch, 2: path-widget-2201051-1.patch, failed testing.

andypost’s picture

Tests should use now path[0][alias]

+++ b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverviewBase.php
@@ -53,7 +53,7 @@
-    $this->fieldTypes = $field_type_manager->getConfigurableDefinitions();
+    $this->fieldTypes = $field_type_manager->getDefinitions();

needed here

yched’s picture

+++ b/core/modules/path/lib/Drupal/path/Plugin/Field/FieldWidget/PathWidget.php
@@ -0,0 +1,87 @@
+  public function errorElement(array $element, ConstraintViolationInterface $violation, array $form, array &$form_state) {
+    return $element['path'];

There's no such thing as $element['path'] ?

sun’s picture

Status: Needs work » Needs review
StatusFileSize
new20.82 KB
new14.5 KB

I agree with doing baby steps. The original "Make Path a field" issue pretty much failed, because I tried to change too many things at once :P

Fixing the primary test failures revealed some more bugs:

  1. Fixed bogus error element key.
  2. Updated Path module tests to use new form input name.
  3. Moved form element validation handler into PathWidget.
  4. Fixed inconsistent field labels.
  5. Fixed path field is not marked as translatable.
andypost’s picture

@sun I suggest you to add validation constraint as we do for fields like #2002168: Convert form validation of terms to entity validation

sun’s picture

StatusFileSize
new21.11 KB
new4.84 KB
  1. Reverted bogus FieldInfo assertion in PathLanguageTest.
  2. Fixed Path JavaScript summary.
  3. Removed seemingly obsolete langcode hack/override from form element validation handler.
  4. Simplified/fixed langcode handling in PathWidget to match Path CRUD service logic.

I'm not able to make PathLanguageTest work — the original English alias somehow seems to be gone after saving the French alias. I wasn't able to figure out why that is.

The last submitted patch, 8: path.widget.8.patch, failed testing.

jibran’s picture

+++ b/core/lib/Drupal/Core/Path/Path.php
@@ -141,4 +141,30 @@ public function delete($conditions) {
+    $query = db_select('url_alias')

Injection.

Status: Needs review » Needs work

The last submitted patch, 10: path.widget.10.patch, failed testing.

sun’s picture

Status: Needs work » Needs review
StatusFileSize
new21.52 KB
new3.54 KB
  1. Fixed only node form is supposed to have a "URL path settings" details wrapper.
  2. Use the injected database connection in Path::isUnique().

Status: Needs review » Needs work

The last submitted patch, 14: path.widget.14.patch, failed testing.

berdir’s picture

  1. +++ b/core/modules/path/lib/Drupal/path/Plugin/Field/FieldWidget/PathWidget.php
    @@ -51,23 +51,15 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
    +    $element += array(
           '#access' => $account->hasPermission('create url aliases') || $account->hasPermission('administer url aliases'),
           '#element_validate' => array(array($this, 'validateFormElement')),
         );
    

    Access should probably move to field access. That means we need a PathItemList class, specified as list_class on the annotation.

  2. +++ b/core/modules/path/path.module
    @@ -92,8 +92,20 @@ function path_menu_link_defaults() {
     function path_form_node_form_alter(&$form, $form_state) {
       if (isset($form['path'])) {
    -    // Move the path widget into the advanced group.
    -    $form['path']['#group'] = 'advanced';
    +    $form['path_settings'] = array(
    +      '#type' => 'details',
    

    Then we can switch to $node->hasField('path') && $node->get('path')->access('edit') here.

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new4.83 KB
new1.32 KB
new23.06 KB

1) Fix #16
2) fix broken test - interdiff2.txt
3) the following addressed

+++ b/core/modules/path/lib/Drupal/path/Plugin/Field/FieldWidget/PathWidget.php
@@ -0,0 +1,96 @@
+      $conditions = array(
+        'source' => $entity->getSystemPath(),
+        'langcode' => $entity->language()->id,

+++ b/core/modules/path/path.module
@@ -91,130 +88,24 @@ function path_menu_link_defaults() {
-    $conditions = array('source' => 'node/' . $node->id());
-    if ($node->language()->id != Language::LANGCODE_NOT_SPECIFIED) {
-      $conditions['langcode'] = $node->language()->id;
-    }

Status: Needs review » Needs work

The last submitted patch, 17: 2201051-path-widget-17.patch, failed testing.

andypost’s picture

Status: Needs work » Needs review
Issue tags: +D8MI
StatusFileSize
new3.95 KB
new23.91 KB

Currently Drupal\path\Tests\PathLanguageTest is broken some how, probably the order of alters with content translation...
The node body field does not store translatable text, and language is not properly passed to new widget

Seems we need Gabor here

Status: Needs review » Needs work

The last submitted patch, 19: 2201051-path-widget-19.patch, failed testing.

gábor hojtsy’s picture

I don't think I could be in any way better authority than sun, Berdir and yched combined here :)

berdir’s picture

Status: Needs work » Needs review

Hm. This seems to work... content_translation_entity_field_info_alter() is messed up, it doesn't correctly merge by-bundle settings of base field translatability. The first bundle just wins. That stuff is pretty messed up :(

I hoped that #2114707: Allow per-bundle overrides of field definitions would help a bit, but it doesn't.

As a workaround, we can set the article fields to translatable too, and use getLangcode() in PathItem().

Not so happy that Path now suddenly needs to be made translatable to work (once the form is saved, which is what the patch was doing) .

#2143291: Clarify handling of field translatability is related...

berdir’s picture

Uploading a patch usually works better than not doing so.

andypost’s picture

+++ b/core/modules/path/lib/Drupal/path/Plugin/Field/FieldWidget/PathWidget.php
@@ -0,0 +1,103 @@
+      // Node language needs special care. Since the language of the URL alias
+      // depends on the node language, and the node language can be switched
+      // right within the same form, we need to conditionally overload the
+      // originally assigned URL alias language.
+      // @todo Remove this after converting Path module to a field, and, after
+      //   stopping Locale module from abusing the content language system.
+      if (isset($form_state['values']['langcode'])) {
+        $form_builder->setValue($element['langcode'], $form_state['values']['langcode'], $form_state);

This is a ugliest hunk, any idea how to get rid of it?

andypost’s picture

23: 2201051-path-widget-22.patch queued for re-testing.

Status: Needs review » Needs work

The last submitted patch, 23: 2201051-path-widget-22.patch, failed testing.

andypost’s picture

Assigned: Unassigned » plach
Status: Needs work » Needs review
StatusFileSize
new2.3 KB
new24.67 KB

Patch removes @todo, and changes path language to $items->getLangcode() as #23 does

Let's get @plach review on it!
Yes, we need to enable both bundles because of comment in content_translation_entity_base_field_info_alter()

    // Currently field translatability is defined per-field but we may want to
    // make it per-instance instead. In that case, we will need to implement
    // hook_bundle_field_info_alter() instead.

Suppose related issue is #2111887: Regression: Only title (of base fields) on nodes is marked as translatable

andypost’s picture

StatusFileSize
new24.64 KB

re-roll (library, details-open)

jibran’s picture

  1. +++ b/core/modules/path/lib/Drupal/path/Plugin/Field/FieldWidget/PathWidget.php
    @@ -0,0 +1,102 @@
    +    $element['pid'] = array('#type' => 'value', '#value' => $path['pid']);
    +    $element['source'] = array('#type' => 'value', '#value' => $path['source']);
    +    $element['langcode'] = array('#type' => 'value', '#value' => $path['langcode']);
    

    multi line please.

  2. +++ b/core/modules/path/lib/Drupal/path/Plugin/Field/FieldWidget/PathWidget.php
    @@ -0,0 +1,102 @@
    +   * Form element validation handler for URL alias form element.
    

    @param doc missing.

  3. +++ b/core/modules/path/lib/Drupal/path/Plugin/Field/FieldWidget/PathWidget.php
    @@ -0,0 +1,102 @@
    +  public static function validateFormElement(&$element, &$form_state) {
    

    I think we have to add array before both the params

plach’s picture

Assigned: plach » Unassigned

Hm. This seems to work... content_translation_entity_field_info_alter() is messed up, it doesn't correctly merge by-bundle settings of base field translatability. The first bundle just wins. That stuff is pretty messed up :(
I hoped that #2114707: Allow per-bundle overrides of field definitions would help a bit, but it doesn't.

I also hoped #2114707: Allow per-bundle overrides of field definitions would help :)
Not sure whether that code was written making the wrong assumptions or it's just wrong. Anyway I think it's ok to set path fields as translatable, as written also below.

+++ b/core/modules/path/lib/Drupal/path/Plugin/Field/FieldWidget/PathWidget.php
@@ -0,0 +1,102 @@
+      // Entity language needs special care. Since the language of the URL alias
+      // depends on the entity language, and the entity language can be switched
+      // right within the same form, we need to conditionally overload the
+      // originally assigned URL alias language.
+      // @see \Drupal\content_translation\ContentTranslationController::entityFormAlter()

I couldn't find the part the the @see refers to. Anyway we might be able to simplify this code by using $form_state['controller']->getFormLangcode(), but it seems the implemented logic is needed in the isUnique() call below.


+++ b/core/modules/path/path.module
@@ -203,8 +98,13 @@ function path_form_taxonomy_term_form_alter(&$form, $form_state) {
+      ->setTranslatable(TRUE)

I think it's correct to set this translatable as path natively supports language.

andypost’s picture

StatusFileSize
new1.68 KB
new24.83 KB

Fix for #29

#30 1) ContentTranslationController::entityFormAlter() consumes $form['langcode'] that is set here

Status: Needs review » Needs work

The last submitted patch, 31: 2201051-path-widget-31.patch, failed testing.

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new761 bytes
new24.82 KB
andypost’s picture

StatusFileSize
new24.77 KB

re-roll

Status: Needs review » Needs work

The last submitted patch, 34: 2201051-path-widget-34.patch, failed testing.

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new656 bytes
new24.8 KB

fix wrong merge

plach’s picture

+++ b/core/modules/path/lib/Drupal/path/Plugin/Field/FieldWidget/PathWidget.php
@@ -0,0 +1,116 @@
+      $form_builder = \Drupal::formBuilder();
+      $form_builder->setValue($element['alias'], $alias, $form_state);
+
+      // Entity language needs special care. Since the language of the URL alias
+      // depends on the entity language, and the entity language can be switched
+      // right within the same form, we need to conditionally overload the
+      // originally assigned URL alias language.
+      // @see \Drupal\content_translation\ContentTranslationController::entityFormAlter()
+      if (isset($form_state['values']['langcode'])) {
+        $form_builder->setValue($element['langcode'], $form_state['values']['langcode'], $form_state);
+      }
+

I still think this whole block of code could be simplified. Probably even $entity->language()->id might work as an argument to ::isUnique().

andypost’s picture

but this code set language for the whole node form!?
@sun suggest to file follow-up , here it is #2225977: Remove langcode manipulation by Path widget

plach’s picture

Ok with the follow-up from me, I posted a comment there.

sun’s picture

FWIW, the change to use setTranslatable(TRUE) for the path field definition appears to be in line with the changes that were performed by #2111887: Regression: Only title (of base fields) on nodes is marked as translatable — so hopefully that question is obsolete now.

Didn't study the latest patch yet.

berdir’s picture

36: 2201051-path-widget-36.patch queued for re-testing.

Status: Needs review » Needs work

The last submitted patch, 36: 2201051-path-widget-36.patch, failed testing.

andypost’s picture

Status: Needs work » Needs review

re-roll, isUnique() replaced with aliasExists() in 'path.alias_storage'

andypost’s picture

StatusFileSize
new22.49 KB

patch

andypost’s picture

+++ b/core/modules/path/lib/Drupal/path/Plugin/Field/FieldType/PathItem.php
@@ -55,10 +57,7 @@ public function insert() {
-      // Ensure fields for programmatic executions.
-      $langcode = $entity->language()->id;
-
-      if ($path = \Drupal::service('path.crud')->save($entity->getSystemPath(), $this->alias, $langcode)) {
+      if ($path = \Drupal::service('path.crud')->save($entity->getSystemPath(), $this->alias, $this->getLangcode())) {

@@ -76,10 +75,7 @@ public function update() {
-      // Ensure fields for programmatic executions.
-      $langcode = $entity->language()->id;
-
-      \Drupal::service('path.crud')->save($entity->getSystemPath(), $this->alias, $langcode, $this->pid);
+      \Drupal::service('path.crud')->save($entity->getSystemPath(), $this->alias, $this->getLangcode(), $this->pid);

not included in last patch

Status: Needs review » Needs work

The last submitted patch, 44: 2201051-path-widget-43.patch, failed testing.

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new1.75 KB
new23.39 KB

revert this change

andypost’s picture

StatusFileSize
new971 bytes
new23.38 KB

forget to change isUnique()

The last submitted patch, 47: 2201051-path-widget-46.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 48: 2201051-path-widget-48.patch, failed testing.

berdir’s picture

Status: Needs work » Needs review
StatusFileSize
new23.39 KB
new795 bytes

Missed one path.crud :)

andypost’s picture

StatusFileSize
new23.4 KB

Another re-roll

sun’s picture

Status: Needs review » Reviewed & tested by the community

Looks good to me, thanks!

catch’s picture

Status: Reviewed & tested by the community » Fixed

This looks like good clean-up, although looks like we have work still to do to remove the form alters and/or have this configurable as part of the form display.

Committed/pushed to 8.x., thanks!

  • Commit 6a0257c on 8.x by catch:
    Issue #2201051 by andypost, sun, Berdir: Convert path.module form alters...
berdir’s picture

I don't think Drupal 8 will have an UI for the sidebar/vertical tabs stuff, so I expect those form alter to stay, but only node needs it. Also when we switch to widgets for the node form, we'll still need to move them into the corresponding groups.

alexweber’s picture

@Berdir correct me if I'm wrong but don't aren't form display modes the UI for vertical tabs stuff on entity forms?

amateescu’s picture

@alexweber, nope, form modes just provide the option to arrange fields differently in various forms.

lokapujya’s picture

After this patch: When adding an entity reference field to an article via the UI, and saving the field settings (I used target entity of: content) I get the following:
Notice: Undefined index: columns in Drupal\Core\Field\FieldDefinition->getSchema() (line 484 of core/lib/Drupal/Core/Field/FieldDefinition.php).
I think it has something to do with pathItem being a "computed field" and not having a schema.

tstoeckler’s picture

Yes I found that bug in #2183231: Make ContentEntityDatabaseStorage generate static database schemas for content entities as well. The problem is that getSchema () should initialize columns to an empty array by default. See the latest patch there for example.

tstoeckler’s picture

Title: Convert path.module form alters to a field widget » [regression: Entity Refernece fields broken] Convert path.module form alters to a field widget
Category: Task » Bug report
Priority: Normal » Critical
Status: Fixed » Needs review
Issue tags: +Needs tests
StatusFileSize
new944 bytes

Here's the relevant hunk of that patch extracted. When I found this I didn't realize that this means that adding fields from the UI is broken. That makes this a critical bug. Instead of reverting this let's just commit the attached patch and add test coverage in a follow-up?

tstoeckler’s picture

Title: [regression: Entity Refernece fields broken] Convert path.module form alters to a field widget » [regression: Path field broken] Convert path.module form alters to a field widget

Sorry, complete brain failure. Don't know why I thought of Entity Reference.

yched’s picture

Status: Needs review » Reviewed & tested by the community

Looks good to me.

sun’s picture

Title: [regression: Path field broken] Convert path.module form alters to a field widget » Convert path.module form alters to a field widget
Category: Bug report » Task
Priority: Critical » Normal
Status: Reviewed & tested by the community » Fixed
Issue tags: -Needs tests

That internal Field API code wasn't touched by this issue/patch here, so that's a preexisting problem and the change of this issue is not guilty for that.

Created #2257769: Adding an Entity Reference field in the Field UI throws a PHP notice; fails to add field

Status: Fixed » Closed (fixed)

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