Feature #1892

New simpleviews box

Added by Jon Sagotsky almost 4 years ago. Updated almost 4 years ago.

Status:In QAStart date:02/27/2012
Priority:NormalDue date:
Assignee:Jon Sagotsky% Done:


Category:New functionality
Target version:2.0-RC1


Make a new simpleviews box that modifies a generic view (vsite_view_base) instead of creating a brand new one. Other content types can extend this to provide their own options, the goal of which being less copy/paste when making special case boxes like presentations and publications.

Start this in D6. Expect porting to D7. Also we may use this for creating menu links to new pages, so don't limit it to boxes.

  1. Base class provides the usual simpleviews options
    1. Name, title, title/teaser, # displayed posts, pager
    2. More link (hiding additional more link options when more is unchecked)
    3. Sorting
  2. Multipart form, changes to secondary class after clicking next.
    1. When editing an existing box or going back to an earlier form step, form should already be filled out.
  3. Content type classes defined by each content type as ctools plugin.
    1. Content type classes do not show up in widgets list (no title elem), but are accessible by choosing a content type in the form.
    2. Content type classes load parent form, then add their own elements. Presentation date for instance.
  4. Form options must work in all views
    • Most content types will use the os_simpleview_list_base view the module provides. Check each option on one of those content types. Content types that implement their own plugin will likely change the view and should be tested as well:
      1. Confirm for presentations
        1. Check additional sort option defined by presentations
      2. Confirm for books
      3. Confirm for publications
        1. Check additional page of options defined by publications

See fb_social for similar plugin

  • Boxes exports for scholar_{presentations,announcements,reader,book,publications} have changed. You may need to revert the features to test them.


#1 Updated by Jon Sagotsky almost 4 years ago

  • Status changed from New to In Dev
  • % Done changed from 0 to 50


First attempt's progress so far.

Created os_simpleview_list module. Not sure this will stay in its own module, but I wanted to keep it isolated for now.

Began new plugin. This plugin defines forms, defaults, and rendering. It uses similar logic as a box without actually being a box. I have a default plugin and started another one for presentations.

Also made os_simpleview_list into a box extending os_boxes_default. This one loads a class defined by one of the other plugins and loads its options_defaults/form/etc. As a content type is selected I can load up a new class at this point.

What I'm stuck on right now is figuring out how to get a multipage form in there. I haven't done one of those before. I plan to try making the form in a regular page and then once I understand it better, push it into the widget config box. Once I get that done I'll start on render.

#2 Updated by Jon Sagotsky almost 4 years ago


Began writing multiform_info function. I figure this will be called at the lowest child and modified along the way, allowing subclasses to add and alter pages.

Got stuck on ctools_wizard_multistep_form. I was expecting this to prepare a form for multistep mode. Instead it does that and renders the form, giving me HTML. This is useless to a box's options_form(), so I'm not really sure how to handle this case. boxes_box expects to be given a form array and handle the processing of that itself. So far all my ideas for how to get around that are either ugly hacks or massive rewrites.

#3 Updated by Jon Sagotsky almost 4 years ago


It works. The first page collects content type. If that content type has a plugin, that plugin has a chance to modify the existing forms and/or multiform steps. Forms defined in the plugin class are called appropriately.

There's a bit of chicanery involved in getting a plugin's class to load. ctools expects to receive the name of a form function so it can call that function and get the form array. When this happens, instead of passing ctools a form id that's buried in an object, I give it os_simpleview_list_class_form, which is defined in my module file. This form figures out what plugin to use based on form state, instantiates an object, gets the form array, and passes that back to ctools as expected.

One odd effect I've found is that I need to have multiple pages before a content type's page can be added. The reason is that if I try to start with a single page, the wizard expects to finish at the end of that and will never load up the list of pages for after a content type is selected. Because we have options beyond the first page, this isn't a big deal. If it ends up being problematic I may have to add an 'are you sure you want to save' page at the end.

Still some rough spots, but it's functional for passing the form off to different plugins. After lunch will work on either finishing the form (saving to box or menu depending on context) or on setting up defaults sanely.

Also wondering how editing an existing box is going to work out. That's where I'm worried about setting the default values above. I don't expect it to be difficult, I just haven't gotten that far yet.

#4 Updated by Jon Sagotsky almost 4 years ago


  1. Began setting this up to be configured in a modal frame. First form loads. Next form looks like it's returning a whole page and throws an error in the modal.
  2. Completion of the multiform creates a box of type os_simpleview_list_box. This box checks its content type against the available simpleview_list plugins. If a plugin is provided for that content type, it uses the appropriate plugin. Otherwise it sticks with the default. Content type plugins will render, load forms, etc with parent::function and then modify the results.
  3. I got started on making the default plugin's views_alter function handle box options. So far it does pager, number of items, content type, and (in theory) display style. Had to give this function an extra options array, so the box object could pass its options along.

Filling out more option handling will be straightforward. The box isn't using the default options I've provided yet. Still working on getting the multistep form to display right in the modal. Haven't even though about how to save this to a page (could a page with only a box as its contents work?). Slightly worried about what will happen when people edit the box. Will its content type have to be set in stone once its created? If you use the form to make a presentation and then change it to a publication, there will be saved options that no longer apply. I'm not sure that figuring out how to clean those up is worth the trouble when it's so easy to just recreate the box/page.

#5 Updated by Jon Sagotsky almost 4 years ago


Separated multiform_info. The form labeling and order remains part of the plugin. The multistep configuration is part of the module. The idea is that someone implementing a plugin should not see the removed section.

Began ctools ajax prep, but haven't finished it.


Split up os_simpleview_list_default. Made part of it into an abstract class to help guide plugin authors. Default form specifics remain in default. This was a little messier than intended because my third party plugin (scholar_presentation) was no longer extending the default plugin.

Because of this I had the module always load the default plugin's forms. If there's a plugin that provides forms for the selected content type, it also can add forms. It bloats the module a little, but plugin writers won't notice. It does help by removing class from the form array, since I'm able to determine what class is used when loading forms.

Began view_overrides function, which reads through the form options and gives back overrides to apply to the view handler. I'm still a little unclear on how much of this should be provided for all and how much should be left up to the plugin. What I'm aiming for is providing some functions in the abstract class that plugin classes can call or not as they need. For instance, given a sorting method - newest, oldest, or a-z, - return an array describing those sorts for views. This is something that we don't want every plugin to rewrite. But the function should be easily overridden. Still not sure about this approach.

Changed view_name and display_id to be part of an object returned by a function. I couldn't have an abstract variable, but an abstract function that returns variables will make things more explicit for plugins.

The generic class form merges the default options with the options that have already been set and passes those to the plugin's form. This not only lets the default options work as advertised, but it also means that stepping back through the form will no longer lose the options you've set. Will need some similar logic when it's time to let users edit the box/page.


I'd like to finish honoring all the options I've presented.

I also made a new view, but haven't exported it yet because it's still a work in progress.

#6 Updated by Jon Sagotsky almost 4 years ago


Added views overrides for all options in os_simpleview_list_default.

More link, as we were using it, was not part of views. The way that views does the more link is that they build the path on the fly and have no option to provide your own path. All our boxes were appending a link to the contents of the box. I repeated that behavior here to maintain consistency.

The way I've been trying to make these views overrides extensible is by providing functions in os_simpleview_list. They're currently _parse_options_OPT. Basically I expect a number of plugins to want to set title/teaser, so if they do nothing, they get the default overrides. If they implement their own _parse_options_display, they could do something completely different or just add options to what exists. ie, case ('full'): //code; break; default: parent::_parse_options_display;break;.

Still need to export the view. Would also like to make sure box creation/editing works in modal.

#7 Updated by Jon Sagotsky almost 4 years ago


Backtracked on os_simpleview_list. Using that as an abstract class that os_simpleview_list_default was confusing. I was trying to put default behavior into both classes so that other plugins could make use of it. For instance, I needed presentations to extend the display options form so that it could add presented date as opposed to created date to the sort options. If the form lived in the default plugin, the presentations plugin just ended up

Instead os_simpleview_list is now an interface. Plugins that make use of it will have some guidance about what they need to implement. os_simpleview_list_default implements it and provides defaults. The presentation plugin will extend that.

#8 Updated by Jon Sagotsky almost 4 years ago


Set up the presentation plugin. This involved overriding 4 functions from the default plugin:

options_defaults() - Change the url of the more link.
os_simpleview_list_form_display_options() - Call parent and add a "recently presented" option to the sort select, then return the whole thing.
view_settings() - Declare which view/display we're using.
_parse_options_sorts() - Look at the box's saved options and provide sorting options for "recently presented". If that's not selected, use the default plugin's sorting.

I was also having trouble with filters because I was overriding the existing ones. Wrote another function for handling options that are appended to current view instead of replacing them.

Cleaned up a lot of leftover code.

#9 Updated by Jon Sagotsky almost 4 years ago


Included the default view I was using as a feature.

More link is automatically detected in default plugin. Removed that override from presentations plugin.

_os_simpleview_list_content_type_to_vsite_path() takes a content type and uses features_get_component_map() and vsite_menus_get_feature_menu_item() to determine its path in the current vsite. This should probably by moved into another module where it makes more sense and someone else might find and recycle it.

At some point I broke the form_state/cache interaction. Going back a page loses previous form state. Need to doublecheck all that.

#10 Updated by Jon Sagotsky almost 4 years ago


Added plugin for scholar_books. Trivial. All it does is change the view. This and all the other special case views should get some extra care during testing.

#11 Updated by Jon Sagotsky almost 4 years ago


Began publications plugin.

This involved a bit of a rewrite for plugins passing options to the box. The generic box had been using its content type to fetch options from the list plugin. This didn't work when creating a new box and passing it new option defaults. Boxes will only set options that are currently defined in options defaults. Anything else is thrown out. It was able to set the content type, but the additional defaults hadn't been fetched yet because the content type was not known initially.

The solution was to add a plugin_opts array to the default options list for the default plugin. I can put whatever I want in that array. Still not sure if this should be exposed to the plugin writers or if I should try and conceal it.

Publications plugin is still incomplete. It adds a new form page which takes publication types and grouping options. The grouping options lets the plugin choose a view to display publications by year, type, or coauthor. The only problem with this is that it's mutually exclusive with the sorting option. I may end up making this a toggle. There would be an input lets you pick grouping or sorting, but not both, and the form would swap out group by or sort by accordingly. Still need to honor the which groups to include option.

#12 Updated by Jon Sagotsky almost 4 years ago


Finished off the publications plugin options. Biblio types can be restricted. Recently published sorting option works as well. I still haven't found a good way to communicate the exclusivity of sorting with grouping. I'm also not sure that recently published/newest/oldest will be clear on its own, but I have no other ideas that aren't too wordy.

Still not totally satisfied with the plugin_opts box option array. I've been starting to hide it from the plugin by merging it with the rest of the options before passing it back to the plugin, but I'm worried about how editing settings will work in that case. I feel like there will be a lot of pushing options between the base array and the nested one. Not sure how that will actually play out until I try editing plugin settings. Going to try to start that working now.

#13 Updated by Jon Sagotsky almost 4 years ago


Refactored a bit to deal with ctools. I don't think ctools ever intended a wizard to be inside a modal and I couldn't even get the example they provided to work. The form displays inside the modal and on a non-js page. Editing it displays the form, but I don't really handle editing yet. At any rate, now that it looks like the basics of making a wizard and sticking the wizard inside the modal are working I can start porting over the other stuff from prior to refactoring.

#14 Updated by Jon Sagotsky almost 4 years ago


Updated form to include cached values from previous pages and box opts for editing existing boxes. Boxes don't actually edit yet, but that shouldn't be hard to add.

What I got stuck on this morning was default values in the modal. They don't load. The default_values works in nojs, but not if js is enabled because of how ctools builds the form. According to http://drupal.org/node/678158 this is actually a problem with core forms, so merlinofchaos doesn't want to fix it, but the forms devs aren't interested either. That thread has a workaround, but I couldn't convince it to work.

Relatedly ajax-responders in the form aren't working when loaded via ajax. I think it's either part of the problem above or that events aren't attached when the new elements get loaded.

Editing the modal form mostly works until it's time to dismiss the form. Will look at that in the afternoon but I don't expect it to be anything complicated.

#15 Updated by Jon Sagotsky almost 4 years ago


Edited box gets saved at end of form. Modal still won't dismiss.

#16 Updated by Jon Sagotsky almost 4 years ago


Simpleview box now saves to space if it's in a space. Added support for saving top level options. By that I mean title, description and anything in $box. $box->options and $box->options['plugin_opts'] were already being saved. Saving the form still needs to dismiss the modal and refresh the page or at least the box.

Removed options_form from box. Having a blank form told boxes that there were no config options and removed the configure link from the contextual.

#17 Updated by Jon Sagotsky almost 4 years ago


Switched from modalframe to default ctools popup. That got rid of the dismiss problem and cleared out some of the code I was using to handle modalframe's quirks.

Still have to clean up some modal frame leftovers. Need to get defaults to show (which DOES work in the ctools example, so it is doable). Need to get new widget to show in layout and bounce like the other new widgets.

After that, the publications options could use some clarifying, but that's more of a user experience problem than a code problem

#18 Updated by Jon Sagotsky almost 4 years ago


Switching to ctools_popup changed the way the box was configured. modalframe had been overriding that, but now it's back to default box style. I tried changing the block_config_path, but couldn't find a good way to pass the delta for editing a previously created box.

I added an options_form() to my box, as boxes expects. What it does differently is call my form's page with ajax enabled. The output from that is then inserted in the modal instead of returning a form. Since boxes also uses options_form() to figure out if a box is configurable, I return a normal form when the box is not being edited. Right now I'm checking that with $_POST['js'], but there's probably a better option.

Still trying to work out default values.

#19 Updated by Jon Sagotsky almost 4 years ago


I use theme_status_messages() to check if any of the forms didn't validate. When that happens, the messages are passed back through instead of the new form.

Also got the form to finally load default values. Basically the problem was that the form builder was looking at posted values to figure out what form elements were present in the form. The elements that were added through ajax weren't always present, so they get ignored. As I understand it, this is only the case with how ctools builds forms - it doesn't happen elsewhere. I adjusted $form_state['input'] to include the form elements I'd be including, so now their default values (as well as user entered values if the user goes back a step in the form) show up by default.

Forms loaded via ajax are not using their dependent elements. The more link options are always displayed whether or not the more link is enabled. Looking into this next.

#20 Updated by Jon Sagotsky almost 4 years ago


Switched out my own ctools_ajax commands for ctools_modal_form_render. This returns form_errors correctly for and attaches javascript correctly so dependent elements work right.

I still have to handle what happens when the form finishes. New box is created, but needs to be added to layout icons and told to bounce. There's also some old cruft that needs cleaning. I believe the basic functionality is all correct right now though.

#21 Updated by Jon Sagotsky almost 4 years ago


Newly created boxes are now added to the layout page's list of icons via ajax instead of forcing a page reload.

Still not sure where to put users if they're using the form outside of cp, but I'm not sure that'll actually happen.

#22 Updated by Jon Sagotsky almost 4 years ago

Updated requirements. I think this is just about ready for QA. I'd still like to improve the publications form. Page 2 asks for sorting. Page 3 asks for grouping (by year/type/co-auth etc). These are mutually exclusive and the user shouldn't be filling out both. Still figuring out how to present that.

#23 Updated by Jon Sagotsky almost 4 years ago

  • Status changed from In Dev to In QA
  • % Done changed from 50 to 90


Added a page refresh after configuring the widget outside of cp. This is how the other boxes work.

Marking as QA.

#24 Updated by Richard Brandon almost 4 years ago

  • Status changed from In QA to In Dev
  • % Done changed from 90 to 50

Jon, I don't see an update hook for this? Shouldn't this module be installed by default? What is the migration path for existing boxes that use plugins that this replaces?


#25 Updated by Jon Sagotsky almost 4 years ago

Richard Brandon wrote:

Jon, I don't see an update hook for this? Shouldn't this module be installed by default? What is the migration path for existing boxes that use plugins that this replaces?


See the notes in the description. The module name isn't finalized, so I haven't written an update_hook yet. I would like the basic functionality tested sooner than later though. Migration path will probably need some discussion.

#26 Updated by Richard Brandon almost 4 years ago

I think all boxes plugins that this can replace should be rolled into this plugin with an update hook and changes to the exported box. (Assuming all the existing functionality can be preserved).

Document List
Publications List
Presentation List
Publication (the other three publication boxes)
Old SimpleView List

Having those 7+ plugins rolled up into this one excellent wizard will really releave some confusion for users.

#27 Updated by Jon Sagotsky almost 4 years ago


Removed _list from module's name. Found a bug preventing the view from exporting.

Will continue migration.

#28 Updated by Jon Sagotsky almost 4 years ago


Began update hook to migrate boxes. I got recent docs and presentations. The rest should come more quickly. I've also been updating the box exports as I go.

Found and fixed couple bugs involving plugin_opts.

Migrated recent docs don't hide the teaser when set to display on title. Need to look into this more.

#29 Updated by Jon Sagotsky almost 4 years ago


Added publications by year, type, and co-author to update hook.

Figured out what was wrong with docs title only display. It was using a different view than the basic one so I had to override it to use fields. Did that for the three pub ones as well.

My publications plugins were missing the switch to toggle whether or not category counts were displayed. I added that in.

Found another problem. Checkboxes weren't uncheckable. When a checkbox is unchecked, the browser sends nothing. I've been using array_merge to combine current form options with existing box options and default settings. This was problematic. A checkbox that's set by default, but unset by the user will not be present in the list of user settings and will be overwritten when I merge with the defaults. I dealt with this in a naive but straightforward way. A hidden element holds a list of checkboxes. Before I start merging box settings and default options, I look at the list and explicitly set any of those checkboxes to false if they weren't included in form_state's input.

Still have to add this batch of publication widgets to the exported boxes. Also, pub_groups' whitelist is probably not being honored correctly by the update hook.

#30 Updated by Jon Sagotsky almost 4 years ago

Still have to add this batch of publication widgets to the exported boxes.

Incorrect, those boxes are not exported.

#31 Updated by Jon Sagotsky almost 4 years ago


Removed support for publications group. This widget is supposed to create lists. A grouping is no longer a list. The grouping widgets will remain as they are. Let the previous commits exist as a proof of concept of the flexibility of the module.

This has the advantage of removing the grouping options from the form. With those out of the way, I moved the publications type selector back to the display options page, so we're back down to two steps for the form.

#32 Updated by Jon Sagotsky almost 4 years ago


Update hook converts announcement and feed item list boxes to simpleview. Their box exports have been updated as well.

#33 Updated by Jon Sagotsky almost 4 years ago


Began running update hooks on local copies of prod data. So far so good. Some blocks wouldn't unserialize and lacked plugin_keys, so I had the update hook bail out instead of update them.

The more link wasn't being formatted, so I passed it through the theme function. Views was always giving me the block title, so I only return it if $views->results is populated. I would have preferred to use an option within views, but I couldn't find one.

#34 Updated by Jon Sagotsky almost 4 years ago


More link isn't handled by views because we override the url of the link and views doesn't provide that as an option.

Now the more link only shows if there are more results than can be displayed in the box, as determined by the number of items option.

#35 Updated by Jon Sagotsky almost 4 years ago


For comment 34, had to change > to >=. Didn't realize views was limiting its results to the number specified.

#36 Updated by Jon Sagotsky almost 4 years ago


Gave simpleview box an access function. This prevents disabled features from having their boxes shown in the layout list.

#37 Updated by Jon Sagotsky almost 4 years ago

  • Status changed from In Dev to In QA
  • % Done changed from 50 to 90


Removed titles from old boxes plugins so they can't be added. Left the old plugins intact so we don't get missing .inc file problems again. Renamed simpleview box to be the new list of posts.

Marking for QA.

#38 Updated by Jon Sagotsky almost 4 years ago


Restored titles to the old boxes so they'll display in layout again. Commented out the simpleviews update hook in os.install. We need more time to test this module.

Also available in: Atom PDF