drupal

I develop on my MacBook Pro and when building Drupal 6 sites, I had to run PHP 5.2 because there were many conflicts in Drupal 6 core and contributed modules which meant running on PHP 5.3 either threw up errors or didn't run properly. Since I run XAMPP for Mac OS X, I also run phpswitch which lets me switch from XAMPP using PHP 5.2 to PHP 5.3 and back.

Unfortunately, Drupal 8 not only requires PHP 5.3 but PHP 5.3.5 or higher. Drupal 7 ran fine on PHP 5.2.5 or higher with PHP 5.3 recommended.

1) XAMPP Mac OS X 1.7.3 comes with: Apache 2.2.14, MySQL 5.1.44, PHP 5.3.1.

Read the rest of this article...

Say you have a bunch of blocks and you want them to be displayed on certain nodes of varying content type based on some criteria like the content type and some CCK fields or taxonomy. You can't do this with the stock block visibility settings without writing custom PHP code.

But we can implement it using some existing basic Drupal building blocks: CCK and Views

1. Create a content type called Visibility Block.

You might have a field for content type where the possible values are returned from code which returns an array of the content types (using function node_get_types()).

2. Then for any fields you want to match, you'll have the same fields in this content type. For example, if one of your content types has a textfield and the possible values are 1, 2, 3, then do the same for Visibility Block.

When you create a Visibility Block, you'll have your block content in the body as normal (optionally you could use Block Reference and create blocks like usual and then link to them in the node instead, but I see no point in the extra effort and redirection), then select the conditions for the pseudo-block being visible.

3. Now create a view called Visibility Blocks Viewed. You'll create block displays, one for each content type that you have a Visibility Block set for which may only be one or two of your c-types.

Create an overridden argument each block display for the content type -field- in Visibility Block. You want to match the content type of the viewed node with the field in the Visibility Block, which are not the same type of thing. So you'll need to convert the argument in code.

You'll call menu_get_object() to get the $node because it's better than "$node = node_load(arg(1));". For the chosen c-type for that block display you will check that the implied node's c-type is what ever type you want to show in this block display because you will also check any fields that are specific to this c-type. Use PHP to supply a value since no argument will be passed in, and have the code load the current node and return the type. Then use PHP for the Validator Options and if the c-type doesn't match then you will display empty text. If you have multiple c-types which share CCK fields then you can put them into a single block display.

4. For each content type, in the chosen block display you will create a new argument for each compared against CCK field. You will pick a field from V-block and then use PHP to return a default value of the currently viewed node's field's value. You won't need to do Validation on these arguments.

5. Finally, you may want to limit the number of nodes returned, maybe just one. Now give this block a title and save it and configure its region in the normal block admin.

--

Why not the normal block visibility settings?

Because there you can't even configure by content type (anymore in D6). You can configure by path glob and by PHP code which overrides the path glob field (including in the database).

So under "Page specific visibility settings", set to "Show if the following PHP code returns TRUE (PHP-mode, experts only).", the field is blocks.pages. Essentially, PHP code works by overriding the pages list.

Why not use Block Page Visibility?

Block Page Visibility (http://drupal.org/project/bpv) enables site developers to centralize the display of blocks to a single PHP function. It is an alternative to controlling display via each block's configure form. The more "sometimes on, sometimes off blocks" that a site uses, the more useful this module becomes.

This takes over the visibility settings of all your blocks by calling:

$sql = 'UPDATE blocks SET visibility = 2, pages = CONCAT("<", "?", "php ", "return bpv_is_visible(\'", module, "-", delta, "\'); ", "?", ">") WHERE status=1 AND theme=\'%s\'';

Sometimes it's easier to configure a block by just whether you're logged in, or whether you're on the front page.

This module doesn't give you any finer grained controls. And you have to configure every block in code. You also lose all your current block visibility settings once you install this module. To use this module you have to implement your own bpv_config or bpv_configuration (I think it's a bug that it's looking for bpv_configuration but actually uses bpv_config).

Taxonomy is normally pretty simple by default except that it's also called vocabulary (but never terminology although the tags are called terms) and that it can be attached to nodes as fields (using Content Taxonomy Fields to make CCK fields which gives you a bit more control) or not, or both.

Adding language makes it complicated though. Drupal can be said to support languages other than English, multiple-language sites, internationalization and translation. But it's not always user friendly or clear even to developers. Such is the case with taxonomies.

Let's say you have a site that's in two languages, English and Vietnamese. You have translated the interface of the site as well as nodes so that URLs are consistent. To switch language you just add the language code to the front of the URL. So you have a taxonomy with terms in your site's primary or default language. But you want to use the same terms by ID rather than a different set of terms.

1) Edit the vocabulary. Set "Localize". This doesn't set a language to any terms or anything, they are just assumed to be in the default language already.

[Look in term_data and confirm the language column is still empty.]

2) Refresh strings in Translate Interface. Now if you search taxonomy for a term it should appear.

[Look in locales_source for location = "term:$termid:name" where $termid is the tid of a term in your vocabulary. This means it's ready to be translated. After translating, it should be in localtes_target with the same lid. But the translation column is a blob so you won't be able to see the translation directly depending on your mysql client.]

3) I recommend installing the Translation Table module instead of searching for each new term in the regular translate interface. Translation table shows up as a new tab in the translate interface and you can select a vocabulary to see all of its terms in one place.

4) If you use terms in arguments in URLs you'll need something further. Otherwise, all URLs will use the term in the site's default language.

5) One last thing: Don't use t() to translate a term. Use i18ntaxonomy_translate_term_name on a term object (like if you get a vocabulary object from taxonomy_get_tree).

Before I begin: I'm a Drupal guy. What I say could be construed as being biased. I'll try to be honest though.

When building a website you or your developers have some decisions to make: what language to use, whether to use a framework and which one (depending on language - Zend/CodeIgniter/Symfony/CakePHP for PHP, Ruby on Rails, Django for Python, etc.), whether to use a CMS (WordPress, Joomla, Drupal), whether to self-host or use a blogging service (WordPress.com, Drupal Gardens, Tumblr, Blogger). There is no single right answer.

First, go with the language that is most comfortable. Previously, I had several years experience with both PHP and Python with Python actually being more recent. But few people in Vietnam know Python where many know PHP. But Drupal being in PHP sealed the deal.

Next, is it mostly about managing news-like content? Then go with a blog. Does it need some popular features like user logins and full accounts, social media integration, voting, storing meta-information besides blog text, or otherwise some customization of what kind of content you are storing? Then it's no longer a blog and you should use Drupal. Is it purely ecommerce? Drupal Commerce or Ubercart can do the job, but Magento might be all you need if you are not a developer and as long as you can afford to buy the yearly license fee for it and your website only needs a store of physical items without any other content or custom design.

Do you need something that is more like a web app that's unlike any existing blog, news site, social media site, online store, or corporate website out there? Then maybe you should have a team of developers starting with a web framework (Drupal, as well as being a content management system, is also a content management framework) and start from more basic building blocks.

Some specific use cases:

1) An intranet website for managing some internal corporate data that is really custom to your company. WordPress would not be adequate none of its strong points would apply. Drupal's theming weak points would no longer hurt you here since you just need a professional-looking tool. Best of all Drupal easily gives you and novice users a way to manage your data.

2) Brochure website - like a business card for a store or business with a dozen or so pages of information and some links and a contact form. If you don't already know Drupal then use WordPress. WordPress also has many available commercial themes which can be used. However, a Drupal expert can just as quickly and easily build brochure sites in Drupal.

3) Social network - There are open source packages that are like social-network-in-a-box solutions. But nowadays, social networking is a feature, not a sufficient product alone. In my experience, using these off the shelf packages ends up being too limiting because you will always want to do new things and come up against the limits of the software, even if its open source. This applies to social news software like Pligg, school software like OpenSIS, Open Source Q&A software, forums like vBulletin, etc. Those kinds of sites were once novel and rare but are now just features to be added to larger sites, but they can not reasonable be used to build those larger sites.

WordPress's strong points:

1) Being a blog. It does one thing really well. I have run many WordPress blogs in the past. This blog is built with Drupal though because it's possible to blog with Drupal, and because I've also extended it far beyond blogging with many experiments.

2) Availability of commercial themes. There are a lot of companies making and selling themes for WordPress (this is also a point where Joomla wins over Drupal). There are also plenty of free themes. This is good for people who don't want to put money down on a fully custom design yet and are just happy to use something that looks professional.

3) Usability. Out of the box, WordPress is user friendly and makes it easy to get up and running. Drupal improves at this with every major version but is still something a developer more easily loves than an end user.

Honorable mentions

Mezzanine (http://mezzanine.jupo.org/) is a promising-looking CMS built with Django/Python. If you like Python (like I do) then consider giving it a shot, although it doesn't have nearly the depth and breadth of free modules that Drupal offers nor the size of community.

Cartridge (http://cartridge.jupo.org) is Mezzanine's ecommerce/shopping cart solution. Again, you won't get the community and support like you would with Ubercart but at least you would get to hack in Python!

Build your own FAQ in Drupal

Submitted by tomo on October 13, 2012 - 12:15pm

Websites, including Drupal sites, often need Frequently Asked Questions and answers to them. Drupal, as a content management system, should manage your question and answer content intelligently. With all the great modules contributed to Drupal's community you might think there are some good FAQ modules. In my experience, the Drupal FAQ module is too rigid, and therefore unusable for most of my sites. But we can build a FAQ system using basic Drupal building blocks.

What we need: taxonomy, blocks, views, a few lines of PHP (that can be stored in the database - no custom module required)

1. Content type: Create a new content type. CCK is optional here, as you can just use Title as Question and Body as Answer.

2. Vocabulary: Create a new vocabulary called FAQ. Add a few terms if only for testing.

3. Devel Generate: Optional - requires Devel module's devel_generate to generate some test nodes with test questions, answers, and topics. devel_generate can be run from the command line too if you have drush installed - just run "drush genc". Anyways, generate a few dozen nodes, as many nodes as questions you have. It'll be easier to mass edit the questions once the nodes have already been generated.

4. Views: You'll need two views although they can also be two displays of a single view, so let's do that.

a. Create a view, filtered by your FAQ content type (and published or published/admin).

You will add three node fields:
Node: Nid (Nid) [make this field hidden, but its value is used in the rewritten Question field below]
Node: Title (Question)
Node: Body (Answer)

For the Question, rewrite the output to:

<a name="q-[nid]"></a>
[title]

You'll have on argument, which is the Term (FAQ vocabulary topic) in the URL.

- Configure Argument Taxonomy: Term
-- Provide default argument
--- Default argument type: Taxonomy Term ID from URL
-- Validator: (Choose your FAQ vocabulary)
-- Argument type: Term name or synonym
-- (Optional) Transform spaces to dashes in URL

Now turn this default view into a page that's not overridden in any way. Set the URL to be something that's NOT your vocabulary name because your URL will conflict with the default taxonomy paths ("taxonomy/term/%" - which Taxonomy sets up path aliases for from each vocabulary with each term - but that page may also be being overridden by a view included by Views by default). So if you want your URLs to be like "/faq/return-policy" then name your Vocabulary like "FAQ Terms" instead of "FAQ".

At this point you should save your new view and be able to go to "/faq/troubleshooting" or whatever. It will give you a list of questions with answers. But usually a FAQ section will also list out all questions at the top with links to answers below. How can we accomplish that?

b. Let's create a new Display that's a Block. Now override the fields and remove the Answer field. Override the display of the Question to:

<a href="#q-[nid]">[title]</a>

Optionally, set a blank title for this field. Then we will have a block that is just a list of questions. But the argument won't work anymore since it's a block. So you need to override the argument "Taxonomy: Term".

- Default argument type:
-- PHP Code
--- return arg(1);

- Validator: Basic validation + Transform dashes in URL to spaces in term name arguments

This will find the term "charity" in the path "/faq/charity" and pass it on.

5. Now that the block is created, you need to make it display. We want to display it on the top of our first view!

This is assuming you have a region in your theme for blocks at the top of content in pages. You could choose another location but it should really appear as the first content you see. But you want this block to appear ONLY on this page! So in block admin, configure the block you just created, and under:

Page specific visibility settings
- Show block on specific pages:
-- [check] Show on only the listed pages.
Pages:
- Type in "faq/*"

Save the block. Now your question list with links to answers further down the page should be appearing at the top of your FAQ pages!

7. Next, you need a list of your categories. Sadly, there's no easy way for Drupal to do this. Views has a view type for taxonomies which is unfortunately not very powerful and so we can't use it to get links to "/faq/[term]" as it doesn't allow us to rewrite our own links. It allows you to link to term pages but those pages are rendered by either the Taxonomy module or that default view I mentioned earlier. Trying to override those paths with our own view is a mess, probably due to weighting.

Anyways, we can easily create a list of topics with links with a tiny bit of PHP. Create a new block using the Block admin page. In the block body:

<?php
$tree = taxonomy_get_tree($vocabulary_id=YOUR_FAQ_VOCABULARY_ID_HERE);
$html = '<ul>';
if ($tree) {
    foreach ($tree as $term) 
        $html .= '<li>' . l($term->name, 'faq/' . str_replace(' ', '-', mb_strtolower($term->name))) . '</li>';
}
$html .= '</ul>';
return $html;
?>

Again, set this block to only appear on "faq/*" pages. Then configure its location into a sidebar or somewhere and you will be displaying links to each of your FAQ topics and you're done!

Mass editing nodes in Drupal can be a chore. If you just want to edit some attribute and set it to a single value for many different nodes then Views Bulk Operations can help. But you may instead want to make some quick changes to the titles, bodies, and CCK fields of a bunch of nodes of a certain type. The default way would be to open each node in a browser tab, go to their edit forms, and then operate on each one individually. Can we come up with a better way?

Multi Node Edit is a module that sounds like it could help. It promises to give you a page with many node edit forms. Unfortunately, this is not the case. By itself, this module is not usable to users. If you write some code to use it like a library you might be able to create a page with many node edit forms on it.

Recommendation: This module isn't useful to most people. It might be useful if you're writing code for a custom page.

Editview (editview) is the easiest to use, you just build Views and select 'Style' of 'Editview' in one of your displays. It works on the whole display, so all fields become editable. Unfortunately, you can't control this. Some fields shouldn't be editable, and so sometimes they just don't appear at all. Other times you may want to view a field but not edit it. Unfortunately, this isn't possible, even when using Global fields. [This issue is tracked here: http://drupal.org/node/635076]

* In my case, I just wanted to get a link to edit the node. I accomplished this by adding a Node: Path field which shows the path/alias editing form.

Recommendation: Use Editview if you're comfortable with building Views. Then you can construct a view of the fields you want to edit, and make it easy to filter the nodes you want to edit.

Editable Fields (editablefields) - 6.2 doesn't integrate with Views, despite the README. 6.3 does integrate but not the way explained in the README.txt. There is no added View type to choose when creating views. The exported content types used for demonstration don't import either. Most fields aren't editable, but if they are there will be a new checkbox for editable with some options. However, the 6.3 version of the module is still quite buggy so it doesn't work at all.

Recommendation: Avoid Editablefields module for now unless you want to just edit fields in the node display.

Drupal Links in Content

Submitted by tomo on October 11, 2012 - 3:01am

Problem: In your blog posts you have a lot of links to other pages on your site, then one day you decide to change the URL pattern for all nodes on your site, or you change the pattern and slowly update paths to nodes by editing and saving them. Unfortunately, you had hard-coded paths in your content bodies and now they are all leading to 404 pages. What to do?

1) Link checker (linkchecker) module will find the broken links. This is something you may need to use.

2) Path Finder is a module that turns your node links into permalinks with node id (slug) at the front of the URL so that any future change to title which results in a different URL still leads to the same node via the node id. Example: http://www.example.com/837/latest-news/my-descriptive-seo-friendly-url

Of course, this doesn't help you once you already have a bunch of nodes and content linking to them, but it's one strategy to start with. Then if you do change the titles or patterns of your nodes, as long as the node id / slug is still at the beginning of the url, then you won't get any 404 errors, although you'll then have multiple URLs pointing to the same content. So this isn't ideal.

3) Turn on Pathologic: "Pathologic is an input filter which can correct paths in links and images in your Drupal content in situations which would otherwise cause them to “break;” for example, if the URL of the site changes, or the content was moved to a different server. Pathologic is designed to be a simple, set-it-and-forget-it utility. You don't need to enter any special “tags,” path prefixes, or other non-content noise into your content to trigger Pathologic to work; it finds paths it can manage in your content automatically."

4) If you just need to remove a base path (like http://www.domain.com:8080) from all URLs, then URL Replace Filter (url_replace_filter) will suffice.

5) If you need to do more complicated search and replace on URLs, and want to use regular expressions, then use Search and Replace Scanner (scanner).

Finally, use Global Redirect to always have a single canonical path for each piece of content.

Dealing with Spam Comments on a Drupal Site

Submitted by tomo on October 11, 2012 - 1:26am

Drupal sites, like any content sites, naturally receive a lot of spam comments. Any blog or blog-like site which allows unauthenticated or anonymous users to comment on posts or any content is open to spam because spammers just want to have links to their websites displayed by your website for link-building purposes which is important for SEO. Spam comments used to be much more obvious as in blatant ads for penis-enhancing drugs. Nowadays, spammers are using more sophisticated scripts that are still easy to detect - by humans and usually also by spam-detection software. New spam might praise your blog or quote something you said in your blog post or just say something generic, perhaps on a related topic or perhaps not related at all. Then they will have their spam website in the URL field, if not also in the comment text. If the website has keywords which are totally unrelated to your blog, you can bet it's spam.

What can a Drupal website do about spam?

One old solution for spam, a common plugin on WordPress sites, is called Akismet. Akismet is a service and requires you to create an account and get an API key from them. Then they will help you detect spam.

Drupal has something like Akismet but improved and it was created by the Drupal creator himself. It's called Mollom, and it's also a cloud-based service, and you also create an account with them. Mollom is free to use although there are some paid services. I use Mollom on this blog. It catches hundreds of spam comments for me but also lets in a single false negative per day or so. I wouldn't have been able to turn on comments without turning on Mollom as I would immediately be deluged with spam. But I hope that Mollom continues to improve so that I don't even get 1 spam on most days.

Since I still do get some ham and spam comments, I have to process them somehow and report the spams to Mollom so they can improve their algorithms and heuristics for the future. Unfortunately, Drupal's default comments management view doesn't easily let me see if a comment is spam or not. In order to make that decision I need to see the URL and comment text that was saved. If there was no URL, it usually isn't spam, and if there was no URL in the comment text then most certainly it isn't spam. But if there was a link in the text, I need to see what site it links to, and see if the comment is at all intelligent or relevant. You can also tell by looking at any link saved in the URL field. Since Drupal's comment management page doesn't do this, I created a view, which you can import (this is Drupal 6) below.

The thing that Drupal's comment admin page offers is bulk operations. Mollom provides some operations such as report spam to Mollom and delete. This is usually what I want to do. Unfortunately, there's no way to use Mollom's actions in Views with Views Bulk Operations! So until this issue gets resolved (http://drupal.org/node/655846) I've done the next best thing which is to have links to the Mollom management page for each comment. It will still require you to open that page, select the reporting action you want, and then submit the form though. But this workflow has at least saved me some time and now I have removed all the really spammy spam from this site.

$view = new view;
$view->name = 'comments_more';
$view->description = '';
$view->tag = '';
$view->view_php = '';
$view->base_table = 'comments';
$view->is_cacheable = FALSE;
$view->api_version = 2;
$view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
$handler = $view->new_display('default', 'Defaults', 'default');
$handler->override_option('fields', array(
  'name' => array(
    'label' => 'Author',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'link_to_user' => 1,
    'exclude' => 0,
    'id' => 'name',
    'table' => 'comments',
    'field' => 'name',
    'relationship' => 'none',
  ),
  'homepage' => array(
    'label' => 'Author\'s website',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'display_as_link' => 1,
    'exclude' => 0,
    'id' => 'homepage',
    'table' => 'comments',
    'field' => 'homepage',
    'relationship' => 'none',
  ),
  'comment' => array(
    'label' => 'Body',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'exclude' => 0,
    'id' => 'comment',
    'table' => 'comments',
    'field' => 'comment',
    'relationship' => 'none',
  ),
  'delete_comment' => array(
    'label' => 'Delete link',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'text' => '',
    'exclude' => 0,
    'id' => 'delete_comment',
    'table' => 'comments',
    'field' => 'delete_comment',
    'relationship' => 'none',
  ),
  'edit_comment' => array(
    'label' => 'Edit link',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'text' => '',
    'exclude' => 0,
    'id' => 'edit_comment',
    'table' => 'comments',
    'field' => 'edit_comment',
    'relationship' => 'none',
  ),
  'hostname' => array(
    'label' => 'Hostname',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'exclude' => 0,
    'id' => 'hostname',
    'table' => 'comments',
    'field' => 'hostname',
    'relationship' => 'none',
  ),
  'status' => array(
    'label' => 'In moderation',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'type' => 'yes-no',
    'not' => 0,
    'exclude' => 0,
    'id' => 'status',
    'table' => 'comments',
    'field' => 'status',
    'relationship' => 'none',
  ),
  'timestamp' => array(
    'label' => 'Post date',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'date_format' => 'small',
    'custom_date_format' => '',
    'exclude' => 0,
    'id' => 'timestamp',
    'table' => 'comments',
    'field' => 'timestamp',
    'relationship' => 'none',
  ),
  'view_comment' => array(
    'label' => 'View link',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'text' => '',
    'exclude' => 0,
    'id' => 'view_comment',
    'table' => 'comments',
    'field' => 'view_comment',
    'relationship' => 'none',
  ),
  'cid' => array(
    'label' => 'Mollom',
    'alter' => array(
      'alter_text' => 1,
      'text' => '<a href="/mollom/report/comment/[cid]">Report to Mollom</a>',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'link_to_comment' => 0,
    'exclude' => 0,
    'id' => 'cid',
    'table' => 'comments',
    'field' => 'cid',
    'override' => array(
      'button' => 'Override',
    ),
    'relationship' => 'none',
  ),
));
$handler->override_option('access', array(
  'type' => 'none',
));
$handler->override_option('cache', array(
  'type' => 'none',
));
$handler->override_option('css_class', 'view-comments-more');
$handler->override_option('header', '<style>
.view-comments-more table {
background: white;
position: relative;
z-index: 100;
}
</style>');
$handler->override_option('header_format', '2');
$handler->override_option('header_empty', 0);
$handler->override_option('items_per_page', 30);
$handler->override_option('use_pager', '1');
$handler->override_option('style_plugin', 'table');
$handler->override_option('style_options', array(
  'grouping' => '',
  'override' => 1,
  'sticky' => 0,
  'order' => 'desc',
  'columns' => array(
    'name' => 'name',
    'homepage' => 'homepage',
    'comment' => 'comment',
    'delete_comment' => 'delete_comment',
    'edit_comment' => 'edit_comment',
    'hostname' => 'hostname',
    'status' => 'status',
    'timestamp' => 'timestamp',
    'view_comment' => 'view_comment',
  ),
  'info' => array(
    'name' => array(
      'sortable' => 1,
      'separator' => '',
    ),
    'homepage' => array(
      'sortable' => 1,
      'separator' => '',
    ),
    'comment' => array(
      'separator' => '',
    ),
    'delete_comment' => array(
      'separator' => '',
    ),
    'edit_comment' => array(
      'separator' => '',
    ),
    'hostname' => array(
      'sortable' => 0,
      'separator' => '',
    ),
    'status' => array(
      'sortable' => 0,
      'separator' => '',
    ),
    'timestamp' => array(
      'sortable' => 1,
      'separator' => '',
    ),
    'view_comment' => array(
      'separator' => '',
    ),
  ),
  'default' => 'timestamp',
));
$handler = $view->new_display('page', 'Page', 'page_1');
$handler->override_option('path', 'views/comments_more');
$handler->override_option('menu', array(
  'type' => 'none',
  'title' => '',
  'description' => '',
  'weight' => 0,
  'name' => 'navigation',
));
$handler->override_option('tab_options', array(
  'type' => 'none',
  'title' => '',
  'description' => '',
  'weight' => 0,
  'name' => 'navigation',
));

Drupal has many SEO features built in and available as contributed modules. One main one being Clean URLs. But it's often said that Drupal gives you "just enough rope to hang yourself".

Drupal has a powerful module called Pathauto that lets you create powerful URL patterns based on Tokens. Any number of modules can provides tokens via the Token API for you to use to construct URLs and you can easily create your own tokens with a bit of PHP code. With Path Auto you can also easily change the URLs for all your nodes, users, and taxonomy terms at once. This is the rope.

A big part of SEO is the link building you do outside of your site to get other sites to link to your site and your inner pages within the site. The problem is when you've done all this and have thousands of links to hundreds of your pages and then you decide to change all of your URLs. Suddenly, visitors to your pages are seeing 404 error pages and Google also no longer thinks you have any linked to pages.

So what can you do if you ever want to change the path of a node after you've already created the node and saved the URL? What can you do once you rebuild your paths from a new pattern? What if your maximum URL length limit was too short and now you need to fix all the long node URLs.

Fortunately, new versions of Path Auto integrate with Path Redirect, which is a module for managing lists of 301 URL redirects. So by hand, you could manually create 301 redirects from the previous alias to a new alias, but luckily you can also do this automatically now. A new option was added to Path Auto to "Create a new alias. Redirect from old alias." Choose this instead of just deleting old aliases and your new node paths should have old paths pointing to them, managed by Path Redirect.

Just remember that bulk update from within Path Auto isn't the only way to update URLs. You can also bulk update selected nodes from the default content management page and also edit the URL from each node's edit page.

To use this, just install both Path Auth and Path Redirect.

Related Issues: http://drupal.org/project/issues/pathauto?text=redirect+from+old+alias&status=All

When manually changing titles and thus URLs make sure to check "Automatically create redirects when URL aliases are changed." in Path Redirect's settings.

Regarding Path Redirect's fixes and Path Auto's fixes:

http://drupal.org/node/629742#comment-4336624


In short: the two work independently.

The option "Automatically create redirect" (on the Path Redirect admin screen) only governs situations where you manually change a path setting. Whether pathauto is or isn't installed, does not change this behavior.

Detail: when saving a node from the edit screen, the Path Redirect code executes before Pathauto does. It has no knowledge of whether Pathauto will or will not change the path alias, later on.

If pathauto runs afterwards and decides that the path needs changing, it will look only at its own "Update action" to determine what to do. If that is "Delete the old alias", it will indeed get deleted, and no redirect will be created (regardless of the "Automatically create redirect" option in the Path Redirect admin screen).

Drupal URLs can be pretty long. But practically, there's a limit in the database of 128 characters, even though browsers and web servers can support much longer URLs. With new versions of Path Auto, the schema is checked for alias column size. Then aliases longer than 128 characters are supported. This requires no hacking!

To change this, without just manually altering the length of the column in your database, you can use the following code in your own module:

/**
* Implementation of hook_schema_alter().
*/
function yourmodulename_schema_alter(&$schema) {
  $schema['url_alias']['fields']['dst']['length'] = 255;
}

Long URLs aren't very human friendly but even the oldest browsers can support URLs more than 2048 characters in length. Browsers support long paths, web servers support them, proxies support them, and mail clients either support them or break around 80 characters anyways. This doesn't mean you should carelessly throw around long URLs, but if you're generating them automatically then you don't need to cut them at an artificially low limit anymore.

Syndicate content
© 2010-2014 Saigonist.