Wednesday, January 30, 2013

Writing a custom Drupal 6 Views 2 filter - resources

This is not intended to be a full tutorial but resources and tips that I found helpful.

Drupal 6
Views 2

Helpful Tutorials:
http://www.hashbangcode.com/blog/creating-custom-views-filters-exposed-form-element-drupal-6-561.html

In summary the major steps are:

1. Within a custom module, define hook_views_api() to alert Drupal that the module is views enabled, api version 2, optional path index pointing to a directory that has additional files for the view.

2.  Use hook_views_handlers() to again point to the directory of files to include for the view, as well as the name of a custom handler to be used and the parent handler it will extend.  The custom name handler should be the same as the name of the .inc file which will contain a class, which again will have the same name.

3. Use hook_views_data() to define the name and group the filter will appear under in the Views UI. Again the name of the custom handler is included.

4. In the .inc file named after the handler, create a class (custom handler name) that extends the parent handler class.  This class will contain about two methods. The first value_form() will build and return the form to be used within the views UI. The second, query(), uses drupal methods to insert additional 'WHERE' or 'AND' clauses to the SQL query statement being built by the view.  (add_where())

One major roadblock I hit was attempting to reference a table other than the main one being used by the view. SQL was giving me errors about an 'unknown column'. The method add_table() allowed me to register other tables to be used within the query.

Drupal permissions and the node_access table - a hard learned lesson

While building a custom filter for Views 2 on a Drupal 6 site I leaned an important lesson about the way Drupal handles permissions.

I was trying to write a filter that would display a selected list of nodes to users with a certain role.  Sounds easy right?  It would be fairly logical to assume that Drupal would support filtering access to nodes based on role. If you want to restrict access to an entire content type by role, this is easy. The 'views' explanation would be something like: "Show me nodes of this type, only to users who have this role".

My situation was different because the content type is accessible to all authenticated users, I only want to show a small subset of those nodes to users with a specific role.  That subset of nodes has no distinguishing property to filter, leading me to believe that I would have to write my own.

Here is where the trouble starts.

I wanted the filter to do a join between the 'node' table and the 'node_access' table to see if a particular node id was listed in the node_access table with the role id ( 'gid' in the table ) of the role to which I wanted to display the nodes. I was surprised when my queries were coming back empty.

I noticed that nodes of this content type would be returned with my custom filter when I used a role id that had access to nodes not available to 'authenticated users'.  To test this discovery I removed node access for authenticated users to the nodes I wanted available to the new role, and suddenly they were being listed in 'node_access' with the new role's id.

In summary:  If a node is accessible by the role 'authenticated user', the node_access table will only contain records associated with that role id.  Other roles given the same access will not have a record in the node_access table. This is most likely intended to reduce redundancy in the table because any user with any custom role will already be authenticated.

This is probably why this filter is not included in Views by default.

Unfortunately this means my query is impossible ( at least the way I attempted it ), and there goes several hours of facemashing my keyboard.

Thursday, January 24, 2013

Javascript query parameter setup

Using a query parameter can often be more convenient than having to change a hardcoded value while testing a script. This allows you to pass a variable into the script without having to edit and re-save your script.

var query = window.location.search.substring(1);
var keyVal = query.split("=");
var value = keyVal[1];
if (!value) { value = 100; } // in case no query parameter is passed in, use a default

Wednesday, January 9, 2013

Assigning CSS float values in javascript

I have to give credit for this information to an anonymous poster on stack overflow:  http://stackoverflow.com/questions/606470/is-there-a-cross-browser-way-of-setting-style-float-in-javascript

While creating and adding styles to some DOM elements with javascript, I noticed that my IDE was unhappy with me using this syntax:

domElement.style.float = "right";

The trouble is that 'float' is a reserved keyword in javascript, and the above syntax will cause unexpected results which vary across browsers.  I learned that I should be using: domElement.style.styleFloat = "right"; but this was still not working Firefox.

The cross browser solution ( Chrome, IE, Firefox ) :
domElement.style.styleFloat = "right";
domElement.style.cssFloat = "right";

Now everyone is happy.