Action Streams Easy Installation

| 1 Comment

I was installing Action Streams on Chris Alden’s r21.org and remembered that Mark Pascal showed me tip about installing Action Streams.

Instead of distributing all the files in the extlib directory in the sub-directories of the extlib directory in your MT install—as described in steps 3 of the Action Steams readme—Mark showed me that the Action Streams extlib directory can be placed in the Action Streams plugin directory.

When you download the Action Streams plugin, here are the files in the directory. Notice the location of the extlib directory:

ActionStreams-1.0/
    example_templates/
    extlib/
        HTML/
        HTTP/
        Web/
        XML/
    mt-static/
    plugins/
        ActionStreams/
            blog_tmpl/
            config.yaml
            lib/
            tmpl/
        Iwtst/

When you install Action Streams in your MT install, move the extlib directory under the Action Streams plugin directory:

MT_HOME/
    plugins/
        ActionStreams/
            blog_tmpl/
            config.yaml
            extlib/
                HTML/
                HTTP/
                Web/
                XML/
            lib/
            tmpl/

Clean URLs for Tag & String Searches

| No Comments

Because Movable Type is not always installed on servers where customers have access to the servers apache config or an .htaccess file, MT’s tag and string search urls look like:

Tag Search and String Search (respectively)

http://chezbeau.com/cgi-bin/mt/mt-search.fcgi?blog_id=1&tag=tomato&limit=20
http://chezbeau.com/cgi-bin/mt/mt-search.fcgi?search=tomato&IncludeBlogs=1&limit=20

These can easily be changed to more “clean” urls

http://chezbeau.com/tag/tomato
http://chezbeau.com/search/tomato

To convert your Movable Type powered site to use clean urls, follow these steps:

  1. Edit your .htaccess file and add the following lines

    RewriteEngine on
    RewriteRule ^tag/(.*)$ /cgi-bin/mt/mt-search.fcgi?blog_id=1&tag=$1&limit=20
    RewriteRule ^search/(.*)$ /cgi-bin/mt/mt-search.fcgi?search=$1&IncludeBlogs=1&limit=20
    

    The first line RewriteEngine on turns on the Rewriting Engine. The second and third lines use RewriteRule to map the desired urls to the actual urls.

  2. Update tag links in tag clouds and on entry details by replacing <$mt:TagSearchLink encode_js="1"$> with:

    <$mt:BlogURL$>tag/<$mt:TagName normalize="1"$>
    
  3. Update search form.

    This requires a few more invasive changes:

    1. add class search-form to the <form> element
    2. Include a link to jquery in your header. Use a local file or remotely hosted file like this one on Google:

      <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
      <script type="text/javascript">
      $(document).ready(function() {
          $('.search-form').submit(function() {
              window.location.href = "/search/" + $('.search-form input:text').val();
              return false;
          });
      });
      </script>
      

Notes:

Do Not Upgrade Plugin

| No Comments

Brad created a small plugin on the fly as a temporary fix to solve an upgrade issue which I’ve documented here for your pleasure… =)

This plugin will disable/stop/cancel all upgrades to a Movable Type installation.

Because some plugins require upgrade scripts, the DoNotUpgrade plugin must be removed/disabled/etc in order to perform upgrades to MT.

  1. Create a file:

    MT_DIR/plugins/DoNotUpgrade/config.yaml
    
  2. Add the following code to the file:

    callbacks:
        init_request: sub { MT->app->{upgrade_required} = 0 }
    

This plugin should work in 4.x versions of Movable Type.

Increase Basename Length for SEO URLs

| 2 Comments

Well authored urls make for good SEO. One the simplest ways to do this is to write good titles to your entries and then MT will dirify the title to create a basename from which the url to the entry is created. But if your entry title is longer than 100 characters, the rest of the url is clipped.

Good news! Basename can be increased to 250 characters. As it seems that most people would prefer unclipped urls to long urls, I added a feature request to increase the default to the max of 250 characters. Then if a user prefers to have smaller urls, they can modify this setting.

To change your default, navigate to Preferences > Entry Settings, and change Basename Length to your desired length.

Entry Settings - Adventures in Movable Type | Movable Type Pro

Wondering how to customize the Global Templates “Profile Edit Form” or the “Registration Form”? Here’s a few options.

Basic reordering of custom fields is possible on the edit profile page in the MT app. Using the “Reorder Fields” in the “related content” sidebar.

If you want to intersperse custom fields between default fields it’s a little more trickey; by default all built-in fields are output and then all custom fields are output in the order specified on the edit profile page.

The <mt:AuthorCustomFields> tag should be used for this but as of MT4.2 I couldn’t get it to work on the edit profile or registration form, so for now you can use the same loop that currently outputs the custom fields, but limit the output with an <mt:if> tag. Here’s an example of how you can do it…

Description

Use three loops each containing an conditional tag (if or unless) to limit the output of the loop by custom field basename. The first and second loops limit by checking to see if the basename is equal to a value. The third loop outputs all fields except the the two I’ve specified (if fields are duplicated on the form the html will be invalid and only the second input’s value will be saved)

Example

Thi example uses the custom fields “Level” and “Bio”. You may place each loop anywhere in the Edit Profile template’s form.

<mt:Loop name="field_loop">
   <mt:If name="__first__">
   <input type="hidden" name="_type" value="author" id="obj_type" />
   <input type="hidden" name="customfield_beacon" value="1" id="customfield_beacon" />
   </mt:If>
   <mt:if name="basename" eq="level">
   <!-- start-customfield_<$mt:Var name="basename"$> -->
   <mtapp:setting
   id="$field_id"
   label="$name"
   hint="$description"
   shown="$show_field"
   show_hint="$show_hint"
   required="$required">
   <$mt:Var name="field_html"$>
   </mt:App:Setting>
   <!-- end-customfield_<$mt:Var name="basename"$> -->
   </mt:if>
</mt:Loop>

<!-- Default field here -->

<mt:Loop name="field_loop">
   <mt:If name="__first__">
   <input type="hidden" name="_type" value="author" id="obj_type" />
   <input type="hidden" name="customfield_beacon" value="1" id="customfield_beacon" />
   </mt:If>
   <mt:if name="basename" eq="bio">
   <!-- start-customfield_<$mt:Var name="basename"$> -->
   <mtapp:setting
   id="$field_id"
   label="$name"
   hint="$description"
   shown="$show_field"
   show_hint="$show_hint"
   required="$required">
   <$mt:Var name="field_html"$>
   </mt:App:Setting>
   <!-- end-customfield_<$mt:Var name="basename"$> -->
   </mt:if>
</mt:Loop>

<!-- Default field here -->

<mt:Loop name="field_loop">
   <mt:If name="__first__">
   <input type="hidden" name="_type" value="author" id="obj_type" />
   <input type="hidden" name="customfield_beacon" value="1" id="customfield_beacon" />
   </mt:If>
   <mt:unless name="basename" like="(bio|level)">
   <!-- start-customfield_<$mt:Var name="basename"$> -->
   <mtapp:setting
   id="$field_id"
   label="$name"
   hint="$description"
   shown="$show_field"
   show_hint="$show_hint"
   required="$required">
   <$mt:Var name="field_html"$>
   </mt:App:Setting>
   <!-- end-customfield_<$mt:Var name="basename"$> -->
   </mt:unless>
</mt:Loop>

Aaron Vanderzwan offers a similar solution and Elise summarized the solution on LearningMT4.com

MTML Code in Entries or Pages

| No Comments

You want a page with a title and a few paragraphs… but you also want a list of entries as a part of the page. How to do it?

You can use the mteval global modifier, but in the note I added there due to the way MT is optimized to publish, using the mteval global modifier isn’t really an option for most cases.

But there is a better way. The concept is to use an index template but to build the content of the template by combining content from a page and from entries.

Here’s how to create a page for entries tagged as events:

  1. Create a page titled “Events”.

    Add the body text “These are our events”.

    Add the tag “@eventpage”.

  2. Create a few entries with sample event info and add the tag “event”.

  3. Create a new index template called “Events” and set the output file as events.html.

    In the body of the template add this code to list the most recent 10 events tagged with the private tag “@event”:

    <mt:Pages tag="@eventpage" lastn="1">
        <h1><$mt:EntryTitle$></h1>
        <$mt:EntryBody$>
    </mt:Pages>
    <ul>
    <mt:Entries tag="event" lastn="10">
        <li><a href="<$mt:EntryPermalink$>"><$mt:EntryTitle$></a></li>
    </mt:Entries>
    </ul>
    
  4. Save the index template… and then publish the index template.

That’s it. =)

Update: I’ve placed this upgrade script on the wiki, a better place for more people to enjoy and collaborate: wiki.movabletype.org/MT_Shell_Script_Installer

Automation is awesome! This script I use to set up a new MT instance probably saves me 15-20 hours a year, that 2-3 workdays.

I use the below shell script to:

  • checkout target release of MT
  • checkout addons (Packs [ProPack, MTCS, Enterprise], static files, & Tristan Theme)
  • checkout addons themes (Tristan
  • issue make
  • set up a static directory for the release
  • set permissions
  • create a mt-config.cgi file
  • and finally… open the release in TextMate

Getting FastCGI configured and running can be a pain. There are FastCGI instructions on MovableType.org, but the page is so long that it looks kinda daunting.

Strangecode has got FastCGI enabled for all hosting accounts. So after installing Movable Type all I had to do to was the following two steps:

  1. Create symlinks to the primary MT scripts with names ending in .fcgi.

    $ cd /PATH/TO/MT
    $ for F in mt{,-comments,-search,-tb}.cgi; do ln -s $F $(basename $F .cgi).fcgi; done
    
  2. Add these lines to mt-config.cgi.

    AdminScript mt.fcgi
    CommentScript mt-comments.fcgi
    SearchScript mt-search.fcgi
    TrackbackScript mt-tb.fcgi
    

Advanced Archive Widget

| 1 Comment

Anil ArchivesMie has been blogging every month since 2003 on kokochi.com, the list of 57 monthly archives in her sidebar was getting really long.

Mie asked if I could add an archive widget to her blog’s sidebar like the one Anil sports on dashes.com. After looking at the source HTML I realized that coding it in MTML was gonna be kinda complex. In MTML typically for each year in your archives you’d list all the months, but—because of the way that html tables are built—I’d need to list all the months for each year. For example, I need to list all the Jan archives, then all the Feb archives, etc. etc.)

So I asked Anil for his code. Doh! He admitted he was manually updating it. =P

mie-archives.gifI mentioned this to Brad, and he got so excited that he wrote a rough draft. I added the code to the sidebar on Kokochi.com, but the code wasn’t working. =/ After some testing, I realized that there were a few limitations (year’s w/o posts, and the inability to output the month as a number w/o a “0” prefix on single digit months), but then after consulting with Brad, solutions were found!

Follow the below code and you too can have this advanced archive table widget as seen on kokochi.com and dashes.com/anil.

Update: The blog must be publishing a yearly archive file. This file can have zero content, but needs be published in order for the Yearly ArchiveList block tag to output content. 2008 Oct 7

The MTML Code

<table id="archives-table">
<mt:ArchiveList type="Yearly" sort_order="ascend">
    <mt:ArchiveListHeader><tr><$mt:ArchiveDate format="%Y" setvar="start_year"$></mt:ArchiveListHeader>
    <th><$mt:ArchiveDate format="'%y"$></th>
    <$mt:ArchiveDate format="%Y" setvar="year"$>
    <$mt:setvar name="is_posts_year_{$year}" value="1"$>
    <mt:ArchiveList type="Monthly">
        <$mt:ArchiveDate format="%m_%Y" setvar="month_year"$>
        <mt:SetVarBlock name="links_{$month_year}"><a href="<$MTArchiveLink$>"><mt:ArchiveDate format="%b"$></a></mt:SetVarBlock>
    </mt:ArchiveList>
    <mt:ArchiveListFooter></tr><$mt:ArchiveDate format="%Y" setvar="end_year"$></mt:ArchiveListFooter>
</mt:ArchiveList>
<mt:for var="month" from="1" to="12">
    <tr>
    <mt:for var="year" from="$start_year" to="$end_year">
        <mt:if name="is_posts_year_{$year}">
            <mt:setvarblock name="month_year"><mt:var name="month" sprintf="%02d">_<mt:var name="year"></mt:setvarblock>
        <td><$mt:var name="links_{$month_year}" default="&nbsp;"$></td>
        </mt:if>
    </mt:for>
    </tr>
</mt:for>
</table>

The Code Explained

Here’s a play-by-play on the MTML code used to produce this list…

Open the table.

<table id="archives-table">

List yearly archives in an ascending order (2001, 2002, 2003, etc).

<mt:ArchiveList type="Yearly" sort_order="ascend">

Open the TR; set the $start_year variable.

    <mt:ArchiveListHeader><tr><$mt:ArchiveDate format="%Y" setvar="start_year"$></mt:ArchiveListHeader>

Output the two-digit year in a TD.

    <th><$mt:ArchiveDate format="'%y"$></th>

Set $year variable with the current year in the archive list.

    <$mt:ArchiveDate format="%Y" setvar="year"$>

Set $is_posts_year_$year using year variable set above. This is a boolean variable that determines if there are posts within the year in context.

    <$mt:setvar name="is_posts_year_{$year}" value="1"$>

List monthly archives for the current year.

    <mt:ArchiveList type="Monthly">

Set the $month_year variable after removing the “0” from the front of the month if it exists (eg. 1_2005, 2_2005 … 12_2005).

        <$mt:ArchiveDate format="%m_%Y" regex_replace="/^0/","" setvar="month_year"$>

Set the links_$month_year variable. This variable name is dynamically set using the $month_year var set above. The value will be a month linked to the correct archive (eg. <a href="http://kokochi.com/archives/2004/05/">May</a>).

        <mt:SetVarBlock name="links_{$month_year}"><a href="<$MTArchiveLink$>"><mt:ArchiveDate format="%b"$></a></mt:SetVarBlock>

Close monthly archive list.

    </mt:ArchiveList>

Close the TR. Set the $end_year variable.

    <mt:ArchiveListFooter></tr><$mt:ArchiveDate format="%Y" setvar="end_year"$></mt:ArchiveListFooter>

Close the yearly archive list.

</mt:ArchiveList>

For months 1 thorugh 12 do the following.

<mt:for var="month" from="1" to="12">

Open TR.

    <tr>

Loop through the years between $start_year and $end_year.

    <mt:for var="year" from="$start_year" to="$end_year">

If there is posts in the current year, then continue.

        <mt:if name="is_posts_year_{$year}">

Set the $month_year variable using the $month and $year variables from the above for loops.

            <mt:setvarblock name="month_year"><mt:var name="month">_<mt:var name="year"></mt:setvarblock>

Use the $month_year variable to output the links_$month_year set in the archive lists above.

        <td><$mt:var name="links_{$month_year}" default="&nbsp;"$></td>

Close all the MTML loops, MTML conditionals, and HTML tags.

        </mt:if>
    </mt:for>
    </tr>
</mt:for>
</table>

Scaleable?

As long as your sidebar is wide enough, you’ll have room for this widget as it get’s wider. But by hacking the above code it shouldn’t be to hard to break the table into two vertically stacked tables or add some javascript to produce a solution involving hiding/showing of content.

If you hack the above, I’d love to hear about it.

Enjoy.

And thx again to Brad Choate, Mie Yaginuma, and Anil Dash for the instigation and assistance to produce this advanced example of MTML.

Update: I’ve placed this upgrade script on the wiki, a better place for more people to enjoy and collaborate: wiki.movabletype.org/MT_Shell_Script_Installer

Below code is no longer cutting edge technology. =P

Follow these steps to easily switch between versions of Movable Type.

Requirements

  • Subversion - Movable Type development is kept in a version control system called Subversion. Subversion allow many developers to work on the same code at the same time.
  • shell access - I use Terminal.app on my MacBook Pro.

Development Branches

There is a branch for each development cycle. These branches are worked on for 1-3 weeks, before a branch is closed and passed to QA for testing. If QA finds any bugs, then bugs are fixed in the branch. All subsequent features are implemented in the next branch sequentially. The branch with the highest number is the most current release (as of this writing, release-35)

Stable Tags

Once a particular place in development is tested and approved for release the code at that point is tagged with a release number.

Checkout the Code

These steps will be a little different based upon the setup of the web hosting environment. Here’s a simplified example of how I set-up Movable Type:

www.beausmith.com/
    cgi/
        release-33/
        release-34/
        mt  -> release-34
        mt4.01
        mt4.11
    html/
        blog/
            (archives here)
        index.php
        mt-static -> ../../cgi/mt/mt-static

The items with the arrow -> are symlinks. These allow me to not have to change urls when I update to a new release and also allow me to keep my mt-static directory inside the release folder. When I want to update to release-35, here’s the steps I’ll take:

  1. Navigate to the cgi directory & use the subversion checkout command to get the latest version:

    $ pwd;
    /www.beausmith.com
    $ cd cgi;
    $ svn co http://code.sixapart.com/svn/movabletype/branches/release-35;
    
  2. Issue the make command to build the current release

    $ make;
    
  3. Make the support files writeable

    $ chmod -R 777 release-35/mt-static/support
    
  4. Remove the current symlink and create a new symlink to point to your release branch. I do this in the same step so as to avoid any potential downtime while switching.

    $ rm mt; ln -s release-35 mt;
    

That’s it! Go access you MT installation.

Updating

Since changes will be committed round the clock by the MT teams in San Francisco and Japan, you’ll want to update often to get the latest changes.

    $ cd cgi/release-35;
    $ svn up;
    $ make;

Doing a make is not necessary unless there are *.pre files that need to be rendered for the current language.

Note: If you make changes to the files in the MT code, they may conflict with the updated code. Look forward to a future article about Subversion basics.

Switching Between Movable Type Installs

Is there a bug in release-35 and you want to go back to the stable mt4.11 install? Easy. Remove the mt symlink and then create a new one pointing to the desired MT install:

    $ rm mt; ln -s mt4.11 mt;

View Changes & Code Diffs with Trac

Trac also makes it easy to browse through all the recent changes to any branch of Movable Type. Note the similarity & differences in the urls

  • trac: http://code.sixapart.com/trac/movabletype/browser/branches/release-35/
  • svn: http://code.sixapart.com/svn/movabletype/branches/release-35/

Questions? Please comment below.

Recent Comments

  • toni.hambilton.myopenid.com: Action Streams is one of the plugins that I have read more
  • Beau Smith: A few answers…. Never use beta code for critical projects. read more
  • Beau Smith: I totally agree… asset management will surely be revisited in read more
  • Elise: Hi Beau, Feedback for MT - would you guys please read more
  • Plasticmind: Thanks for the write up, very handy Beau! read more
  • Beau Smith: Fair ‘nuff… some MT users could be considered spammers though read more
  • Jay Allen: My thoughts on the subject: http://jayallen.org/2008/09/oh-awesome-I-cant-wait-for-the-proliferation-of-idiotically-and-needlessly-long-urls-that-look-like-ones-created-by-spammers-because-as-we-know-users-dont-read-or-change-defaults-they-only-complain-yes-that-will-be-great-for-the-web-and-for-all-of-us.html read more
  • Kaan: Hey Beau, Obvious question… what happens if there’s schema changes read more
  • Beau Smith: Edit entry/page links when user = author or sysadmin read more
  • Beau Smith: New Template Set Request Comment Registration and Login Forms Scoring read more

Recent Assets

  • mie-archives.gif
  • Anil Archives
  • Firefox MT Docs Bookmark Shortcut

Find recent content on the main index or look in the archives to find all content.

OpenID accepted here Learn more about OpenID
Powered by Movable Type 4.21-en