Cchost/developer/tutorial/Remix Me

From Creative Commons
Revision as of 13:17, 15 November 2008 by Fourstones (talk | contribs) (Making it 'publicize' Compatible)
Jump to: navigation, search


Docs Home Install Upgrade Troubleshoot Customize Admins Devs Content Query Templates Commands Skins


Overview

This tutorial will walk through the creation of a feature for ccMixter.org that was added by taking full advantage of template engine and Query API. If you just want to download and install the finished project or want to follow along in your own version of the code you can jump down to the download section.

The idea was to create a quick-and-dirty version of a feature of other remix sites that allow artists to embed "remix me" widgets onto their site. (Typical example is from the Trifonic site.) Those sites use fancy Flash (tm) widgets, but here we aren't aiming so high. We just want a simplified version of that, something that leads remixers to the stems and starts them down the road to uploading.

Even though this feature was made with ccMixter in mind, we've written the code to be portable to all ccHost installations. The ccMixter specific parts (logo and headline) are parametrized using the template tag ('Edit Footers and Banners') admin screens so you can customize it without changes to the code.

Tech Notes

This feature involves four custom templates and one custom dataview (embedded into one of the templates).

This tutorial demonstrates the flexibility of templates. By the end we will:

  • Create a template the fits into the publicize feature.
  • Create a template that targets a popup window.
  • Nest a ccHost system template in a wrapper template of our own.
  • Create a 'feature page' template that ties it all together.

The entire project, from concept to check-in took less than four hours to put together and install on the site.

Feature Requirements

For this feature we want to generate an HTML snippet that will:

  • List the remixes of a given artist with the ability to stream, download and find out more about the remix.
  • Show a link for downloading stems
  • Show a link for uploading a remix.

This last step is a little tricky. What other sites do is direct users to a screen that allows them to register an account with the site in the same transaction as upload their remix. We won't be quite so fancy and just create a screen that directs users to either create an account or, if they already have an account, submit the remix.

Implementation Spec

To create this feature we will create several templates and use the Query API to call them. Here are the templates we want to make:

  • A Remix Me template - this will be embedded into the user's blog or web site. It will have to be 'straight' HTML and assume nothing about styles or layout.
  • A Get My Stems template - when the user clicks on 'get my stems' this will popup a window with a list of download-able samples from the artist.
  • An Upload My Remix template - this will live on the ccHost installation site and direct the remixer to either the login/register screens or the 'Submit Remix' screen depending on whether they are logged in already.
  • In addition to those we'll create a page on our installation with instructions for our users about how to install the embedding's snippets into their blogs.

We will craft this feature so it will appear in the list of optional embedding in the publicize feature, so technically the last page mentioned is not needed -- but the feature is just cool enough that we'll create it's own instruction page, hopefully inspiring ccMixter users to give it go.

Making the Templates

The 'Remix Me' Embedding Template

The template we embed onto the user's blogs is the most complicated, important piece so we'll start there.

The way we embed snippets into external sites is to generate a <script> tag. The SRC attribute of that tag points back to ccMixter and requests a Query API call whose format parameter is set to docwrite. This parameter is the same as the html format, except the returning HTML in wrapped in javascript docwrite() calls, injecting the results directly into the web page. All the user has to do is copy the one line of HTML with the <script> tag and we do the rest.

For the SRC attribute we're aiming for a query that will look something like:

 api/query?f=docwrite&t=remix_me&user=<user_name>

Making it 'publicize' Compatible

ccHost already has a feature for generating these types of embedding. It's called the publicize command. (You can see it action at ccMixter.) If we do our 'Remix Me' feature right, it will just slip into the 'format' drop down.

In order to this we need to have certain things in place:

  • The template must reside in <local_files>/skins/formats
  • The meta section of the template must specify type = format
  • The same meta section must have a 'desc' field with a one-line description

The template should also be amenable to either remixes by our user or of our user, unfortunately this is a drag because, really, we only care about the remixes of our user. Ah well, the template will act a little funny in publicize but we'll make up for below.

Since this feature is about remixes of a given artist and it really doesn't make sense to do it for remixes by the user. There we'll also specify that remixesof parameter as a requirement of the query in the meta section.

We put the following shell of the template into <local_files>/skins/formats/remix_me.tpl:

 %%
   [meta]
     type          = format
     desc          = _('Remix ME (use with Other Peoples Remixes...)')
     required_args = remixesof
   [/meta]
 %%

Making it Portable to non-ccMixter Sites

Keeping in mind that this code might be used on sites other than ccMixter, the key phrases and logo are pulled in from the environment so admins can customize the feature.

We look for two variables in the template remix-me-title and remix-me-logo but don't assume either is there. We'll use the %if_not_null% Cchost/concepts/Templates#Macro_tabletemplate macro to check:

 %if_not_null(remix-me-logo)% 
    <img style="float:left" src="%(remix-me-logo)%" />
 %end_if%

Adding a 'Download My Stems' Popup Window

We want to have a link at the top that says 'Download My Stems'. This should lead to a popup window with a list of the artist's upload tagged sample.

ccHost arlready has a download template that lists out the download links for a query (example here).

We use the html format parameter so we don't get the whole skin into the popup window.

Ideally the URL for that popup window would be something:

 <your_installation_root>api/query?t=download&user=<user_name>&f=html

Unfortunately, we don't have the user_name (!) as part of the query results in the this template (remember, the query results are the remixes of this artist). However, we do have the user name in the query that generated this template -- it's in the remixesof parameter. So the best we can do is squeeze off the remixesof PHP's $_GET variable.

In order to make the code portable, we use the query-url variable for our ccHost installation:

   <a onclick=
     "window.open( '%(query-url)%t=download&user=%(#_GET/remixesof)%&f=html', 
                   'cchwin',
                   'height=600,width=450'); 
                   return 0;">download my stems</a>

(For brevity we've left off all the javascript goop for the window specs. You can see all that in the code download.)

Adding a 'upload your remix' Link

We'll add another link in the header of the template that points to a template directing the user to the sumbit remix screen (or register if they don't have an account). We'll fill out the remix_me_upload template later, for now we'll use the $_GET trick again to get the user's name:

   <a href="%(query-url)%t=remix_me_upload&user=%(#_GET/remixesof)%">upload your remix</a>

Displaying the remixes

We'll want to loop over the records and display the remixes of our artist by upload name and remixer. Because we are embedding into random blogs we want to keep everything self contained -- no links to CSS files, no outside scripts and the safest layout mechanism possible. That means (forgive me) <table>. We'll also want to control the overflow so we'll make extensive use of the %chop% template macro when displaying names:

 <table cellpadding="0" cellpadding="0">
   %loop(records,R)%
     <tr>
        <td>%chop(#R/upload_name,23)%</td>
        <td>%text(str_by)% </td>
        <td>%chop(#R/user_real_name,12)% </td>

 %end_loop% </table> You're now ready to take a peak. Pick a user that has been remixed in your installation and try: api/query?t=formats/remix_me.tpl&remixes=<user_name> (See why you need the .tpl extension in this case.)

Customizing the Dataview

Until now we're using the default dataview. If you dump that using dpreview=1 to peek inside, you'll see there is no file download URL field. Since we want a download link for each remix we'll need a different set of columns. (While we're at, we will optimize to only the columns we need to avoid default dataview's intense performance overhead.) We'll setup a custom dataview...

   [meta]
     type = format
     desc = _('Remix ME (use with Other Peoples Remixes...)')
     required_args = remixesof
     dataview = remix_me
     embedded = 1
   [/meta]

and embed it directly into the template:

   [dataview]
 function remix_me_dataview()
 {
   $sql =<<<EOF
       SELECT upload_id, upload_contest, upload_name, user_name, user_real_name
              %columns%
       FROM cc_tbl_uploads
       JOIN cc_tbl_user ON upload_user=user_id
       %joins%
       %where%
       %order%
       %limit%
 EOF;

     $sql_count =<<<EOF
       SELECT COUNT(*)
       FROM cc_tbl_uploads
       JOIN cc_tbl_user ON upload_user=user_id
       %joins%
       %where%
       %order%
 EOF;

       return array( 'sql' => $sql, 
                     'sql_count' => $sql_count, 
                     'e' => array( CC_EVENT_FILTER_DOWNLOAD_URL ) );
 }
 [/dataview]

The return array has the event that will trigger the dataview filter to generate the 'download_url' field in the returning records. That particular filter requires some columns to work (upload_id, upload_contest, upload_name) so we made those part of the SELECT statement.

Now that we have the 'download_url' we can use it in the display table:

 <td><a href="%(#R/download_url)%">download</a></td>

Adding the Stream URL

Audio streaming in ccHost is done by an M3U "plain text" query formatter. All that is needed is the upload_id for the ids parameters. We can safely embed the query URL directly into the HREF attribute of an anchor because most browsers will not navigate to page, just call up the system's music player. (No, it's not ideal but we're just trying to get through this - exercise for the reader: cram a Flash(tm) player into this scheme somewhere.)

The stream link looks like:

 <td><a href="%(query-url)%f=m3u&ids=%(#R/upload_id)%">stream</a></td>

Adding an 'info' button

To add an 'info' button we'll use ccHost's 'i' icon at ccskins/shared/images/i-fg.png. Again, because we are being embedded into a random blog's page and we don't want any borders on the image. To generate a fully qualified URL we'll use the %url% template macro:

  <img style="border:0px" src="%url('images/i-fg.png')%" />

The link we wrap around this will need a URL to the page of the remix. We can generate this into a field (i.e. SQL column) called 'file_page_url' using the ccl URL builder helper and then SQL's CONCAT function:

   [dataview]
 function remix_me_dataview()
 {
   $furl = ccl('files') . '/';

   $sql =<<<EOF
       SELECT upload_id, upload_contest, upload_name, user_name, user_real_name,
              CONCAT( '{$furl}', user_name, '/', upload_id ) as file_page_url
              %columns%
       FROM cc_tbl_uploads
       JOIN cc_tbl_user ON upload_user=user_id
       %joins%
       %where%
       %order%
       %limit%
 EOF;

Now that the remix's page URL is available we can use it in the wrapper link:

 <td><a href="%(#R/file_page_url)%"><img style="border:0px" src="%url('images/i-fg.png')%" /></a></td>

The 'Download My Stems' Template

Unfortunately the system's download template is really boring. We want to style it similar to our embedding look/feel and we want a pretty header with the user's name and other information in it.

We will make our version in <local_files>/skins/remix_me_download.tpl directory.

Quick back step: since we're changing templates we have to update our #Adding_a_.27Download_My_Stems.27_Popup_Window popup window URL in the embedding template:

    window.open( '%(query-url)%t=remix_me_download&user...

Nesting Templates

Here we take advantage of the nesting quality of templates and queries: We can embed the system download template in one of our own.

Each template is a self-contained entity. They each have their own query that triggers them, their own dataview that defines the data sources and their own rendering that defines what the results are formatted like.

Just because we embed the system's download template does 'not' mean we have to have the same query, dataview or render format.

In this case the query for our 'outer' may look the same as the one we pass to the download when we embed it, but it will behave in a very, very different. (For a technical explanation see the section on datasources.)

Digging Out the User

In ccHost the user has two 'names' - the login name and a 'pretty' name called user_real_name internally. In order to get that piece of information in our 'outer' template we'll use the system's user_basic dataview which returns basic information from the user's record.

We'll also require callers to this template to use a user parameter:

 %%
   [meta]
      type         = template_component
      dataview     = user_basic
      require_args = user
   [/meta]
 %%

Since we only care about one user at a time, we use the %map% template macro to get the first (and only) user in the array into a local variable:

 %map(#R, records/0 )%

The combination of these steps will allow us to display good looking information about the user like:

 <h2>Remix %(#R/user_real_name)%!</h2>
 Here are %(#R/user_real_name)%'s stems for download...

Embed the System's 'Download' Template

Ideally we'd just use the %query% template macro with something:

 %query('t=download&tags=sample&user=%(#R/user_name)%')%

Unfortunately macros can not nest so we have to drop to PHP. You can see we use the embed format which will run the query and output the HTML directly to the screen in situ. The PHP equivalent of the %query% macro, now with our parameter is:

 <?= cc_query_fmt(
         'f=embed&noexit=1&nomime=1&t=download&tags=sample&user=' .
         $R['user_name']);
 ?>

The 'Remix Me' Upload Template

The 'Remix Me' Feature Page

Download the Source

The source for the latest version of feature is available scattered about the ccHost SVN repository. The version that this tutorial uses is available from here (ZIP).

Installing

  • Unzip the source ZIP file on your local directory and copy the files to <local_files>/skins maintaining the directory structure.

Customizing

  • Log in as admin to your ccHost installation (if not already)
  • Click on Manage Site, then Banner and Footers, then Banner Text, Footers, etc.
  • In the header of the form click on clicking here.
  • Type in the text: 'remix-me-title' (without the quotes)
  • Click on 'Submit' (this should bring you back to the 'Edit Banners...' form).
  • Again, in the header of the clicking here
  • Type in the text: 'remix-me-logo' (without the quotes)
  • Click on 'Sumbit'
  • Now at the bottom of this form you should see the new fields you just enetered.
    • For the title enter something like 'Remix Me' - this will be the text that is displayed in the embedding on the users' sites.
    • For the logo enter the fully qualified URL to any logo you want to appear in the embedding. This is optional and you can fill it in later.

Now your "remix me" feature is ready to go. You should see it as an option when you browse to publicize/<user_name> and also when you browse to api/query?t=remix_me_embed&user=<user_name> which you put into your menu for registered users.