One of the major barriers blocking a useful, useable core installation profile is the inability to show nodes of a given type on a page or block. "Promoted to front page" can serve that purpose for one content type, but it's a terrible match for the usual use cases. When a node type is created, it should have an additional vertical tab containing 'display' or 'listing' options. It should contain three options:

  1. Provide a listing page - this would create a listing page of node teasers at the url: content/[content-type-machine-name]. It would function exactly like the front page, but it would displace nodes of a given type rather than promoted nodes.
  2. Provide a sidebar block - generates a disabled block containing the latest 5 posts of the content type.
  3. Provide an RSS feed - generates an rss feed at content/[content-type-machine-name]/rss3.xml, duplicating the pattern set by our main rss.xml file.

A (relatively) minor obstacle is convenient naming of the pages that would be generated. if #23298: Entity bundles should declare a plural form of their label were implemented first, it could be used to conveniently auto-generate a meaningful 'Latest [plural-name-of-content-type]' page title without additional tweaking.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

eaton’s picture

Status: Active » Needs work
FileSize
2.57 KB
59.9 KB
95.81 KB
54.21 KB

I took a quick stab at what this might look like and created a single custom module that does all of what's described above. if we were to refactor a couple of node module helper functions (notably node_get_recent(), node_page_default(), and node_feed()) we could probably eliminate about 2/3 of the code. As it stands it's only about 200 lines.

Thoughts and feedback on how to best turn this into a patch (rather than a separate module) are welcome. I like the fact that it provides an obvious on-ramp for the Views module; it could easily provide default views that mirror each of these content type pages and blocks.

Two details that probably need loving. First, the menu path (/content/$typename) is a bit crap, since there's no /content url. Ideally, we'd use something other than /node for the promoted content listing page, and we could have that be the top-level path. We'll see. Second, when you choose to enable a listing page for a given type right now, it also inserts the listing page into the breadcrumb trail when content of that type is being displayed. Should that be part of the behavior? I'm not sure, but providing it as a default when the listing page is activated certainly simplifies the creation of a nicely built-out site.

eaton’s picture

Also, I think it's probably worth removing the toggle-switch for RSS feeds - we don't allow peopel to turn off RSS on the front page, and toggling it for the individual content types is probably unnecessary. A global toggle switch ala #28337: Add permissions to disable RSS feeds would make more sense.

eaton’s picture

...And for those who want to see this get all official-like, the 'Lister' module attached above now has an actual sandbox project.

mansspams’s picture

Block title could be "Latest articles" if this passes #23298: Entity bundles should declare a plural form of their label

eaton’s picture

Yep, that's exactly the reason I'm hoping it goes through (It's listed in the first post in this issue). The language is currently a little awkward, but that would smooth it quite a bit. A couple of other possible directions for this module have been suggested by the kind folks in #drupal:

  1. Refactor node_get_recent(), node_feed(), and node_page_default() to do the bulk of the work
  2. If a content/$type page is empty, display a 'No content available' message and an 'Add content' link instead of a 404 page.
  3. INSTEAD of having node module do the bulk of the work, keep the functionality in a separate module AND move the front page from /node to /content, and have this module take it over. That would accomplish the eternal request of allowing people to disable /node if they don't want people seeing a duplicate URL, or if they aren't using the promoted flag at all.
  4. Use EntityFieldQuery instead of db_select().
  5. Make the sidebar block themable.
  6. Add a 'view $type content' permission that acts as a content-type-wide toggle switch, rather than a per-node toggle switch. Then use that permission as the default access control on the listing pages as well.

I'm particularly interested in #3, because it would split out a lot of oddball special casing in Node module, and make the "Make node module optional" patch that's been floating around a lot more doable. Baby steps, though.

catch’s picture

It'd be good to use EntityFieldQuery to run this.

Is it worth providing a listing at the entity type level as well as per-bundle?

If we did that, this might make more sense for other entity types - new comments block etc.

Poll module also provides a node type listing at /poll.

Blog does one at /blog (the per-user listings would be trickier but we could convert the main one).

eaton’s picture

Regarding entities, I think we could probably benefit from some generic 'get me a list of things and show them' code. Doing an unfiltered entity-level listing page would actually bring us very close to the standard /node page behavior, which definitely interests me.

Because it's being driven by the roadblocks we're hitting while working on the Snowman project, the actual end-user-facing functionality is actually what I'm most concerned about in this patch. Every site that's been built for that project has run into the "I can't just list nodes of X type" problem, without fail. None have run into similar issues with any other entity types, at least not yet.

I'm not sure that the /blog and /poll functionality would be a great mix either, for the following reasons:

  1. It would require a fair amount of extra configuration, including customizable paths for the listing pages. While it's not a show stopper, it introduces a lot of extra configuration questions and possible collision problems
  2. blog module, forum module, and poll module all do extra "stuff" on their pages that goes above and beyond a simple filtered teaser list. They're good examples of modules doing the heavy lifting so that a 'simple listing page' is unnecessary.

One possible option is to include some kind of option in the node type info itself, specifying that there's a listing page or block provided by the module that exposes the content type. If one is made available, the 'generic' listing page or block can't be turned on. I'm not sure there's a lot of value in that, though, especially if we don't have the listing page or block turned on by default. Turn on blog module, and it provides a page. If you go in and manually add another listing page, it doesn't hurt anything. In addition, it would lead towards tight coupling of the Listing functionality and the general node type system, which I'm hoping to avoid.

I'm open to alternative approaches on any of these, though. Just wanting to hold the line on the original intent, ie "Provide a simple way to list stuff with no fuss and no muss, then punt to Views/contrib for anything more."

eaton’s picture

eaton’s picture

A final idea about the blog/forum/poll intersection. node_type_get_types() lets modules return custom flags in the node type definition, and they get cached along with the 'standard' information. At least in theory, that would mean that a module could include 'listing_page_already_provided' => TRUE or something like that to disable the option for module-provided content types.

catch’s picture

For blog and poll, couldn't we move them and provide url aliases in the upgrade path or something? I did not look at extras they might be adding though, agreed if those have extra special-casing it's OK to leave them.

eaton’s picture

For blog and poll, couldn't we move them and provide url aliases in the upgrade path or something? I did not look at extras they might be adding though, agreed if those have extra special-casing it's OK to leave them.

We could -- blog module's top-level page at /blog does just list blog posts, so aliasing it would work. The only trick (I think?) is whether we would want the sub-pages linked to /blog/$uid or /content/blog/$uid. The breadcrumb trail behavior that's current provided in Lister would have to be disabled or overridden as well, since the blog nodes themselves would be a level or two deeper.

Poll is probably a good candidate, though, as I look closer. Currently it exposes an unordered list of poll links rather than teasers. Moving from D7 to D8, I don't think there would be a huge amount of pushback just nuking that custom page entirely, enabling the centralized listing page, and aliasing /polls to /content/poll. Removing the custom page would give us 50 lines of code for free! ;-)

Gábor Hojtsy’s picture

Don't want to overcomplicate your work, but one of the top complaints about Drupal listing pages from the mutlilingual realm is that there is no control on their language filtering. Although Drupal supports node language association (even if you don't have translations turned on), none of the listings will let you list only nodes in certain languages. If there is a listingf feature in core that covers either new ground and/or replaces the existing listing pages, adding langage filtering support would be of high interest for my initiative :) The basic feature would be a multiselect field (checkboxes or a multiselect dropdown) to configure which languages to show per listing. Given that you approach this from the content type configuration, I'm not sure how this would be possible to tie in in a meaningful way. Maybe this one is not the best of the snowman issues to bring this up? :)

sun’s picture

Hm. I was tempted to ask whether we don't waste time here in light of having Views in core at some day in the future, but well, yeah, I know, still a long way... Hm.

eaton’s picture

one of the top complaints about Drupal listing pages from the mutlilingual realm is that there is no control on their language filtering. Although Drupal supports node language association (even if you don't have translations turned on), none of the listings will let you list only nodes in certain languages.

Hmmmm. If we were to add a custom tag to all of the queries being run by these listing pages, would the language/locale configuration screens be able to offer their own checkbox/selection behavior? IE, 'Filter listing pages by language', then hook_query_alter just the listing page queries to add an extra condition? That would allow the complexity to still live on a module-by-module basis, and other modules that offer listing pages would be able to tag themselves as supporting the same functionality...

Hm. I was tempted to ask whether we don't waste time here in light of having Views in core at some day in the future, but well, yeah, I know, still a long way... Hm.

An excellent question. Basically, Views isn't in core and I haven't (yet) seen a credible proposal to get it there. I'm against creating a "customizable page builder" in core, but now that most content types are in CCK rather than custom modules like Poll or Blog, we need some way of listing them. If/When Views goes into core this module can be replaced with a set of Default views, but the decisions being hashed out in this thread (what should be displayed on the page, what options should be selected by default, where the paths should live, etc) are all ones we'd have to make when building out default views, too.

Gábor Hojtsy’s picture

@eaton: the idea for Drupal 8 not that locale module will do this magically for everybody else, because, frankly that is what i18n module did all these years, and it is a major mess. Unfortunately modules do need some language awareness, it is impossible to ignore that if we want to be a real multilingual system. See #540294: Move node language settings from Locale to Node module which is one of the D8 issues. Ok, that was strategy speak :)

Now for the concrete suggestion, the question is if the same setting for all these listings is appropriate. Do you use the same "how many items to display", "which ordering to use for display", "what properties to display" logic for all these listings? Blog, poll, taxonomy, other content types, the front page, etc?

eaton’s picture

the idea for Drupal 8 not that locale module will do this magically for everybody else, because, frankly that is what i18n module did all these years, and it is a major mess.

Hmm. I can see that. This feels like it's a general issue that we may run into all over core as different systems are decoupled from each other. The tag-it-and-hand-it-off approach is one that we're taking in similar situations like node access control, for example. This is a problem we'll probably be encountering on Taxonomy pages, too.

Now for the concrete suggestion, the question is if the same setting for all these listings is appropriate. Do you use the same "how many items to display", "which ordering to use for display", "what properties to display" logic for all these listings? Blog, poll, taxonomy, other content types, the front page, etc?

My philosophy going into the patch is something like this:

  1. The Drupal 'Core product' should provide good, usable defaults that allow people to build out a reasonable site skeleton
  2. The core product should provide global toggle-switches and options wherever possible, rather than lots of granular configuration.
  3. The core product should punt to contrib for complex/granular configuration, unless providing those options tools in contrib is impossible.
  4. When end-user-facing features are provided in the core product, they should be alterable or completely disable-able, to be replaced in contrib.

Given those principles (which I understand not everyone shares, naturally!) I'd favor either no control over the number of items, display order, and display style on listing pages, or a single global toggle-switch that applies to all listing pages. If a content type (like blog) needs a very specific set of options for its functionality to make sense, or it needs "Defaults plus X," it should implement its own custom listing page, because that custom presentation logic is integral to the concept of, say, "Multi-user blogging" or "Forum navigation." That would keep the custom logic custom and the 'Simple listing page' logic simple (and easy to replace).

One of the concerns I have about leaving language-awareness up to each individual module is that it's unclear what different 'language display' philosophies make sense. I can think of four off the top of my head: Listing pages should display the site's default language, Listing pages should display all languages, and Listing pages should display the currently logged in user's preferred language. Fallback to a language-neutral version, or some sort of negotiation if the 'preferred' language isn't available, would probably make sense. I can't help but think that centralizing that logic in some way, and allowing listing pages from various modules to take advantage of it if appropriate, is preferable to reproducing the same config options and logic everywhere.

Perhaps I'm misunderstanding the nature of the problem? Admittedly, I've only worked on a small number of sites that really utilized the localization system.

Gábor Hojtsy’s picture

@eaton: well, you/we need to draw a line in the sand, you certainly included display information on a per content type basis (author and time info checkbox), so that is not centralized. People rightly question these decisions. I do agree that having a centralized place to configure language filtering is better than nothing, I'm not sure its great UX or that we can provide a centralized listing UI for arbitrary objects like aggregator posts or listing of users. I can imagine a centrally provided language filtering widget that you could reuse in your config UI and then implement the actual query components in your module for your entities, nodes, users, aggregator posts, etc. Anyway, really don't want to derail this conversation, we can come back to language support for listings as a question in a different issue too.

Bojhan’s picture

Issue tags: +Usability

I would support this direction for the standard profile it makes sense to have better defaults when it comes to created listings and blocks. I have no idea why you placed the admin settings like that though.

Let's consider some problems we haven't solved here though:

  1. We are increasing the clutter on the block pages, simply by adding more by default
  2. We have to consider enabling this functionality for basic page/article content types or not, by default
  3. There is little to no discoverability of these pages/blocks. We have a page where you can "find" blocks, but not a page where you can find pages.
  4. You solve the problem of configuration of these blocks/pages by saying, there should be no configuration. Which makes sense in many ways, but also short term thinking in educating our users of this flexibility. This is my biggest concern, I'd love to discuss this more on IRC.
eaton’s picture

I would support this direction for the standard profile it makes sense to have better defaults when it comes to created listings and blocks. I have no idea why you placed the admin settings like that though.

Toggling the feature on and off on a per-content-type basis seemed to make sense; other than that, there's no particularly solid reason for where the settings went. I'm open to any and all ideas on that front.

We have to consider enabling this functionality for basic page/article content types or not, by default

That's an issue for the profile to figure out -- clearly Minimal isn't going to use it. The 'Snowman' profile will be using it for a number of content types, which is why the functionality is needed. The standard profile is in an odd place - articles are already promoted to the front page by default, so they have an obvious place to live, while pages don't. I'm not sure a listing page of pages makes a lot of sense, though. Open for discussion.

There is little to no discoverability of these pages/blocks. We have a page where you can "find" blocks, but not a page where you can find pages.

Emma Jane Hobgin in IRC has suggested that the listing pages themselves should be added to a sidebar block, or perhaps a custom menu that's displayed in a sidebar block. That would make them relatively easy to enable/disable, just by editing the menu block.

Also, I'm not particularly happy with the /content/$type paths use for the pages, but I'm stymied trying to come up with a better location. Simply placing the pages at a top level url like http://sitename.com/$type could work, but the odds of a collision with existing paths is very high. /node/$type doesn't work, as we've already overloaded the /node path beyond recognition. I'm leaning towards the idea of moving the default '/node' listing page over to the same url path as the pages generated by this feature. In that model the default front page would be at /content, the listing pages would be at /content/$type, and so on. That would leave /node as an orphan path, however, and people wouldn't be able to hack /node/1 to get back to the root level page. I think better handling of the /node page is probably a separate issue.

You solve the problem of configuration of these blocks/pages by saying, there should be no configuration. Which makes sense in many ways, but also short term thinking in educating our users of this flexibility. This is my biggest concern, I'd love to discuss this more on IRC.

This has been a topic of some debate, and I feel really strongly that the long term solution is to use Views. Period. Once we start adding a pile of different configuration options to these pages ("Only show things tagged with X, only show articles with a photo attached, show 20 items on this page but 15 on that one...) we're on the road to rebuilding Views in core, and that's a losing game. Getting Views into core is a good goal, but building it piecemeal on top of a simple feature like this would be a recipe for #fail.

Based on the R&D sites we built for snowman earlier this year, the "80%" problem is not being able to list content types on their own page, and the simplicity of the solution is a major feature IMO. I'm happy to discuss it IRC, though. ;-) I'm popping in and out of #drupal-contribute, and there's also a #drupal-snowman channel that I and a number of people hang out in.

Bojhan’s picture

I have had a long discussion with eaton on IRC, to better understand the scope of Snowman and how it effects Drupal. While Snowman is clearly defined in its purpose, "Default profile" is not - therefor determining when functionality should be enabled in the default profile is a difficult discussion to have. However as we have always done, we can do it on a per case basis - and for this piece of functionality I think it makes sense to enable it in the Default profile. Because it provides a smart default for content types, which if "promoted to frontpage" is disabled often leaves people guessing where content goes.

Discoverability of the content type listing can be solved by adding a "All items" link at the bottom of a recent pages content type block.

I agree with the current UX around configuration of pages and blocks, that we should avoid adding any additional options. Although this is a short-term solution to our flexibility problem, we have applied this method in D7 consistently.

We could consider placing the creation of these blocks and pages in their own vertical tab. This would follow a similar pattern to other places in core, such as menu creation as vertical tab in content creation.

eaton’s picture

We could consider placing the creation of these blocks and pages in their own vertical tab. This would follow a similar pattern to other places in core, such as menu creation as vertical tab in content creation.

Makes sense. That also gives other modules a sensible place to put related options. Any thoughts on what tab title would make sense for it? Display pages? Viewing options? Listing options?

eaton’s picture

A couple key issues are fixed in the dev sandbox version of the code. The config options are now in their own vertical tab and have descriptions, though the JS to update the vertical tab isn't in place yet. As per webchick's comments in IRC, turning on a page and visiting it when there's no matching content nets a "No content has been created" message, and a link to create a node of the appropriate type.

Keeping the code in a separate module makes sense right now but it's definitely requiring some duplicate code. I think it's obvious after some investigating that the code to generate these pages should live in the same location as the code to generate the standard /node page and /rss.xml feed. That leaves us with two choices:

  1. Roll this code directly into node module, and refactor node module's node_page_default and node_feed functions to support it cleanly
  2. Move the site front page and the standard feed OUT of node.module into this module, and start rolling a real core patch.

I lean towards the latter option, because I dislike the hard-coded nature of the front page listing of promoted content, but I'm on the fence about which direction to pursue. Thoughts, anyone?

joachim’s picture

> I took a quick stab at what this might look like and created a single custom module that does all of what's described above.

This already existed in contrib: http://drupal.org/project/nodetypeviews
Has an alpha for D7 too!

sun’s picture

I dislike the hard-coded nature of the front page listing of promoted content

Yes! Also struggled with this in #375397: Make Node module optional

valderama’s picture

after reading through this issue, i'd like to say that having this simple listing pages sounds like a great idea to me. with the ability to create custom content types, the possibilty to easily create listings is almost a must :)

when i first used drupal, such super easy and quick built-in functions were amazing ;) they can motivate people to spend more time on drupal (and then finally discover views :)

eaton’s picture

OK, this has been brewing for a week or so and I had a chance to chat with Bojhan in IRC about one of the issues that concerned me the most: the path handling. He feels that inconsistency in the paths is acceptable at this point -- ie, /node, /node/1, /content/articles, and so on -- because few users actually navigate by URL. It still leaves us with the problem of menu-tree management; IE, does /content/articles get highlighted in the nav menu when you're on an article node. I lean towards 'Yes,' and I'm going to write the patch with that assumption in mind. Because the goal is to provide a single checkbox that handles all reasonable behaviors, I think that's probably for the best.

For the time being, I'm going to punt on the node module separation issues and just roll this functionality into node.module. Subsequent patches that focus on splitting this functionality (and the front page) out into a separate optional module should come later, unless someone is feeling super ambitious.

sun’s picture

does /content/articles get highlighted in the nav menu when you're on an article node

(Very) Common misinterpretation of menu router and menu links: Active trails in menus are generated from menu links, NOT the menu router. If desired, you can have an active trail that looks like admin/foo » node/2 » user/3/edit (of course, you don't see the paths but the breadcrumb with menu link titles instead). What matters is what links you have in your menus.

The menu router is only ever used as "fall-back", and only in the sense that menu_rebuild() attempts to make sure that hierarchically registered menu router paths also end up as hierarchical menu links if possible, even though that is in no way guaranteed (by design).

FWIW, Node module registering paths in the form of node/[type] that make a clear difference in data type and value to node/$nid sounds fine to me.

eaton’s picture

Here's a first pass at an actual patch; it's definitely still rough and the node/%node_type paths are currently not possible -- the menu router collapses all wildcards to '%' in the actual router table, so it collides with node/%node. I've got them at content/%node_type as discussed, at least for the moment.

Outstanding problems:

  • Page generation duplicates node_page_default() code.
  • Probably should use entityFieldQuery() rather than db_select()
  • Function names are a little funky, but that's par for the course in node.module.
  • Proper title should be generated for RSS feeds. Perhaps '[Site name] - Latest [type] content'?
  • Node Type Page needs a summary value for the 'Content list' vertical tab.
  • Paths still kind of suck; using /content is crummy, but node/%anything doesn't work.

Potential follow-up-patches:

  • Block generation code should probably be themable.
  • Breadcrumb trails/active trails don't reflect the sub-listing pages. Discussed this with Sun and it might be a future feature request.
  • This functionality, the default front page, and the default RSS feed paths should all be moved to a separate module. Probably best save that for a future patch.

At this point, it would be great to hear some feedback from both UX team members, site builders, core devs, and core committers who have thoughts or input on this.

Bojhan’s picture

I have just done an initial pass, a few of the things that could work from a UX perspective :

1) It is probably better to put the settings in a separate field set rather than vertical tabs, if we redesign field ui this might fit in better. But its a bit weird to hide important "creation" functionality in meta vertical tabs.

2) The drupal_set_message after enabling this configuration is missing. It should mention a block is created at blocks and a page is created at content/article/

3) There is no block title that a user can change?

4) The checkbox/description could probally use some work (for example, Create a page that lists *article* content).

Bojhan’s picture

Status: Needs work » Needs review
eaton’s picture

1) It is probably better to put the settings in a separate field set rather than vertical tabs, if we redesign field ui this might fit in better. But its a bit weird to hide important "creation" functionality in meta vertical tabs.

Hmmm. That would make this the only core functionality for content types that's NOT in a vertical tab set. Is that kosher? I'm not against it, just wanted to make sure it followed the existing patterns. Since it's also an easily toggle-able behavior I assumed that it wouldn't be problematic leaving it out of the main flow.

2) The drupal_set_message after enabling this configuration is missing. It should mention a block is created at blocks and a page is created at content/article/

Good catch, thank you! I hadn't even thought of that...

3) There is no block title that a user can change?

Admins can override any block title -- we don't have to make special provisions for it here. Is there a downside to letting them use the common "Custom block title field?"

4) The checkbox/description could probally use some work (for example, Create a page that lists *article* content).

The only downside to this is is that when you first go to create a content type, the typename isn't known and the text is funky. I just realized, actually, that it causes problems for the existing description text, where we try to say what the path will be. Does anyone on the tweaky dev side know if there is a workaround for this, or should we just be sure to use type-name-neutral language in the labels and descriptions?

sun’s picture

Status: Needs review » Needs work

This doesn't look too bad to me. Wondered whether we couldn't re-use some more existing node_page_*() functions and/or whether there couldn't be a query helper function to not repeat more or less the same manually crafted query all over again.

+++ b/modules/node/content_types.inc
@@ -196,6 +196,25 @@ function node_type_form($form, &$form_state, $type = NULL) {
+    '#title' => t('Create a listing page.'),
...
+    '#title' => t('Create a listing block.'),

The term "create" only makes sense when creating a new content type; but when editing an existing, and when the box is already checked, this might read/look a bit odd? (will it "create" another one? ;)

+++ b/modules/node/node.module
@@ -2042,6 +2047,22 @@ function node_menu() {
+  $items['content/%node_type/rss.xml'] = array(
+    'title callback' => 'node_type_page_title',
+    'title arguments' => array(1),

Does a RSS callback need a title?

+++ b/modules/node/node.module
@@ -2103,6 +2124,13 @@ function node_block_info() {
   $blocks['recent']['info'] = t('Recent content');
...
+      $blocks[$type->type]['info'] = t('Latest @name content', array('@name' => $type->name));

I think the info should be "Recent" instead of "Latest" (consistent with the existing "administrative" block).

Oh, and we definitely want a prefix in the delta keys; e.g., 'recent_'

+++ b/modules/node/node.module
@@ -2130,6 +2158,44 @@ function node_block_view($delta = '') {
+      $types = node_type_get_types();
+      if (isset($types[$delta])) {
+        $type = $types[$delta];
+        if (user_access('access content') && variable_get("node_list_block_$type->type", FALSE)) {

I think the user_access() and variable_get() conditions should come first, since they're faster.

+++ b/modules/node/node.module
@@ -2130,6 +2158,44 @@ function node_block_view($delta = '') {
+            // TODO: Make this themable?
+            $block['content']['list'] = array(
+              '#theme' => 'item_list',
+            );
+            foreach ($nodes as $node) {
+              $block['content']['list']['#items'][] = l($node->title, 'node/' . $node->nid);
+            }

Just simply make it themeable by using

#theme => 'links__node_type_block'

+++ b/modules/node/node.module
@@ -2130,6 +2158,44 @@ function node_block_view($delta = '') {
+                '#markup' => theme('more_link', array('url' => "content/$type_url_str", 'title' => t('Read more'))),

Let's use #theme => 'more_link' here

+++ b/modules/node/node.module
@@ -2581,6 +2674,57 @@ function node_page_default() {
+    drupal_not_found();

return MENU_NOT_FOUND;

+++ b/modules/node/node.module
@@ -2581,6 +2674,57 @@ function node_page_default() {
+  $nids = db_select('node', 'n')
...
+    ->extend('PagerDefault')

->extend() normally comes directly after ->db_select()

+++ b/modules/node/node.module
@@ -2581,6 +2674,57 @@ function node_page_default() {
+        '#theme' => 'item_list',
+        '#items' => array(l(t('Add new content'), "node/add/$type_url_str")),

Let's use #theme 'links' here?

+++ b/modules/node/node.module
@@ -2581,6 +2674,57 @@ function node_page_default() {
+    drupal_add_feed("content/$type_url_str/rss.xml", variable_get('site_name', 'Drupal') . ' ' . t('@name RSS', array('@name' => $type->name)));

We can use #attached][feed here.

+++ b/modules/node/node.module
@@ -2581,6 +2674,57 @@ function node_page_default() {
+  drupal_set_title(t('Latest @type content', array('@type' => node_type_get_name($type))));

I think this could be moved to the top of the function. Also, one more instance of "Latest" here.

24 days to next Drupal core point release.

kika’s picture

I am fine with vertical tab for now. Just wondering about the vertical tab descriptions, should they be "Page, Block" or "Create page, Create block" when enabled?

kika’s picture

Another, wider issue is the discoverability and flow of this feature -- initially it's not super-clear where I can see those listings in action, you gotta create a _block_ first to ever discover the listing _page_ (by clicking "More" link).

eaton’s picture

Another, wider issue is the discoverability and flow of this feature -- initially it's not super-clear where I can see those listings in action, you gotta create a _block_ first to ever discover the listing _page_ (by clicking "More" link).

Indeed. One person suggested creating actual menu links in the nav sidebar for each of these pages, but that would require them to be top-level items (ie, /article rather than /content/article or /node/article) to automatically show up. Thoughts, anyone?

In the Snowman profile that's being planned, the assumption is that these blocks will be activated for most content types and links to the listing pages will already be in the primary links. They're easier to demonstrate than they are to discover.

eaton’s picture

Status: Needs work » Needs review
FileSize
21.25 KB

Great feedback from everyone -- thanks! This version incorporates most of the comments made so far. A minor exceptions:

This doesn't look too bad to me. Wondered whether we couldn't re-use some more existing node_page_*() functions and/or whether there couldn't be a query helper function to not repeat more or less the same manually crafted query all over again.

We definitely could, I think. I'd like to make a helper function for the little 'create a url-safe version of the machine name' snippet, and I'm wondering whether anyone sees value in having a version of node_type_get_type() that just takes a type name instead of a full node (that would save a bunch of odd little snippets, but probably not have a big impact on the overall code footprint).

Merging the page generating functions would make the queries themselves simpler -- a simple switch would allow us to add a type filter or a 'promoted' filter, for example. The downside is that the ordering of the logic for both pages is a little tangly; things like 'what should be there on the empty page' and 'what should the RSS feed URL be' need to be handled after the query is run, and the MENU_NOT_FOUND needs to be returned very early in the process, so at least at some point it would get tangly. One function would make sense though, and it's on the to do list once some of the underlying functionality and behavior is better settled.

catch’s picture

Indeed. One person suggested creating actual menu links in the nav sidebar for each of these pages, but that would require them to be top-level items (ie, /article rather than /content/article or /node/article) to automatically show up. Thoughts, anyone?

With menu_link_save() that's not a requirement, they could just be put top-level. I don't have a strong opinion either way on whether the link should be created or not.

+++ b/modules/node/content_types.inc
@@ -196,6 +196,25 @@ function node_type_form($form, &$form_state, $type = NULL) {
+    '#title' => t('Create a listing page.'),
...
+    '#title' => t('Create a listing block.'),

Maybe 'Provide...'.

Haven't looked at the patch yet.

eaton’s picture

I like 'Provide' - I'll change that in the next roll of the patch.

dasjo’s picture

subscribe

dasjo’s picture

subscribe

tim.plunkett’s picture

FileSize
10.59 KB

Rerolled, with Provide instead of Generate. Also removed trailing whitespace.

catch's comment in #37 was actually on an older chunk of the patch, due to it being rolled with git format-patch. This is just git diff, so it's all in one.

catch’s picture

We can replace one page (/blog) that used to be provided by the newly removed blog module with this, see #1263208-3: Upgrade path for blog module removal.

eaton’s picture

We can replace one page (/blog) that used to be provided by the newly removed blog module with this, see #1263208-3: Upgrade path for blog module removal.

Only if we solve the 'where do these URL paths end up' question. 'blog' would be replaced with 'content/blog' in the current patch, which I'm OK with for a first pass. The specific path is easy for us to create, it's just a matter of deciding where a consistent location will be that doesn't collide with other stuff.

eaton’s picture

This is pretty much where I'm hoping that we can get a once-over from Dries or Webchick. At this point, the patch is functinoal, useful, and what improvements could be made to it go in a number of different directions. (Making our pathing more consistent across core, consolidating node module's internal listing pgae code, adding support for this same functionality across all bundle types, and so on.) Each of those would qualify as a separate patch, IMO, if this one gets the thumbs up.

Anyone else have any thoughts on this?

catch’s picture

content/blog is fine, I just meant replacing the list of blog posts as opposed to the path (although the upgrade path could add an alias).

sun’s picture

Meanwhile, I think that the only proper way to implement the internal/router-facing side is in a RESTful-alike manner:

http://example.com/node?type=blog

That is, because

  1. There is no technical difference between /node** and /node?type=blog except for the filtering by node type.
  2. The very same principle can be applied to every other entity type, say, taxonomy/term?vid=tags.
  3. People that don't like the query parameter can still use a URL alias to hide it.

** The current /node output only containing promoted nodes is obviously bogus.

kika’s picture

** The current /node output only containing promoted nodes is obviously bogus.

how would you map existing promoted nodes?

sun’s picture

Issue tags: +Platform Initiative

how would you map existing promoted nodes?

I know that's an open question, but in terms of this issue/initiative, I actually think we don't have to care for it. The focus is on per-bundle listings only. Fixing and restoring sanity for /node is a completely different task and challenge.

eaton’s picture

Status: Needs review » Reviewed & tested by the community

After a brief discussion with webchick, I'm marking this RTBC. The outstanding issues with the patch are not related to the underlying functionality, rather to our overall strategy on RSS exposure, pathing conventions, and entity related functionality. Each of those, IMO, deserves a separate issue to iron out the details as they affect more than just this feature.

sun’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/modules/node/content_types.inc
@@ -196,6 +196,32 @@ function node_type_form($form, &$form_state, $type = NULL) {
+  $form['lists']['node_list_current_settings'] = array(
+    '#type' => 'value',
+    '#value' => array(
+      'page' => variable_get('node_list_page_' . $type->type, FALSE),
+      'block' => variable_get('node_list_block_' . $type->type, FALSE),
+    ),
+  );

@@ -323,7 +349,7 @@ function node_type_form_submit($form, &$form_state) {
+  unset($variables['form_token'], $variables['op'], $variables['submit'], $variables['delete'], $variables['reset'], $variables['form_id'], $variables['form_build_id'], $variables['node_list_current_settings']);

@@ -357,6 +383,14 @@ function node_type_form_submit($form, &$form_state) {
+  if ($variables['node_list_block'] && !$form_state['values']['node_list_current_settings']['block']) {
+    drupal_set_message(t('A block listing recent %name posts has been created, and can be configured on the !link.', array('%name' => $type->name, '!link' => l(t('block administration page'), 'admin/structure/block'))));
+  }
+  if ($variables['node_list_page'] && !$form_state['values']['node_list_current_settings']['page']) {
+    $type_url_str = str_replace('_', '-', $type->type);
+    drupal_set_message(t('A page listing recent %name posts has been created, and can be viewed at !link.', array('%name' => $type->name, '!link' => l("content/$type_url_str", "content/$type_url_str"))));
+  }

The _settings value is superfluous. Needs to check against #default_value in the form instead.

27 days to next Drupal core point release.

joachim’s picture

> http://example.com/node?type=blog

I can understand how that's logical and consistent and everything, but with paths like that, who needs clean URLs!!! I hope when you say 'internal' you mean 'nobody will ever see it unless they want to use the REST server'.

jenlampton’s picture

Jumping in here because I want apply the same patterns to taxonomy and the front page too.

yoroy’s picture

Would be great to see a re-roll of #41 updated with the feedback in #50 incorporated. There's consensus on the feature, lets add a useful feature to core!

swentel’s picture

Status: Needs work » Needs review
FileSize
9.92 KB

Here's reroll for the new core structure, with feedback of #50.

moshe weitzman’s picture

Once we have Views in Drupal Core, we'll easily get this. But I can see value in committing this now, and changing implementation to Views once thats in.

tim.plunkett’s picture

FileSize
9.84 KB

Rerolled due to Paths containing content type names no longer replace underscores with dashes as well as the renaming of PagerDefault to Drupal\Core\Database\Query\PagerSelectExtender

I agree with moshe.

xjm’s picture

Issue tags: +VDC

Tagging.

xjm’s picture

Status: Needs review » Postponed
yoroy’s picture

Status: Postponed » Active

Soooo, I see views is in core for realz. Lets do this. Still a great feature to have and an ideal entry point for getting to know and working with views (content lists). Major even, from that perspective.

What kind of work does this need now?

- #21 has inspiring screenshots
- #22 mentions http://drupal.org/project/nodetypeviews
- #54 has the last patch pre-views in core which was basically rtbc

moshe weitzman’s picture

Latest work is is #1806334: Replace the node listing at /node with a view. Not sure if we should call this a dupe or not.

yoroy’s picture

Maybe this should be postponed on how things get figured out there, then we come back here and implement the per-bundle checkbox?

klonos’s picture

#1806334: Replace the node listing at /node with a view is in for some time now. Can we get this moving again?

eaton’s picture

A very, very simple version of this feature can be rolled using Views. The four questions still remaining are the trickiest ones:

  1. URL path structure. Using /node/[type] is a nonstarter as it collides with our standard node/1 URL paths. Using /content/[type] seems uncontroversial, but also implies that /node should really be /content. I'd be +1 on changing that. Thoughts?
  2. Navigation questions. Nav menus links for these content type list pages would make a lot of sense. Figuring out the best place for them feels like a companion question to the path structure.
  3. Pluralization and language. As mentioned earlier, URLs like /content/article make less sense than /content/articles. In addition, titles like "Latest Article Content" are less desirable than "Latest Articles." Using one contextual-filter-driven View makes sense from an implementation standpoint, but makes it very difficult for site builders to override language without baking plurals into the content type definition. That's sadly a nonstarter due to the complexity of capturing "localizable plural forms."
  4. If we don't use a contextual filter approach, we'll need to bolt a checkbox or somesuch onto the node type editing form, and generate a one-off custom view for each content type that the option is checked for. That makes customizing the paths and so on a lot easier, but adds code complexity. Any thoughts on which direction would be best?

Status: Active » Needs review

jibran queued 56: drupal-1210366-56.patch for re-testing.

Status: Needs review » Needs work

The last submitted patch, 56: drupal-1210366-56.patch, failed testing.

mitokens’s picture

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.