My setup:
Drupal 7.2
Views 7.x-3.0-rc1

If I create a view with an exposed select widget with multiple selection enabled, I get a URL like this when when I select several options in the list and click Apply:
http://www.blahblah.com/viewname?field_select_value[]=2&field_select_val...

If I try to copy/paste this URL into the path of a custom menu item, it gets wrongly URL encoded upon save. In particular, note how all but the last value for field_select_value[] is lost.
viewname?field_select_value%5B%5D=5&=Apply

This encoding appears to happen repeatedly, such that path URL of the menu becomes further munged if I edit and save it again, w/o making any changes:
viewname?field_select_value%255B%255D=5&=Apply

And on the 2nd iteration:
viewname?field_select_value%25255B%25255D=5&=Apply

I gather this imperfect URL encoding would interfere in other instances of users wanting to create custom menu paths with query string parameters.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

agentrickard’s picture

Category: bug » support
Status: Active » Postponed (maintainer needs more info)

The general recommendation is not to use exposed filters but to use contextual arguments for Views pages that should be menu items.

The problem may be that the final clause &=Apply is not valid and breaks parse_url(). Try removing that item before saving the link.

We do not expect to handle invalid URLs.

Robin Monks’s picture

Version: 7.2 » 7.15
Status: Postponed (maintainer needs more info) » Active

I can confirm, even with a path that /should/ be valid; in my case:
know?field_issues_tid_i18n[]=268

Leeteq’s picture

Version: 7.15 » 7.x-dev
bcobin’s picture

Same here, but with a CiviCRM menu string that's valid. In my case, it's not an exposed filter, though.

agentrickard’s picture

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

Must be fixed in HEAD first.

joachim’s picture

Title: Menu links with query string params from views exposed filters get munged by url encoding » Menu links with query string params (from views exposed filters, solr facetAPI search, etc) get munged by url encoding

This happens with Solr Search pages too, where AFAIK there is no way to get nicer paths to enter into menu items.

I don't think the problem occurs on save:

1. I enter a path such as 'search/product?f[0]=sport:Rugby' into a menu link
2. Save
3. Menu link works correctly.
4. Edit the menu link
5. The edit form shows 'search/product?f%5B0%5D=sport%3ARugby'
6. Saving it again breaks the menu link

At stage 3 -- when the link is first saved and works fine -- the DB row for this in {menu_links} has this in the options field:

> a:2:{s:10:"attributes";a:1:{s:5:"title";s:0:"";}s:5:"query";a:1:{s:4:"f[0]";s:10:"sport:Golf";}}

Which to me looks like it's been saved as entered.

agentrickard’s picture

Status: Active » Needs review
FileSize
2.29 KB

The problem is that drupal_http_build_query() and PHP's http_build_query() both assume the need to urlencode the query value.

While I believe this is true for cases where URLs are printed, it is not true in this case, where the URL must only be read.

We can change the function in drupal_http_build_query(), which the attached patch does, or use a different builder function for this one instance

Given that $parent is an internal-only parameter, switching the parameter order seems safe here.

Ideally, this needs a test. Same approach should work for Drupal 7.

Status: Needs review » Needs work

The last submitted patch, 1220410-menu-query-params.patch, failed testing.

agentrickard’s picture

Status: Needs work » Needs review

#7: 1220410-menu-query-params.patch queued for re-testing.

barraponto’s picture

Double checked the usage of the internal parameter with ack --type-add php=.inc drupal_http_build_query and it seems to not have broken anything (only used in one place as far as I could see). Yet we should add tests here.

barraponto’s picture

Issue tags: +Needs tests

Tagging.

bwood’s picture

Attempting this task as part of DrupalCon Portland's Core Mentoring Sprint.

bwood’s picture

This issue exists in D8 HEAD as of today, but the symptoms are a little different:

1. Add a menu item with a query string
2. Item saves with no errors but does not appear in the table of menu links under the menu

This query demonstrates that the menu link is inserted:

SELECT * 
FROM  `menu_links` 
WHERE  `menu_name` LIKE  'main'

The sql results show records with:

link_path= node/1?f[0]=sport:Rugby
link_path= node/1?foo=bar

(Is it correct for the query string to be stored this way?)

The patch in #7 doesn't quite apply to D8 HEAD. The problem is that this hunk:

diff --git a/core/modules/menu/menu.admin.inc b/core/modules/menu/menu.admin.inc
index 3b67b97..08b20eb 100644
--- a/core/modules/menu/menu.admin.inc
+++ b/core/modules/menu/menu.admin.inc
@@ -324,7 +324,7 @@ function menu_edit_item($form, &$form_state, $type, $item, $menu) {
 
   $path = $item['link_path'];
   if (isset($item['options']['query'])) {
-    $path .= '?' . drupal_http_build_query($item['options']['query']);
+    $path .= '?' . drupal_http_build_query($item['options']['query'], FALSE);
   }
   if (isset($item['options']['fragment'])) {
     $path .= '#' . $item['options']['fragment'];

won't apply because menu.admin.inc no longer contains those lines. I looked into rerolling, but I think that the the fix to menu.admin.inc is obsolete.

Maybe this needs to be fixed in menu.admin.inc: menu_menu_edit() which builds the table of menu_links and fails to display the links with the query strings.

Status: Needs review » Needs work

The last submitted patch, 7: 1220410-menu-query-params.patch, failed testing.

msankhala’s picture

Version: 8.0.x-dev » 7.x-dev
Issue summary: View changes
FileSize
7.24 KB

Changing this issue to 7.x-dev because D8 HEAD does not have menu.admin.inc and this issue related to D7 menu and D7 HEAD still have this issue.

I spend quite time to resolve this issue due to menu module using api provided in common.inc and there are possibility of different theme hook call for each menu. Main reason to this issue was when we save a menu item the menu module encode the entered query parameter and save in database and each time we edit the menu item it put that encoded query parameter in path field and then saving again re-encode the query parameters. Thus each time we save the menu item with query parameters it encode each time. So my approach was saving the query parameter without encoding and then modify the theme hooks to display link without encoding query parameter.

I used patch added by @agentrickard in comment #7 as starting point.

Adding the patch. After applying this patch if you still see url in any of the menu item with query string encoded make sure whether your theme is overriding any theme hook for that menu or menu items and add

$element['#localized_options']['encode'] = FALSE;

in that theme hook.

This patch should solve the issue with facet api url like: /clothe/t-shirts?f[0]=field_gender%3A62

msankhala’s picture

Status: Needs work » Needs review

queued for testing.

John Carbone’s picture

+1 for patch in #16.

buhuhus’s picture

+1 for patch in #16.

msankhala’s picture

Status: Needs review » Reviewed & tested by the community

Moving it to RTBC.

stefan.r’s picture

Status: Reviewed & tested by the community » Needs work

This still needs tests, and this changes the function signature of drupal_http_build_query() in that parent now comes in as third argument. Also, this should probably be opt-in, in case anyone relies on the current broken behavior.

chrlvclaudiu’s picture

#16 fixes part of the problem. I'm now facing another issue with URLs coming from apachesolr filtered search.
For example, when trying to save this:
recherche?f[]=field_book_collection:28898&f[]=field_book_status:1
it actually saves this:
recherche?f[]=field_book_status:1

As you can see it only saves the last query parameter because f[] is replaced. When filters are keyed (i.e. f[0], f[1], ... f[n] it works just fine.

Problem:

function drupal_get_query_array($query, $decode = TRUE) {
  $result = array();
  if (!empty($query)) {
    foreach (explode('&', $query) as $param) {
      $param = explode('=', $param, 2);
      $key = ($decode) ? rawurldecode($param[0]) : $param[0];
      $value = isset($param[1]) ? ($decode) ? rawurldecode($param[1]) : $param[1] : '';
      $result[$key] = $value;
    }
  }
  return $result;
}

line $result[$key] = $value;
Any thoughts on this particular one ?

bvirtual’s picture

Drupal 7.67

I desire my customer to have a selection list of just one custom Content Type (glossary_term) in order to let editing occur. This bypasses the need of the customer to understand the use of the 2nd pulldown selection, scanning the selection, and picking glossary_term. I also want the list PRE-sorted by the node title. The menu link I have attempted to make is

/admin/content?sort=asc&order=Title&type=glossary_term

It actually works fine when pasted into the browser, or put into a page body.

When in the Menu Link Edit mode, it even displays in the selection list of links to edit or delete. For example

/admin/structure/menu/manage/user-menu

where the link text displays fine as so:

Edit Glossary Term - selection list to edit or delete

and the above link text, when clicked upon, the link value actually works to go to the desired page

/admin/content?sort=asc&order=Title&type=glossary_term

but the link inside the final displayed menu for the end user, does not display, on all the web pages where the menu displays (admin log in only).

Likely due to the access being changed to false (per another issue, https://www.drupal.org/project/drupal/issues/1822004 which states it's a duplicate of this issue - but now I do not see how that is so.)

The Mysql table menu_links has this row, not showing the query string, though the web page for editing the menu links does show the query string (as admin/content?sort=asc&order=Title&type=glossary_term).

link_path | link_title
admin/content | Edit Glossary Term - selection list to edit or delete

---

This issue arose when I first tried adding this query string link to a Shortcut menu item. It did not work well. The shortcut link was added, even with the correct link value (href= value), but clicking on the shortcut link, went to the URL with the query string encoded,

/admin/content%3Fsort%3Dasc%26order%3DTitle%26type%3Dglossary_term

but Drupal did not honor the encoded query string, and instead went to the page as if the query string was not even there. How does that happen? Very strange.

---

If the above needs more clarification, I am available. I've tried to put in enough info for others to duplicate the problem.

skylord’s picture

Reroll #16 for 7.82.