Changeset 1122

Show
Ignore:
Timestamp:
09/22/08 20:24:17 (18 months ago)
Author:
mpaschal
Message:

Merge changes to 2.1 for Sandbox plugin
Used:

svn merge -r 820:1061 http://code.sixapart.com/svn/mtplugins/branches/StyleCatcher-2.1-dev/ .

Location:
trunk/StyleCatcher
Files:
1 removed
6 modified
3 copied

Legend:

Unmodified
Added
Removed
  • trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/CMS.pm

    r1120 r1122  
    99use strict; 
    1010use File::Basename qw(basename); 
     11 
     12use MT::Util qw( remove_html decode_html ); 
    1113 
    1214our $DEFAULT_STYLE_LIBRARY; 
     
    142144} 
    143145 
     146sub files_from_response { 
     147    my ($res, %param) = @_; 
     148 
     149    my $extensions = $param{css} ? qr{ (?:gif|jpe?g|png|css) }xms 
     150                   :               qr{ (?:gif|jpe?g|png)     }xms 
     151                   ; 
     152 
     153    my $stylesheet = $res->content; 
     154    $stylesheet =~ s!/\*.*?\*/!!gs;    # strip all comments first 
     155    my @images = $stylesheet =~ m{ 
     156        \b url\( \s*                          # opening url() reference 
     157        ['"]? 
     158        ( [\w\.\-/]+\.$extensions )  # a filename ending in an image extension 
     159        ['"]? 
     160        \s* \)                                # close of url() reference 
     161    }xmsgi; 
     162 
     163    return @images; 
     164} 
     165 
     166sub download_theme { 
     167    my $app = shift; 
     168    my ($url) = @_; 
     169 
     170    my $static_path = $app->static_file_path; 
     171    my $themeroot   = File::Spec->catdir($static_path, 'support', 'themes'); 
     172    my $ua          = $app->new_ua(); 
     173    my $filemgr     = file_mgr() 
     174        or return; 
     175 
     176    my @url = split( /\//, $url ); 
     177    my $stylesheet_filename = pop @url; 
     178    my $theme_url = join(q{/}, @url) . '/'; 
     179 
     180    my ($basename, $extension) = split /\./, $stylesheet_filename; 
     181    if ($basename eq 'screen' || $basename eq 'style') { 
     182        $basename = $url[-1]; 
     183    } 
     184 
     185    # Pick up the stylesheet 
     186    my $stylesheet_res = $ua->get($url); 
     187 
     188    my @images = files_from_response($stylesheet_res, css => 1); 
     189 
     190    my $theme_path = File::Spec->catdir($themeroot, $basename); 
     191    if (!$filemgr->mkpath($theme_path)) { 
     192        my $error = $app->translate("Could not create [_1] folder - Check that your 'themes' folder is webserver-writable.", 
     193            $basename); 
     194        return $app->json_error($error); 
     195    } 
     196 
     197    $filemgr->put_data( $stylesheet_res->content, 
     198        File::Spec->catfile($theme_path, $basename . '.css') ); 
     199 
     200    # Pick up the images we parsed earlier and write them to the theme folder 
     201    my %got_files; 
     202    my @files = ('thumbnail.gif', 'thumbnail-large.gif', @images); 
     203    FILE: while (my $rel_url = shift @files) { 
     204        # Is this safe to get? 
     205        my $full_url = URI->new_abs($rel_url, $theme_url); 
     206        next FILE if !$full_url; 
     207        my $url = $full_url->as_string(); 
     208        next FILE if $url !~ m{ \A \Q$theme_url\E }xms; 
     209 
     210        next FILE if $got_files{$url}; 
     211        $got_files{$url} = 1; 
     212        my $res = $ua->get($url); 
     213 
     214        # Skip files that don't download; we were accidentally doing so already. 
     215        next FILE if !$res->is_success(); 
     216 
     217        my $canon_rel_url = URI->new($rel_url)->rel($theme_url); 
     218        my @image_path = split /\//, $canon_rel_url->as_string(); 
     219        my $image_filename = pop @image_path; 
     220 
     221        my $image_path = File::Spec->catdir($theme_path, @image_path); 
     222        if (!$filemgr->exists($image_path) && !$filemgr->mkpath($image_path)) { 
     223            my $error = $app->translate("Could not create [_1] folder - Check that your 'themes' folder is webserver-writable.", 
     224                $basename); 
     225            return $app->json_error($error); 
     226        } 
     227 
     228        my $image_full_path = File::Spec->catfile($image_path, $image_filename); 
     229        $filemgr->put_data($res->content, $image_full_path, 'upload') 
     230          or return $app->json_error( $filemgr->errstr ); 
     231 
     232        if ($image_filename =~ m{ \.css \z }xmsi) { 
     233            my @new_files = files_from_response($res, css => 0); 
     234            # Schedule these as full URLs so relative references aren't 
     235            # misabsolved relative to the theme directory. 
     236            @new_files = map { 
     237                my $uri = URI->new_abs($_, $url); 
     238                $uri ? $uri->as_string() : (); 
     239            } @new_files; 
     240            push @files, @new_files; 
     241        } 
     242    } 
     243 
     244    return $basename; 
     245} 
     246 
    144247# does the work after user selects a particular theme to apply to a blog 
    145248sub apply { 
    146249    my $app = shift; 
    147250 
    148     my $blog_id = $app->param('blog_id'); 
    149     my $url     = $app->param('url'); 
    150     my $layout  = $app->param('layout'); 
    151     my $name    = $app->param('name'); 
     251    my ($blog_id, $url, $layout, $name, $template_set) 
     252        = map { $app->param($_) || q{} } (qw( blog_id url layout name template_set )); 
    152253 
    153254    # Load the default stylesheet for this blog 
     
    163264    } 
    164265 
    165     my $themeroot = 
    166       File::Spec->catdir( $static_path, 'support', 'themes' ); 
    167     my $webthemeroot = $app->static_path . 'support/themes/'; 
    168     my $mtthemeroot  = $app->static_path . 'themes/'; 
    169     my $mtthemebase  = $app->static_path . 'themes-base/'; 
    170  
    171     # Break up the css url in to a couple useful pieces 
    172     my @url = split( /\//, $url ); 
    173  
    174266    # if this isn't a local url, then we have to grab some files from 
    175267    # yonder... 
    176     my $filemgr = file_mgr() 
    177       or return $app->json_error( MT::FileMgr->errstr ); 
    178  
    179     if ( $url !~ m/^(\Q$webthemeroot\E|\Q$mtthemeroot\E)/ ) { 
    180         my $new_url = ''; 
    181  
    182         for (0..(scalar(@url)-2)) { 
    183             $new_url .= $url[$_] . '/'; 
    184         } 
    185         my ( $basename, $extension ) = split( /\./, $url[-1] ); 
    186         if ($basename eq 'screen') { 
    187             $basename = $url[-2]; 
    188         } 
    189  
    190         # Pick up the stylesheet 
    191         my $user_agent  = $app->new_ua; 
    192         my $css_request = HTTP::Request->new( GET => $url ); 
    193         my $response    = $user_agent->request($css_request); 
    194  
    195         # Pick up the thumbnail and thumbnail-large 
    196         my $thumbnail_request = 
    197           HTTP::Request->new( GET => $new_url . "thumbnail.gif" ); 
    198         my $thumbnail_response = $user_agent->request($thumbnail_request); 
    199         my $thumbnail_large_request = 
    200           HTTP::Request->new( GET => $new_url . "thumbnail-large.gif" ); 
    201         my $thumbnail_large_response = 
    202           $user_agent->request($thumbnail_large_request); 
    203  
    204         # Parse out image filenames in the css and then write out the css file 
    205         # and thumbnails to our theme folder 
    206         my $content = $response->content; 
    207         $content =~ s!/\*.*?\*/!!gs;    # strip all comments first 
    208         my @images = $content =~ 
    209           m/\b(?:url\(\s*)([a-zA-Z0-9_.-]+\.(?:gif|jpe?g|png))(?:\s*?\))/gi; 
    210         $filemgr->mkpath( File::Spec->catdir( $themeroot, $basename ) ) 
    211           or return $app->json_error( 
    212             $app->translate( 
    213 "Could not create [_1] folder - Check that your 'themes' folder is webserver-writable.", 
    214                 $basename 
    215             ) 
    216           ); 
    217         $filemgr->put_data( $response->content, 
    218             File::Spec->catfile( $themeroot, $basename, $basename . '.css' ) ); 
    219         if (($thumbnail_response->code >= 200) && ($thumbnail_response->code < 400)) { 
    220         $filemgr->put_data( $thumbnail_response->content, 
    221             File::Spec->catfile( $themeroot, $basename, "thumbnail.gif" ), 
    222             'upload' ); 
    223         } else { 
    224             return $app->json_error($app->translate("Error downloading image: [_1]", $new_url . 'thumbnail.gif')) 
    225         } 
    226         if (($thumbnail_large_response->code >= 200) && ($thumbnail_large_response->code < 400)) { 
    227             $filemgr->put_data( 
    228                 $thumbnail_large_response->content, 
    229                 File::Spec->catfile( $themeroot, $basename, "thumbnail-large.gif" ), 
    230                 'upload' 
    231             ); 
    232         } else { 
    233             return $app->json_error($app->translate("Error downloading image: [_1]", $new_url . 'thumbnail-large.gif')) 
    234         } 
    235  
    236        # Pick up the images we parsed earlier and write them to the theme folder 
    237         for my $image_url (@images) { 
    238             my $image_request = 
    239               HTTP::Request->new( GET => $new_url . $image_url ); 
    240             my $image_response = $user_agent->request($image_request); 
    241  
    242             my @image_url = split( /\//, $image_url ); 
    243             my $image_filename = $image_url[-1]; 
    244  
    245             if (($response->code >= 200) && ($response->code < 400)) { 
    246                 $filemgr->put_data( $image_response->content, 
    247                     File::Spec->catfile( $themeroot, $basename, $image_filename ), 
    248                     'upload' ) 
    249                   or return $app->json_error( $filemgr->errstr ); 
    250             } else { 
    251                 return $app->json_error($app->translate("Error downloading image: [_1]", $new_url . $image_url)); 
    252             } 
    253         } 
    254         $url = "$webthemeroot$basename/$basename.css"; 
    255     } 
    256      
     268    my $static_url = $app->static_path; 
     269    if ( $url !~ m{ \A \Q$static_url\E (?:support/)? themes/ }xms ) { 
     270        my $basename = download_theme($app, $url) 
     271            or return; 
     272        $url = "${static_url}support/themes/$basename/$basename.css"; 
     273    } 
     274 
     275    my $blog = MT->model('blog')->load($blog_id) 
     276      or return $app->json_error( $app->translate('No such blog [_1]', $blog_id) ); 
     277    my $blog_tset = $blog->template_set; 
     278    my $base_css_url = MT->registry('template_sets')->{$blog_tset}->{base_css}; 
     279 
     280    my $base_css = q{}; 
     281    if ($base_css_url) { 
     282        my $uri = URI->new_abs($base_css_url, $app->static_path); 
     283        $base_css = '@import url(' . $uri->as_string() . ');' 
     284            if $uri; 
     285    } 
    257286    my $blog = MT->model('blog')->load($blog_id)     
    258287      or return $app->json_error( $app->translate('No such blog [_1]', $blog_id) ); 
    259  
    260     my $r = MT->registry; 
    261     my $base_css = $r->{"template_sets"}{$blog->template_set}{"base_css"}; 
    262288 
    263289    # Replacing the theme import or adding a new one at the beginning 
    264290    my $template_text  = $tmpl->text(); 
    265291    my $replaced       = 0; 
    266     my $header = 
    267 '/* This is the StyleCatcher theme addition. Do not remove this block. */'; 
     292    my $header = '/* This is the StyleCatcher theme addition. Do not remove this block. */'; 
    268293    my $footer = '/* end StyleCatcher imports */'; 
    269     my $styles = $header . "\n"; 
    270     $styles .= "\@import url(".MT::Util::caturl($app->static_path, $base_css).");\n" if $base_css; 
    271     $styles .= "\@import url($url);\n"; 
    272     $styles .= $footer; 
    273     print STDERR "styles=$styles\n"; 
    274  
     294    my $styles = <<"EOT"; 
     295$header 
     296$base_css 
     297\@import url($url); 
     298$footer 
     299EOT 
    275300    if ($template_text =~ s/\Q$header\E.*\Q$footer\E/$styles/s) { 
    276301        $tmpl->text( $template_text ); 
     
    406431        $tmpl = new MT::Template; 
    407432        $tmpl->blog_id($blog_id); 
     433        $tmpl->name('Stylesheet'); 
     434        $tmpl->type('index'); 
    408435        $tmpl->identifier('styles'); 
    409436        $tmpl->outfile("styles.css"); 
     
    439466    if ( $type =~ m!^text/css! ) { 
    440467        $data->{auto}{url} = $url; 
    441         my $theme = fetch_theme( $url, ['collection:auto'] ); 
     468        my $theme = fetch_theme( 
     469            url  => $url, 
     470            tags => ['collection:auto'], 
     471        ); 
    442472        $data->{themes} = [$theme]; 
    443473    } 
     
    475505        my $themes = []; 
    476506        for my $repo_theme (@repo_themes) { 
    477             my $theme = fetch_theme( $repo_theme, [] ); 
     507            my $theme = fetch_theme( 
     508                url => $repo_theme, 
     509            ); 
    478510            push @$themes, $theme if $theme; 
    479511        } 
     
    547579        next unless -d $theme; 
    548580        $theme =~ s/.*[\\\/]//; 
    549         $themes->{$theme} = 
    550           fetch_theme( $theme_dir, ['collection:mt-designs'], $theme_url, 
    551             $theme_dir ); 
     581        $themes->{$theme} = fetch_theme( 
     582            url      => $theme_dir, 
     583            tags     => ['collection:mt-designs'], 
     584            baseurl  => $theme_url, 
     585            basepath => $theme_dir, 
     586        ); 
    552587        $themes->{$theme}{name} = $themes->{$theme}{name}; 
    553588        $themes->{$theme}{prefix} = 'default'; 
     
    564599        next unless -d $theme; 
    565600        $theme =~ s/.*[\\\/]//; 
    566         $themes->{$theme} = 
    567           fetch_theme( $theme_dir, ['collection:my-designs'] ); 
     601        $themes->{$theme} = fetch_theme( 
     602            url  => $theme_dir, 
     603            tags => ['collection:my-designs'], 
     604        ); 
    568605        $themes->{$theme}{prefix} = 'local'; 
    569606    } 
     
    579616sub fetch_theme { 
    580617    my $app = MT->app; 
    581     my ( $url, $tags, $baseurl, $basepath ) = @_; 
     618    my %param = @_; 
     619    my ($url, $tags, $baseurl, $basepath, $default_metadata) 
     620        = @param{qw( url tags baseurl basepath metadata )}; 
     621    $tags ||= []; 
    582622 
    583623    my $theme; 
     
    585625    my $new_url; 
    586626    my $themeroot; 
    587     if ( $url =~ m/^https?:/i ) { 
    588  
     627    my $url_is_web = $url =~ m{ \A https?: }xms ? 1 : 0; 
     628    if ($url_is_web) { 
    589629        # Pick up the css file 
    590630        my $user_agent  = $app->new_ua; 
     
    597637        $theme = $url; 
    598638        # discard any generic 'screen.css' filename 
    599         $theme =~ s!/screen.css$!!; 
     639        $theme =~ s{ / (?:screen|style) \.css \z }{}xms; 
    600640        $theme =~ s/.*[\\\/]//; 
    601641        my @url = split( /\//, $url ); 
     
    618658        } 
    619659        else { 
    620             $file = File::Spec->catfile( $url, "screen.css" ); 
     660            $file = File::Spec->catfile( $url, $theme, "screen.css" ); 
    621661            if ( -e $file ) { 
    622662                $stylesheet = file_mgr()->get_data($file); 
     
    664704    } 
    665705 
    666     my $thumbnail_link; 
    667     $thumbnail_link = $new_url . 'thumbnail.gif'; 
    668     my $thumbnail_large_link; 
    669     $thumbnail_large_link = $new_url . 'thumbnail-large.gif'; 
     706    my %thumbnails; 
     707    THUMB: for my $thumb (qw( thumbnail thumbnail_large )) { 
     708        $thumbnails{$thumb} = $metadata{$thumb}; 
     709        next THUMB if $thumbnails{$thumb}; 
     710 
     711        my $thumb_filename = $thumb; 
     712        $thumb_filename =~ tr/_/-/; 
     713        $thumb_filename .= '.gif'; 
     714 
     715        if ($url_is_web) { 
     716            my $thumb_url = $new_url . $thumb_filename; 
     717 
     718            my $user_agent  = $app->new_ua; 
     719            my $css_request = HTTP::Request->new( HEAD => $thumb_url ); 
     720            my $response    = $user_agent->request($css_request); 
     721            if ($response->is_success()) { 
     722                $thumbnails{$thumb} = $thumb_url; 
     723            } 
     724        } 
     725        else { 
     726            my $thumb_path = File::Spec->catfile($themeroot, $theme, 
     727                $thumb_filename); 
     728            if (-e $thumb_path) { 
     729                $thumbnails{$thumb} = $new_url . $thumb_filename; 
     730            } 
     731        } 
     732 
     733        $thumbnails{$thumb} ||= $app->static_path . 'plugins/StyleCatcher/' 
     734            . 'images/' . $thumb_filename; 
     735    } 
     736 
     737    my %field_map = ( 
     738        title        => [ 'name',         'theme name' ], 
     739        author       => [ 'designer',     'author' ], 
     740        author_url   => [ 'designer_url', 'author_url', 'author uri' ], 
     741        template_set => [ 'template_set', 'template' ], 
     742        description  => [ 'description' ], 
     743    ); 
     744    while (my ($best_name, $possible_names) = each %field_map) { 
     745        ($metadata{$best_name}) = grep { defined } 
     746            delete @metadata{ @$possible_names }, q{}; 
     747        $metadata{$best_name} = decode_html(remove_html($metadata{$best_name})); 
     748    } 
    670749 
    671750    require MT::Util; 
    672751    my $data = { 
    673         name        => $theme, 
    674         description => $metadata{description} || '', 
    675         title       => $metadata{name} || '(Untitled)', 
    676         url         => $url, 
    677         imageSmall  => $thumbnail_link, 
    678         imageBig    => $thumbnail_large_link, 
    679         author      => $metadata{designer} || $metadata{author} || '', 
    680         author_url  => $metadata{designer_url} || $metadata{author_url} || '', 
    681         author_affiliation => $metadata{author_affiliation} || '', 
    682         layouts            => $metadata{layouts} || '', 
    683         'sort'             => $metadata{name} || '', 
    684         tags               => $tags, 
    685         blogs              => [], 
     752        name         => $theme, 
     753        description  => $metadata{description} || q{}, 
     754        title        => $metadata{title} || '(Untitled)', 
     755        url          => $url, 
     756        imageSmall   => $thumbnails{thumbnail}, 
     757        imageBig     => $thumbnails{thumbnail_large}, 
     758        layouts      => $metadata{layouts} || q{}, 
     759        sort         => $metadata{name} || $theme || q{}, 
     760        tags         => $tags, 
     761        blogs        => [], 
     762        author       => $metadata{author}, 
     763        author_url   => $metadata{author_url}, 
     764        template_set => $metadata{template_set}, 
     765        author_affiliation => $metadata{author_affiliation} || q{}, 
    686766    }; 
    687767    $data; 
  • trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N/de.pm

    • Property svn:executable deleted
  • trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N/es.pm

    • Property svn:executable deleted
  • trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N/fr.pm

    • Property svn:executable deleted
  • trunk/StyleCatcher/plugins/StyleCatcher/lib/StyleCatcher/L10N/nl.pm

    • Property svn:executable deleted
  • trunk/StyleCatcher/plugins/StyleCatcher/tmpl/view.tmpl

    r1120 r1122  
    2929        "layout-wtt": "<__trans phrase="3-Columns, Wide, Thin, Thin" escape="js">", 
    3030        "layout-twt": "<__trans phrase="3-Columns, Thin, Wide, Thin" escape="js">", 
     31        "layout-ttw": "<__trans phrase="3-Columns, Thin, Thin, Wide" escape="js">", 
    3132        "layout-tw": "<__trans phrase="2-Columns, Thin, Wide" escape="js">", 
    3233        "layout-wt": "<__trans phrase="2-Columns, Wide, Thin" escape="js">", 
    3334        "layout-wm": "<__trans phrase="2-Columns, Wide, Medium" escape="js">", 
    34         "layout-mw": "<__trans phrase="2-Columns, Medium, Wide" escape="js">" 
     35        "layout-mw": "<__trans phrase="2-Columns, Medium, Wide" escape="js">", 
     36        "layout-w-b": "<__trans phrase="1-Column, Wide, Bottom" escape="js">" 
    3537    }; 
    3638 
     
    7678        mixer = new TC.Mixer(); 
    7779        // initialize mixer object 
    78         mixer.addSelectedDisplay( "display-details-content" ); 
     80        var display = mixer.addSelectedDisplay( "display-details-content" ); 
     81        display.entryProperties['template_set'] = 'Template Set'; 
    7982        mixer.onselect = selectDesign; 
    8083    } 
     
    225228        selected = mixer.name; 
    226229        var url = mixer.entries[mixer.name].url; 
     230        var tset = mixer.entries[mixer.name].template_set; 
    227231 
    228232        TC.addClassName(btn, "disabled-button"); 
     
    235239            'magic_token': '<mt:var name="magic_token">', 
    236240            'blog_id': blog_id, 
    237             'name': mixer.name 
     241            'name': mixer.name, 
     242            'template_set': tset 
    238243        }; 
    239244        if (layout)