Simple musings of a Drupal developer.

Drush beats CVS, part 2

By krs · August 5, 2009 · 6 Comments · 383 Views

So it seems like a lot of people disagreed with my previous post! :) I should mention that I'm not against CVS and the title may have been provocative, the cvs_deploy module works very well, and CVS and SVN are not mutually exclusive - you can have both in the same repository and they will happily ignore each other.

But it got me to thinking, what am I missing? I use SVN repositories for the sites that I build. I use Drush to install the modules that I need and check for upgrades. The module upgrade process is slower for me since I like to know all the details of what changed first. So I'm open to people letting me know how I could be working smarter, and how using the CVS respository could be making my life easier!

I know the comments system at onSugar is not the greatest, feel free to email me via my Drupal contact form, and I'll post the responses.

Filed in:
Tagged with: , , ,

Drush beats CVS

By krs · July 30, 2009 · 9 Comments · 617 Views

I had checked out a bunch of modules fron CVS, but then I realized that CVS checkouts don't come with all the info such as version numbers, so I wanted to delete them and replace them with real copies. I used Drush and Bash, and here's how I did it.

Need to delete every CVS file from the sites/all/modules directory, and then replace each module with a fresh copy downloaded from drupal.org, and do it without ruining your SVN repository? "What's the difference?" you ask. Well, modules checked out directly from CVS don't get extra packaging info from drupal.org, and don't keep track of their own version numbers properly (you'll see a blank Version column on admin/build/modules).

So by getting a fresh copy from drupal.org, you get a proper .info file, and a LICENSE.txt file added for you. And it's a long module list? No problemo!

Assumptions - you have Drush installed and you're working with a checkout of an SVN repository.

cd to your modules directory, usually
cd examplesite/sites/all/modules


Update your modules to their latest versions - Drush is going to try and download the latest anyway, and you want them to match up.

Tell Drush to grab fresh copies of modules from drupal.org with:
find . -name CVS -depth 2 | sed 's/\// /g' | awk {'print $2'} | xargs drush dl
and watch the "Project xxx downloaded to ..." messages scroll by.

Get rid of all the CVS files with
find . -name CVS -prune -exec svn rm {} \;


Add all the new files (should just be a bunch of LICENSE.txt files) with
svn status | grep '^?' | xargs svn add
Then do a quick svn status - and you should see a bunch of Deletes on CVS files, Adding LICENSE.txt files, and Modifying any .info files

Last, SVN commit the whole bunch! yay!
svn commit -m "removed old CVS tags, redownloaded modules from drupal.org" .

--

edit: thanks to Joel for a better introduction

Filed in:
Tagged with: , , , , ,

Heading to DrupalCampLA!

By krs · July 8, 2009 · 0 Comments · 18 Views

I'm excited to be going to my third LA DrupalCamp! The first one in 2007 was pretty soon after I was hired on at Achieve Internet, and it was my first real experience meeting the Drupal community. I must have had a good time, cause I'm still at it 2 years later :) It was also my first experience drinking with Steve Rude at a conference, which was awesome if you're not sharing a hotel room with him (sorry Bill)! There's still a month to go, so hopefully I can propose a session in time, feel free to send any suggestions.

Drupal Camp Los Angeles 2009 - August 8-9th
Tagged with: ,

finding old versions of firefox

By krs · January 21, 2009 · 0 Comments · 598 Views

It took me a while to find a good source of old versions of Firefox. The need arose while trying to reproduce a bug that the client reported only happened using Mac Firefox 3.0.1 (several versions back).

Most of the places that link to Firefox downloads update to point to the most recent release. A few that did have old version were windows only, and I needed the Mac release! Even Mozilla's website, usually the reliable source only had links to 2.0.0.5

So, back to the old FTP Site.

ftp://ftp.mozilla.org/pub/firefox/releases/

It has everything! All operating systems, all versions back to 0.10 it seems, and all languages! Should make future QA much simpler.

update_sql is not my friend

By krs · January 7, 2009 · 3 Comments · 189 Views

Oh update_sql(), second most unloved of the drupal database functions (db_rewrite_sql() is worse)! If you've never used it, it is basically a wrapper for db_query() that you can use in hook_update_N() hooks in a module .install file. You may never need to write one of these hooks unless you maintain a module; or like me you prefer to make database changes via code when I'm pushing some new features out to dev, stage, and live servers.

The Drupal 6 and 7 versions of the documentation for this function do mention that "%-substitution parameters are not supported." Definitely also true for the Drupal 5 version I'm still working with. So you can't do variable substitution like you do with db_query() and most of the time thats not a big deal.

There is one very important time though.

When using db_query(), you call it with a syntax like db_query($sql, $variable1, $variable2); Now, you know about database prefixes, and always sing curly braces around your table names in FROMs and JOINs, and that lets Drupal work on multisite installs very well, or talk to more than one DB at a time. So the $sql part of that function call always gets passed through a strtr(), or in English, PHP's string translate function that converts every instace of '{' to the right prefix (generally just deletes it). You have no choice about this, and no way to prevent it from getting every single { and }!

So far so good, because you only use curly braces around the table names, and that works out just fine, right?

Now enter update_sql(). This function doesn't support variable substitution, so your function calls look are just update_sql($sql).

Like update_sql("UPDATE {node} SET title = 'something else' WHERE nid = 10"); - that is, everything has to be passed as part of a single SQL statement (the $sql part above). The SQL statement that always gets run through strtr() looking for '{' and '}'. Which, if you are trying to update a serialized array, or a block's visibility code with PHP, or just want to use a { in a node title, it will be deleted. Every time, without exception.

So if you're using update_sql() and any part of the data contains a '{' or '}' that you need to keep intact - rewrite it as a db_query() with variable substitution. The strtr() will operate on the $sql part, and the $values get substituted in later and stay intact.

Filed in:
Tagged with: , , , ,

link fields and tokens

By krs · January 7, 2009 · 0 Comments · 729 Views

Did you know the CCK Link field can accept tokens in the link title? I didn't. Now the link module provides all kinds of ways to format the combination of url + title that get entered, but when asked to have the actual node title link to the given url - I thought for sure I would have to resort to writing some code, either in template.php or in a tpl file.

But the Link module and Token module together made it easy. Set the Title to "static title" - this way the user will never be prompted when creating a node, and remember this is the link title, not the node title. Then set it to the token [title-raw] and you're done! CCK and possibly Views will all work together to get you something like <a href="[user entered url]">[node title]</a>!

Filed in:
Tagged with:

How to hook_views_tables_alter()

By krs · January 7, 2009 · 0 Comments · 195 Views

First of all, this only applies to Views1 & Drupal 5 - there's probably a similar function in views2 however.

The setup: A timestamp ($node->created) was being selected in a View. The only options for formatting it are as Short, Long, Medium, Time Ago, or Custom. With custom you can enter any string that can be interpreted by php's date() function, and have that format apply.

The problem: The site that used a different format as its standard for displaying date and time, let's say "D F j, Y \a\t g:i A". We had created a function in template.php called site_format_date() that accepted a timestamp, and returned the date nicely formatted that way. All for reuseability! Now all the dates in the code (and template files, and theme function overrides) we write can call that function. And when Mrs. Editor decides that she really would like it to be something completely different, we can change it in one place and be done!

The table problem: What a pain to have to go to each View that uses a time or date, and select the "custom" format, and enter into the textbox the format we want to use. Now when someone wants to change the site-wide format, we'll have to go back to each view and update all the format fields! Argh!

So what we're trying to do, is somehow add our own custom format as one of the options for displaying a timestamp, in addition to the basic ones Drupal and Views provides us. Unfortunately, those choices are created by a call to views_handler_field_dates(), which just returns a fixed array of those 5 choices, and there's no way to get your own in there.

hook_views_tables_alter() to the rescue! This hook lets you modify how the Views module understands the tables in the Drupal database. Most of the core tables are added by .inc files in the views module, and many contrib modules have their own views.inc file. Using this hook you have the opportunity to change anything you like about how views works with modules, and do it safely without hacking any modules.

The fields I wanted to affect (the created and changed timestamp) are node fields. You can see them defined in path/to/views/modules/views_node.inc. I'm trying affect how the fields are handled (as opposed to filters, arguments, sorts, or anything else). By checking the .inc file I can see the keys I want to affect are simply called 'created' and 'changed'. Putting that all together, here is my complete hook function :

function hook_views_tables_alter(&$tabledata) {
$tabledata['node']['fields']['created']['handler']['my_custom_format_date'] = t('As My Custom Date');
$tabledata['node']['fields']['changed']['handler']['my_custom_format_date'] = t('As My Custom Date');
}

Now when I can choose "As My Custom Date" to format the timestamps! Views will automatically call my_custom_format_date() for me, and I just pass the data right along to our sitewide date formatter.

function my_custom_format_date($fieldinfo, $fielddata, $value, $data) {
return $value ? site_format_date($value) : theme('views_nodate');
}

If figuring out the syntax of the array to modify was a little confusing (views syntax? confusing? never!) try this little snippet first:

function hook_views_tables_alter(&$tabledata) {
drupal_set_message(print_r($tabledata, TRUE));
}

and you'll get a very long printout of how every table interacts with the Views module. With some searching and little luck, you should be able to find the section you want to modify. Lots of great views1 and views2 documentation is available, but it gets a little hairy! Unfortunately there's not a lot of documentation that I could find on this very powerful hook! I discovered it while poking through the views.module code and found 1 Drupal issue at http://drupal.org/node/142383. (This was the issue that actually enabled the hook to work properly as of about July 2007).

 

Remind me to add some pictures to this post!

Imagecache and You (err, your picture)

By krs · January 6, 2009 · 0 Comments · 165 Views

When you using imagecache on the $user->picture, many people have noticed 1 small problem. If someone uploads a new picture, everything appears to work fine, but the user photo stays the same!

What's going on? When a user uploads a picture, it gets renamed to a specific filename - doesn't matter the name of the file you uploaded. Imagecache then makes a copy of that file to display. (Technically this doesn't happen until the first time the image is viewed with a particular preset). When the new user image is uploaded, it gets the very same name as the previous one, again regardless of the actual filename that was uploaded. Now imagecache will think it already has a cached version of that image, because it just checks the filename and sees that it exists!

So I was all about to post on how to fix that, basically by linking to Nate Haug's excellent post on how to do just that - but the Imagecache module maintainers have just made a new release (for Drupal 5) that includes a fix for the issue! So the new solution is - download the latest version of the Imagecache module!

Filed in:
Tagged with: , , ,

Ampersands and CCK

By krs · January 6, 2009 · 0 Comments · 220 Views

When using a CCK text field that is set to display as a select list, using the "Allowed Values" textarea to specify each of the choices works 99% of the time. But when trying to use an option that included an ampersand, like "Drupal & Drupal", it keeps getting escaped to &amp; -  stop it CCK!

What's going on? Each line of the textarea is eventually passed through filter_xss(), which tries it's best to remove naughty characters like &amp;, becauseof its special meaning in HTML.

How to avoid it? Use the section "PHP Code" and write your values out as an array. You must specify a key and value pair for each option, CCK will not automatically handle just having the value. Don't forget to return the array. PHP open and closing tags arent needed. CCK trusts the values found in this block, and pass them through any kind of text filtering, and your ampsersands will sail through undamaged.

So

Drupal & Drupal
Hans & Franz
Martin & Lewis

become

return array(
'Drupal & Drupal' => 'Drupal & Drupal',
'Hans & Franz' => 'Hans & Franz',
'Martin & Lewis' => 'Martin & Lewis',
);

Filed in:
Tagged with: , ,

On Rewrites and Redirects

By krs · December 17, 2008 · 1 Comment · 417 Views

Webserver configuration is not a task I have to do very often. A client was replacing an old site with a new one at the same URL, but they needed many of the old links to still work correctly, for SEO, bookmarks, and general usability purposes. To further complicate matters, there were actually 2 wordpress blogs hosted at the same domain, and the webserver needed to redirect some of their links, while leaving the wordpress blog itself untouched!

So with great trepidation, I requested the list of URLs to be handled from the client. What arrived was a seemingly random assortment of domains and URLs. All together, I used a number of different techniques to match them all. The next time this comes up, I'll probably have fogotten all the syntax, so I'll preserve everything I learned here. I found other examples to be extremely useful, so my hope is that others will benefit from these as well.

All of these configuration directives were in apache's httpd-vhosts.conf, but could also be used in a .htaccess file, or possibly httpd.conf. Probably other places too, knowing apache. It helps to know that Drupal's home directory was /home/web/sites/production/www, and that's what the virtual host was using as DocumentRoot.

First of all, how was a wordpress blog being hosted on the same domain as the Drupal site - but no files were in Drupal's home folder?

The Alias Directive

Alias /blogs/someblog/ /home/web/sites/production/other/blogs/someblog/

This lets apache know that any URL's coming in like /blogs/exampleblog/ are really hosted in a totally different document root.

The Redirect Directive

Redirect permanent /blogs/someblog/author/someauthor/index.php http://www.example.com/user/someauthor/profile-page

This lets apache know you like to send that specific URL to a new place. Aliases and Redirects are evaluated in the order they appear. Since this one is more specific than the alias above, it actually has to go first. This was we can redirect some links from the wordpress blog to our new Drupal site, without harming the rest of it.

The ServerName Directive

ServerName example.com

This is the domain name you want this virtual host to use.

The ServerAlias Directive

ServerAlias www.another.com subdomain.example.com www.example2.com

These are other aliases for the server name that the vhost should use. Note that these don't get converted to the ServerName, apache just treats them as equally valid. This can cause problems with Drupal's settings.php file - which is usually loaded for specific server names. You can make use of a sites/default/settings.php, but that is generally a practice I don't recommend. If you can, using RewriteRules may be a better option.

The RewriteCond and RewriteRule Directives

RewriteEngine On

Have to set this for the Rewrite statements to be evaluated at all.

RewriteCond %{HTTP_HOST} ^oldsite\.com$ [NC]
RewriteRule ^(.*)$ http://www.newsite.com/blogs/fashion [L,R=301]

This sends all traffic from the old site (which just hosted a blog) to one particular URL on the new site (which hosts a similar blog). [NC] means its not case sensitive. [L] stands for Last, and tells apache to stop evaluating and go there, and [R=301] sends the browser an http status code 301, which should help search engines find your new content. So oldsite.com/articles/my-article becomes www.newsite.com/blogs/fashion.

RewriteCond %{HTTP_HOST} ^(www\.)?oldersite\.(com|net|info)$ [NC]
RewriteRule ^(.*)$ http://www.newsite.com$1 [L,R=301]

This sends traffic from the old domains to the new site as wel, but it keeps the rest of the URL intact. The difference comes form the addition of the $1 at the end of the new domain. So www.oldersite.com/articles/my-article becomes www.newsite.com/articles/my-article.

About Me

Drupal.org username: kscheirer

subscribe

Drupal Cred

Drupal Camp Los Angeles 2009 - August 8-9th

Archive

August 2009
SMTWTFS
 1
2345678
9101112131415
16171819202122
23242526272829
3031 
July 2009
SMTWTFS
 1234
567891011
12131415161718
19202122232425
262728293031