Changeset 1016


Ignore:
Timestamp:
Apr 4, 2007, 8:44:34 PM (15 years ago)
Author:
kake
Message:

Move node RDF generation from inline strings in OpenGuides::RDF to its own template; also make sure all weird characters are encoded.

Location:
trunk
Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Build.PL

    r1015 r1016  
    288288        'File::Temp'                          => 0,
    289289        'Geography::NationalGrid'             => 0,
     290        'HTML::Entities'                      => 0,
    290291        'LWP::Simple'                         => 0,
    291292        'Parse::RecDescent'                   => 0,
     
    356357                      "node_image_fields.tt",
    357358                      "node_photo_notes.tt",
     359                      "node_rdf.tt",
    358360                      "openguides_information_boxes.tt",
    359361                      "preferences.tt",
  • trunk/Changes

    r1015 r1016  
    55
    660.60
     7        Move node RDF generation from inline to node_rdf.tt and replace
     8          home-grown escaping with encode_entities_numeric from HTML::Entities
     9          (technically this is an added dependency, but we already require
     10          the package it comes in, via Wiki::Toolkit::Formatter::UseMod).
    711        Move random page functionality from wiki.cgi into OpenGuides.pm and
    812          add some tests.
  • trunk/MANIFEST

    r1014 r1016  
    6363templates/node_image_fields.tt
    6464templates/node_photo_notes.tt
     65templates/node_rdf.tt
    6566templates/openguides_information_boxes.tt
    6667templates/plain_index.tt
  • trunk/PREREQUISITES

    r974 r1016  
    3434  Geo::Coordinates::UTM
    3535)
     36HTML::Entities
    3637LWP::Simple
    3738Module::Build (version 0.18 or later)
  • trunk/lib/OpenGuides/RDF.pm

    r888 r1016  
    99use URI::Escape;
    1010use Carp 'croak';
     11use HTML::Entities qw( encode_entities_numeric );
     12use Template;
    1113
    1214sub new {
     
    5961
    6062    my $node_name = $args{node};
     63    my $config = $self->{config};
    6164    my $wiki = $self->{wiki};
    62 
    63     my %node_data          = $wiki->retrieve_node( $node_name );
    64     my $phone              = $node_data{metadata}{phone}[0]              || '';
    65     my $fax                = $node_data{metadata}{fax}[0]                || '';
    66     my $website            = $node_data{metadata}{website}[0]            || '';
    67     my $opening_hours_text = $node_data{metadata}{opening_hours_text}[0] || '';
    68     my $address            = $node_data{metadata}{address}[0]            || '';
    69     my $postcode           = $node_data{metadata}{postcode}[0]           || '';
    70     my $city               = $node_data{metadata}{city}[0]               || $self->{default_city};
    71     my $country            = $node_data{metadata}{country}[0]            || $self->{default_country};
    72     my $latitude           = $node_data{metadata}{latitude}[0]           || '';
    73     my $longitude          = $node_data{metadata}{longitude}[0]          || '';
    74     my $version            = $node_data{version};
    75     my $username           = $node_data{metadata}{username}[0]           || '';
    76     my $os_x               = $node_data{metadata}{os_x}[0]               || '';
    77     my $os_y               = $node_data{metadata}{os_y}[0]               || '';
    78     my @categories         = @{ $node_data{metadata}{category} || [] };
    79     my @locales            = @{ $node_data{metadata}{locale} || [] };
    80     my $summary            = $node_data{metadata}{summary}[0]            || '';
    81 
    82     # replace any errant characters in data to prevent illegal XML
    83     foreach ($phone, $fax, $website, $opening_hours_text, $address, $postcode,
    84              $city, $country, $latitude, $longitude, $version, $os_x, $os_y,
    85              @categories, @locales, $summary)
    86     {
    87       if ($_)
    88       {
    89         $_ =~ s/&/&/g;
    90         $_ =~ s/</&lt;/g;
    91         $_ =~ s/>/&gt;/g;
    92       }
    93     }
    94    
    95     my ($is_geospatial, $objType);
    96 
    97     if ($os_x || $os_y || $latitude || $longitude || $address || $postcode || @locales || $opening_hours_text) {
    98         $is_geospatial = 1;
    99         $objType    = 'geo:SpatialThing';
    100     } else {
    101         $objType = 'rdf:Description';
    102     }
    103 
     65    my $formatter = $wiki->formatter;
     66
     67    my %node_data = $wiki->retrieve_node( $node_name );
     68    my %metadata = %{ $node_data{metadata} };
     69    my %tt_vars = (
     70                    node_name  => $node_name,
     71                    version    => $node_data{version},
     72                    site_name  => $self->{site_name},
     73                    site_desc  => $self->{site_description},
     74                    og_version => $self->{og_version},
     75                  );
     76
     77    my %defaults = (
     78                     city => $self->{default_city},
     79                     country => $self->{default_country},
     80                   );
     81
     82    foreach my $var ( qw( phone fax website opening_hours_text address
     83                          postcode city country latitude longitude username
     84                          os_x os_y summary ) ) {
     85        my $val = $metadata{$var}[0] || $defaults{$var} || "";
     86        $tt_vars{$var} = $val;
     87    }
     88
     89   
     90    my @cats = @{ $metadata{category} || [] };
     91    @cats = map { { name => $_ } } @cats;
     92    $tt_vars{categories} = \@cats;
     93
     94    my @locs = @{ $metadata{locale} || [] };
     95    @locs = map {
     96                  {
     97                    name => $_,
     98                    id   => $formatter->node_name_to_node_param( $_ ),
     99                  }
     100                } @locs;
     101    $tt_vars{locales} = \@locs;
     102
     103    # Check for geospatialness and define container object as appropriate.
     104    my $is_geospatial;
     105    foreach my $var ( qw( os_x os_y latitude longitude address postcode
     106                          opening_hours_text ) ) {
     107        $is_geospatial = 1 if $tt_vars{$var};
     108    }
     109
     110    $is_geospatial = 1 if scalar @locs;
     111
     112    $tt_vars{obj_type} = $is_geospatial ? "geo:SpatialThing"
     113                                        : "rdf:Description";
     114    $tt_vars{is_geospatial} = $is_geospatial;
     115
     116    # Timestamp of last edited.
    104117    my $timestamp = $node_data{last_modified};
    105    
    106     # Make a Time::Piece object.
    107     my $timestamp_fmt = $Wiki::Toolkit::Store::Database::timestamp_fmt;
    108 
    109118    if ( $timestamp ) {
     119        # Make a Time::Piece object in order to canonicalise time.  I think.
     120        my $timestamp_fmt = $Wiki::Toolkit::Store::Database::timestamp_fmt;
    110121        my $time   = Time::Piece->strptime($timestamp, $timestamp_fmt);
    111         $timestamp = $time->strftime("%Y-%m-%dT%H:%M:%S");
    112     }
    113 
    114     my $user_id = $username;
    115     $user_id =~ s/ /_/g;
    116    
    117     my $url               = $self->{make_node_url}->( $node_name, $version );
    118     my $version_indpt_url = $self->{make_node_url}->( $node_name );
    119     my $rdf = qq{<?xml version="1.0"?>
    120 <rdf:RDF
    121   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    122   xmlns:dc="http://purl.org/dc/elements/1.1/"
    123   xmlns:dcterms="http://purl.org/dc/terms/"
    124   xmlns:foaf="http://xmlns.com/foaf/0.1/"
    125   xmlns:wiki="http://purl.org/rss/1.0/modules/wiki/"
    126   xmlns:chefmoz="http://chefmoz.org/rdf/elements/1.0/"
    127   xmlns:wn="http://xmlns.com/wordnet/1.6/"
    128   xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
    129   xmlns:os="http://downlode.org/rdf/os/0.1/"
    130   xmlns:owl="http://www.w3.org/2002/07/owl#"
    131   xmlns="http://www.w3.org/2000/10/swap/pim/contact#"
    132 >
    133 
    134   <rdf:Description rdf:about="">
    135     <dc:title>} . $self->{site_name} . qq{: $node_name</dc:title>
    136     <dc:date>$timestamp</dc:date>
    137     <dcterms:modified>$timestamp</dcterms:modified>
    138 
    139     <dc:contributor>
    140       <foaf:Person rdf:ID="$user_id">
    141         <foaf:nick>$username</foaf:nick>
    142       </foaf:Person>
    143     </dc:contributor>
    144 
    145     <dc:source rdf:resource="$version_indpt_url" />
    146     <wiki:version>$version</wiki:version>
    147     <foaf:topic rdf:resource="#obj" />
    148   </rdf:Description>
    149 
    150   <$objType rdf:ID="obj" dc:title="$node_name">
    151 };
    152     $rdf .= "    <dc:description>$summary</dc:description>\n" if $summary;
    153 
    154     $rdf .= "\n    <!-- categories -->\n\n" if @categories;
    155     $rdf .= "    <dc:subject>$_</dc:subject>\n" foreach @categories;
    156    
    157     if ($is_geospatial)
    158     {
    159       $rdf .= "\n    <!-- address and geospatial data -->\n\n";
    160       $rdf .= "    <address>$address</address>\n"        if $address;
    161       $rdf .= "    <city>$city</city>\n"                 if $city;
    162       $rdf .= "    <postalCode>$postcode</postalCode>\n" if $postcode;
    163       $rdf .= "    <country>$country</country>\n"        if $country;
    164 
    165     foreach (@locales)
    166     {
    167       my $locale_id = $_;
    168       $locale_id =~ s/ /_/g;
    169    
    170       $rdf .= qq{
    171     <foaf:based_near>
    172       <wn:Neighborhood rdf:ID="$locale_id">
    173         <dc:title>$_</dc:title>
    174       </wn:Neighborhood>
    175     </foaf:based_near>\n};
    176     }
    177    
    178       if ( $latitude && $longitude ) {
    179           $rdf .= qq{
    180     <geo:lat>$latitude</geo:lat>
    181     <geo:long>$longitude</geo:long>\n};
    182       }
    183 
    184       if ( $os_x && $os_y ) {
    185           $rdf .= qq{
    186     <os:x>$os_x</os:x>
    187     <os:y>$os_y</os:y>};
    188       }
    189     }
    190    
    191     $rdf .= "\n\n    <!-- contact information -->\n\n" if ($phone || $fax || $website || $opening_hours_text);
    192     $rdf .= "    <phone>$phone</phone>\n"                              if $phone;
    193     $rdf .= "    <fax>$fax</fax>\n"                                    if $fax;
    194     $rdf .= "    <foaf:homepage rdf:resource=\"$website\" />\n"        if $website;
    195     $rdf .= "    <chefmoz:Hours>$opening_hours_text</chefmoz:Hours>\n" if $opening_hours_text;
    196 
    197     if ($node_data{content} =~ /^\#REDIRECT \[\[(.*?)]\]$/)
    198     {
    199       my $redirect = $1;
    200      
    201       $rdf .= qq{    <owl:sameAs rdf:resource="} . $self->{config}->script_url
    202       . uri_escape($self->{config}->script_name) . '?id='
    203       . uri_escape($wiki->formatter->node_name_to_node_param($redirect))
    204       . ';format=rdf#obj';
    205       $rdf .= qq{" />\n};
    206     }
    207    
    208     $rdf .= qq{  </$objType>
    209 </rdf:RDF>
    210 
    211 };
    212 
     122        $tt_vars{timestamp} = $time->strftime("%Y-%m-%dT%H:%M:%S");
     123    }
     124
     125    $tt_vars{user_id} = $tt_vars{username};
     126    $tt_vars{user_id} =~ s/\s/_/g;
     127   
     128    $tt_vars{node_uri} = $self->{make_node_url}->( $node_name );
     129    $tt_vars{node_uri_with_version}
     130                            = $self->{make_node_url}->( $node_name,
     131                                                        $tt_vars{version} );
     132
     133    # Should probably be moved into OpenGuides::Utils.
     134    if ($node_data{content} =~ /^\#REDIRECT \[\[(.*?)]\]$/) {
     135        my $redirect = $1;
     136        $tt_vars{redirect} = $config->script_url . $config->script_name
     137                             . "?id="
     138                             . $formatter->node_name_to_node_param( $redirect )
     139                             . ";format=rdf#obj";
     140    }
     141
     142    # Escape stuff!
     143    foreach my $var ( keys %tt_vars ) {
     144        if ( $tt_vars{$var} ) {
     145            $tt_vars{$var} = encode_entities_numeric( $tt_vars{$var} );
     146        }
     147    }
     148
     149    # OK, we've set all our template variables; now process the template.
     150    my $template_path = $config->template_path;
     151    my $custom_template_path = $config->custom_template_path || "";
     152    my $tt = Template->new( {
     153                    INCLUDE_PATH => "$custom_template_path:$template_path" } );
     154
     155    my $rdf;
     156    $tt->process( "node_rdf.tt", \%tt_vars, \$rdf );
     157    $rdf ||= "ERROR: " . $tt->error;
    213158    return $rdf;
    214159}
  • trunk/t/21_rdf.t

    r957 r1016  
    1919
    2020Wiki::Toolkit::Setup::SQLite::setup( { dbname => "t/node.db" } );
    21 my $config = OpenGuides::Config->new(
    22     vars => {
    23                 dbtype             => "sqlite",
    24                 dbname             => "t/node.db",
    25                 indexing_directory => "t/indexes",
    26                 script_url         => "http://wiki.example.com/",
    27                 script_name        => "mywiki.cgi",
    28                 site_name          => "Wiki::Toolkit Test Site",
    29                 default_city       => "London",
    30                 default_country    => "United Kingdom",
    31             }
    32 );
     21my $config = OpenGuides::Test->make_basic_config;
     22$config->script_url( "http://wiki.example.com/" );
     23$config->script_name( "mywiki.cgi" );
     24$config->site_name( "Wiki::Toolkit Test Site" );
     25$config->default_city( "London" );
     26$config->default_country( "United Kingdom" );
     27
    3328eval { require Wiki::Toolkit::Search::Plucene; };
    3429if ( $@ ) { $config->use_plucene ( 0 ) };
Note: See TracChangeset for help on using the changeset viewer.