Monday, August 23, 2010

embedded media video provider notes

Nice bootstrap guide in emfield/contrib/emvideo/...easy to get started. CCK needs one of these.

validation hook isn't implemented in the example, but is called from emfield module.

Posted via email from dsayswhat's posterous

Friday, August 20, 2010

views hooks to fix calendar display

Ran into a difficult bit of work today -

Views in Drupal based on the Calendar and Date modules are nifty, except when it comes to how you display recurring items.

On views fields, the 'group multiple values' settings don't allow you to set your 'show 1 value starting from' to correspond to the arguments which have been passed to your view.

That means you get the next item, even if it's outside the bounds of the argument driving your month, week or day view.

That's ugly, cause you'll get Sept 4th sandwiched between Aug 12 and Aug 15, since the event already happened, so it jumps forward to the next recurrence, but shows it in the original place on the month view. Ick.

Turns out I had to use hook_views_pre_render() to sift the $view->results array for nodes that were within the bounds of my arguments...here's the code:

function xxx_views_pre_render(&$view) {
// we want to exclude search results from this treatment - but the other calendar displays ( week, day, month ) seem to benefit
if ($view->name == 'eventcalendar' && $view->display_handler->display->id != 'page_2' ) {
// set our date arguments to unix timestamps for comparison with row data.
$startwindow = strtotime($view->date_info->min_date_date);
$endwindow = strtotime( $view->date_info->max_date_date );

foreach ($view->result as $key=>$row) {
$eventdate = strtotime($row->{yourDateFieldHere});
if ( $eventdate >= $startwindow && $eventdate <= $endwindow ) {
// our event is within the window set by the arguments to our view.
$newresult[] = $row;
}
}
$view->result = $newresult;
}
}

Another interesting point to note is that it seems ( at least on this view, need to verify elsewhere ) that $view->current_display is always set to 'calendar_period_2'. That's the month view...but it's set to that even if you're on week or day. That may be a function of the default display for the calendar? need to look into that further.

That meant I couldn't reference $view->current_display to include/exclude certain displays from my hook. I had to go deeper into the $view->display_handler object to get what I was looking for: found it at $view->display_handler->display->id.

Posted via email from dsayswhat's posterous

Wednesday, August 18, 2010

custom cck field development

Reference material: cck hook docs found here: http://drupal.org/node/342987,
Karen Stevenson (http://www.lullabot.com/articles/creating-custom-cck-fields)
Jennifer Hodgdon (http://poplarware.com/articles/cck_field_module)
link and cck/optionwidgets modules

GOTCHAS:


Gotcha #1
// implementation of hook_field_info

function classnote_degree_field_info() {
return array(
'degree' => array(
'label' => t('Degree'),
'description' => t('Stores a degree with the year it was earned.'),
)
);
}

// implementation of hook_widget_info

function classnote_degree_widget_info() {

return array(
'degree' => array(
'label' => 'Degree/Year selector',
'field types' => array('degree'),
'multiple values' => CONTENT_HANDLE_CORE,
'callbacks' => array(
'default value' => CONTENT_CALLBACK_DEFAULT,
)
)
);
}

if field_type in hook_widget_info doesn't match an array key from hook_field_info, your field won't show up in the cck | manage fields UI.


GOTCHA #2:

function classnote_degree_field_settings($op, $field) {
switch ($op) {
case 'form':
$form['initial_year'] = array(
'#type' => 'textfield',
'#title' => t('What year did you begin awarding degrees?'),
'#size' => 10,
'#default_value' => $field['initial_year'] ? $field['initial_year'] : date('Y')-50,
'#required' => TRUE
);

...

#default_value needs a ternary operator or variable that's set before the form definition, or else you'll lose your previous settings when the edit form loads.

---

My preferred order of operations is to get the ui piece of it working first...

Bits related to the node edit form

hook_field_info() is needed to get the datatype available to the manage fields interface.

hook_field_settings() to define database tables
note: if this isn't defined, nowhere to save the data.

hook_widget to define the form elements in node_edit form
Note:

Then think about making the options configurable...

hook_field_settings()::op=database columns handles database storage

hook_field()::op=validate does the form validation.


CCK does no checking to see if the various parts are consistently implemented - doesn't look at db fields and see if they match fields in code, for example. That means you can make a false start, don't clean it up cause you don't understand the database tables are orphaned, and then change your code and you can't figure out why it doesn't save...no fields to save to.

CCK makes new tables PER FIELD INSTANCE - add a field, make a table. So if you make changes to your cck field module, delete your cck fields and start over in your content type.

Posted via email from dsayswhat's posterous

Thursday, July 15, 2010

Lullabot Module Development Deep Dive

Notes from Thursday AM - Angie Byron, Jeff Eaton, Randy Fay

Be sure to read http://drupal.org/writing-secure-code - Read it. Love it.

Alter hooks - how to totally trick out your Drupal site.

hook_X-alter() - what we do when Drupal does it wrong...

  1. build stuff
  2. Alter stuff...
( mental note: don't name themes the same as modules - they'll clobber each other and the world will explode. )

Fun tip: PHP5 passes objects by reference, but scalars and arrays get passed by copy.  Don't alter objects passed as arguments unless you mean to.

Some hooks:

  • hook_form_alter()
  • hook_menu_alter
  • hook_link_alter
  • hook_mail_alter
  • hook_schema_alter
  • hook_theme_registry_alter
  • lots more
Common pattern for module developers - firing your own hooks to let other folks interact with your module:

function myapi_do_something() {
// let modules hook myapi_stuff() to add to the list of stuff.
  $stuff = module_invoke_all('myapi_stuff');
// let modules alter the stuff
  drupal_alter('myapi_stuff', $stuff);
// process the stuff
  $results = myapi_process_stuff($stuff);
// let modules react by doing a post-event hook
  module_invoke_all('myapi_stuffed', $stuff, $results);
  return $results
}
This appears to also be a help toward maintainability - expose your stuff in small bits and write a family of modules to work together?  Maybe?

Important tips:

  • make a module for reuse if you do stuff the same way on multiple sites.
  • NEVER name a module and theme the same thing...ka-BOOM
  • be kind to other developers, use unique function names, namespaces, etc.
I will now misquote @webchick, talking about debugging module_invoke_all() - It's not really hacking core if you do it quick... ( speaking of dsm'ing in core to see what modules are altering your hook... )

Posted via email from dsayswhat's posterous

Saturday, March 20, 2010

1st try with the Admin theme

I checked out the admin module ( http://drupal.org/project/admin ) last night on a side project I've got - I think I like it.

It reorganizes your admin menu structure into groups which are more sensible, and looks really nice if you're using the rubik theme ( http://code.developmentseed.org/rubik ). Rubik is a subtheme of Tao ( http://code.developmentseed.org/tao ).

Both the admin module and it's accompanying themes were created by Development Seed, may they live forever.

So here's the process I followed to get them set up:

  1. install the module
  2. install the two themes
  3. enable all the module and the themes
  4. Try to set the admin theme to Rubik by visiting /admin/settings/admin on my site.
  5. Discover that with the admin module turned on, it appears that /admin/settings/admin doesn't work at all.
  6. disable admin module
  7. visit /admin/settings/admin to set rubik as the admin theme
  8. re-enable admin module
  9. admire pretty new admin screens and nicer information architecture.
  10. feel sad that my themes are so incomplete and not pretty
  11. start thinking dangerously about starting a new theme for UNT based on Tao.
Admin module appears to be the next best thing to Drupal 7's usability improvements for Drupal 6. Try it out. Watch out for the /admin/settings/admin bug, in case it bites you.

Friday, March 19, 2010

Building a feature

I'm building a person directory that ought to be reusable across various projects. My goal through this process is to document the building of a feature, including the content type, views, context, etc.

So far, my team and I have created a CCK content type that contains the following fields:

  • First name
  • Last name
  • Job title
  • Head shot
  • Email
  • Office Hours
  • Phone
  • Location
  • Website(s)
  • Bio/description
Once that's created, we need a listing of people. Be sure to name the view something descriptive ( in my case, peopledirectory ) and put a note on it to describe what it is.

Once you're in the view editing screen, ( /admin/build/views/edit/{viewname} ), you have to do a few things to get started. These steps are pretty much true for any view you create...
  1. Set a couple of filters, especially the 'public or admin' filter, plus one for the specific content type that you are creating a list for.

    There may be other filters depending on what your view is meant to accomplish...in my case, filtering for published/admin and for content type were sufficient.

  2. In the Basic settings box, choose whether you want your view's row style to be a set of fields, or full node. Node-based views will run through the Drupal theme layer and respect any theming you've done for that content type. In my case, I want to theme them specifically, so I choose 'node'.

  3. Also under Basic settings, you can select how many items should be on the list, whether to use pagination controls, header and footer text, etc.

  4. Next, I made a new display for my view - a page display that can be visited at a specific URL on my site. Once added, choose a path for your page view under Page options and set any specific sorting or additional filter criteria that you might want this page to have.

    Display-specific sorting, filters, or other settings can be set as overrides to the default view, or they can update the entire view. Think about how specific you need to be, and if there will be multiple displays of this view with different filters, sorting, etc. that need specific overrides.
With a view set up to list your records and sort them properly, you can move on to theming your view to your liking.

*Update*

After posting this yesterday, I did a few other things:
  • I used the ImageCache module to resize images as they're uploaded to generate thumbnails or other form factors as appropriate for the theme

  • I themed the view by using a node-view-viewname.tpl.php file, where viewname is the name of my view. my view was called node-view-PeopleDirectory.tpl.php.

    Important tip: This works whether or not you're in 'node' or 'fields' display type. It appears that the node-whatever supersedes the views tpl files to some extent. More research needed on this...

  • I themed the content type a little bit using node-person.tpl.php

  • Last, I used the features module to package the content type, view, and ImageCache presets into a tarball that can be reused across sites. I imported it into another development site I was working on, and the content type came in fine, but the view did not. Guess I'll have to try again Monday to see what I did wrong.

Monday, March 8, 2010

wireframing

Most of my day is spent taking a bunch of ideas and turning them into a finished product. Many times, this involves making prototypes of the desired outcome so that my team and I can communicate with one another about what we're trying to achieve.

As my team and I grow together, one of the things I've identified is that I'm not always able to communicate what's in my head, how I go about my work, etc.

That's natural, I suppose, since I've been growing into my own skill for over a decade. I can't remember how I acquired this or that skill most of the time, and I've thrown my team for a loop several times by telling them to 'go make a wireframe'.

One of the resources that taught me to wireframe or prototype what should be on a page is this article by 37signals' Lead UI designer, Ryan Singer ( twitter ). Well worth reading.

In the article, Ryan walks through the design of a 'My account' page. Even though he's handling little bits of information, the same process applies to a landing page assembling various kinds of content for various audiences to navigate.

He uses several steps to achieve his finished product:

  1. List your bits
    You have to know what content you're handling.

  2. Figure out what bits relate to one another
    How does your content group itself Some things are related, some aren't.

  3. Prioritize
    What's most important? What's the next thing after that?

  4. Design each chunk
    Design could mean scribble a quick solution. or it could mean sit down with a graphic designer. You decide.

  5. Put the chunks together
    With all the important things decided, you can now arrange your page based on priorities and relationships.

  6. Make it real
    This will usually involve a code monkey, unless you are one.
So the main thing here is knowing what content you want to showcase - in my case that means knowing:
  • what content you have
  • what content you wish you had
  • what other resources are available
Sometimes you need institutional history to get the full picture, but basically, if you know waht content you're handling, you can
  • group it
  • prioritize it
  • then put the most important thing front and center.