summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordakkar <dakkar@luxion>2005-11-09 17:14:54 +0000
committerdakkar <dakkar@luxion>2005-11-09 17:14:54 +0000
commit27cff350e9e5fb832185bc14dee35b5b8f942a81 (patch)
treee89f9b5d457b711cce6d908ef0b33792cab20e75
parentora il BookmarksManager gestisce per bene i tag multipli, e i template sono f... (diff)
downloadBookmarks-27cff350e9e5fb832185bc14dee35b5b8f942a81.tar.gz
Bookmarks-27cff350e9e5fb832185bc14dee35b5b8f942a81.tar.bz2
Bookmarks-27cff350e9e5fb832185bc14dee35b5b8f942a81.zip
* passati i template a HTML4, altrimenti l'autocompletamento non va
* aggiunto autocompletamento per i nomi di tag * migliorato il caricatore da YAML * aggiunto un convertitore XBEL -> YAML * aggiunto campo 'tipo icona' * aggiunta funzionalità di edit e delete di link * dopo ogni update di un link, i tag non più riferiti vengono cancellati * migliorato il recupero favicon, con tipo
-rw-r--r--lib/Bookmarks.pm1
-rw-r--r--lib/Bookmarks/C/Main.pm92
-rw-r--r--lib/Bookmarks/M/DB/Tags.pm14
-rw-r--r--lib/Bookmarks/Utils.pm16
-rw-r--r--lib/Bookmarks/V/TT.pm12
-rw-r--r--root/add_form13
-rw-r--r--root/links6
-rw-r--r--root/tags3
-rwxr-xr-xscript/bookmarks_load.pl14
-rw-r--r--script/bookmarks_makedb.pl1
-rw-r--r--script/check_icons.pl39
-rw-r--r--script/xbel2yaml.pl77
12 files changed, 234 insertions, 54 deletions
diff --git a/lib/Bookmarks.pm b/lib/Bookmarks.pm
index fb88958..810a64f 100644
--- a/lib/Bookmarks.pm
+++ b/lib/Bookmarks.pm
@@ -2,6 +2,7 @@ package Bookmarks;
use strict;
use Catalyst qw/-Debug Prototype DefaultEnd/;
+use HTML::Element;
our $VERSION = '0.01';
diff --git a/lib/Bookmarks/C/Main.pm b/lib/Bookmarks/C/Main.pm
index b6170c0..d4c5a66 100644
--- a/lib/Bookmarks/C/Main.pm
+++ b/lib/Bookmarks/C/Main.pm
@@ -61,7 +61,7 @@ sub icon : Global {
my $link=Bookmarks::M::DB::Links->retrieve($c->req->param('link'));
my $icon=$link->get_icon();
if ($icon) {
- $c->res->content_type('image/x-icon');
+ $c->res->content_type($link->icon_type());
$c->res->body($icon);
}
else {
@@ -100,31 +100,41 @@ sub add : Global {
# POST: accept data and create link+tags
elsif ($c->req->method eq 'POST') {
my ($dblink)=Bookmarks::M::DB::Links->search({url=>$pre_link{url}});
- if (!defined $dblink) { # devo crearlo
- $dblink=Bookmarks::M::DB::Links->create({});
- $dblink->add_date(time());
- $dblink->access_count(0);
+
+ if (defined $dblink) {
+ Bookmarks::M::DB::LinksTags->search({
+ link => $dblink->pk()
+ })->delete_all();
+ }
+
+ if (defined $dblink and $c->req->param('delete')) {
+ $dblink->delete();
}
- $dblink->set(%pre_link);
- $dblink->set_icon(Bookmarks::Utils::get_site_icon($pre_link{url}));
- $dblink->update();
-
- # tags
- Bookmarks::M::DB::LinksTags->search({
- link => $dblink->pk()
- })->delete_all();
-
- for my $tagname (@tags) {
- my $dbtag=Bookmarks::M::DB::Tags->find_or_create({
- name => $tagname,
- });
-
- Bookmarks::M::DB::LinksTags->find_or_create({
- tag => $dbtag->pk(),
- link => $dblink->pk(),
- });
+ else {
+ if (!defined $dblink) { # devo crearlo
+ $dblink=Bookmarks::M::DB::Links->create({});
+ $dblink->add_date(time());
+ $dblink->access_count(0);
+ }
+
+ $dblink->set(%pre_link);
+ $dblink->set_icon(Bookmarks::Utils::get_site_icon($pre_link{url}));
+ $dblink->update();
+
+ for my $tagname (@tags) {
+ my $dbtag=Bookmarks::M::DB::Tags->find_or_create({
+ name => $tagname,
+ });
+
+ Bookmarks::M::DB::LinksTags->find_or_create({
+ tag => $dbtag->pk(),
+ link => $dblink->pk(),
+ });
+ }
}
+ Bookmarks::M::DB::Tags->cleanup();
+
if ($c->req->param('close')) {
$c->stash->{template}='closewin';
}
@@ -134,6 +144,28 @@ sub add : Global {
}
}
+sub edit : Global {
+ my ( $self, $c ) = @_;
+
+ my $link=Bookmarks::M::DB::Links->retrieve($c->req->param('link'));
+
+ $c->stash->{link}=$link;
+ $c->stash->{tags}=[ map {$_->name()} $link->tags() ];
+ $c->stash->{mode}='edit';
+ $c->stash->{template}='add_form';
+}
+
+sub complete_tag : Global {
+ my ( $self, $c ) = @_;
+
+ my $pretag=$c->req->param('tag');
+
+ my @tags=map { $_->name() }
+ Bookmarks::M::DB::Tags->search_like({name => "${pretag}%"});
+
+ $c->res->body($c->prototype->auto_complete_result(\@tags));
+}
+
=back
@@ -202,6 +234,13 @@ sub link {
return $uri->as_string();
}
+sub edit_link {
+ my ($self, $link)=@_;
+ my $uri=URI->new($self->{base} . 'edit');
+ $uri->query_form(link=>$link->pk());
+ return $uri->as_string();
+}
+
sub add_action {
my ($self)=@_;
return URI->new(
@@ -209,4 +248,11 @@ sub add_action {
)->as_string();
}
+sub tag_autocomplete {
+ my ($self)=@_;
+ return URI->new(
+ $self->{base} . 'complete_tag'
+ )->as_string();
+}
+
1;
diff --git a/lib/Bookmarks/M/DB/Tags.pm b/lib/Bookmarks/M/DB/Tags.pm
index 3686a7d..cc675f7 100644
--- a/lib/Bookmarks/M/DB/Tags.pm
+++ b/lib/Bookmarks/M/DB/Tags.pm
@@ -22,7 +22,7 @@ GROUP BY links_tags.tag
ORDER BY how_many DESC
END_SQL
-__PACKAGE__->columns(TEMP=> 'how_wany');
+__PACKAGE__->columns(TEMP=> 'how_many');
sub count_links {
my ($self)=@_;
@@ -52,6 +52,18 @@ sub ordered_links {
return sort links_sorter @links;
}
+sub cleanup {
+ my ($class)=@_;
+
+ my @tag_list=reverse $class->search_popularity();
+
+ while ($tag_list[0]->how_many() == 0) {
+ (shift @tag_list)->delete();
+ }
+
+ return;
+}
+
=head1 NAME
Bookmarks::M::DB::Tags - CDBI Model Component Table Class
diff --git a/lib/Bookmarks/Utils.pm b/lib/Bookmarks/Utils.pm
index fd0b68d..a876340 100644
--- a/lib/Bookmarks/Utils.pm
+++ b/lib/Bookmarks/Utils.pm
@@ -1,15 +1,17 @@
package Bookmarks::Utils;
use strict;
use warnings;
-use LWP::Simple;
+use LWP::UserAgent;
use URI::URL;
+my $ua=LWP::UserAgent->new();
+
sub check_link {
my ($url)=@_;
return 1 if $url!~/^http:/;
#my ($type,$length,$update,$expires,$server)=head($url);
#return defined $type;
- return scalar head($url);
+ return $ua->head($url)->is_success();
}
sub get_site_icon {
@@ -38,8 +40,14 @@ sub get_site_icon {
print "Trovato: '$favicon'";
$favicon=URI::URL->new($favicon,$url)->abs->canonical->as_string;
print ", ovvero '$favicon'\n";
- my $icon=get($favicon);
- return $icon;
+ my $res=$ua->get($favicon);
+
+ if ($res->is_success()) {
+ return ($res->decoded_content(),$res->header('Content-type'));
+ }
+ else {
+ return;
+ }
}
1;
diff --git a/lib/Bookmarks/V/TT.pm b/lib/Bookmarks/V/TT.pm
index f2f8e7d..d2063b6 100644
--- a/lib/Bookmarks/V/TT.pm
+++ b/lib/Bookmarks/V/TT.pm
@@ -3,18 +3,6 @@ package Bookmarks::V::TT;
use strict;
use base 'Catalyst::View::TT';
-sub process {
- my ( $self, $c ) = @_;
- my $ret=$self->NEXT::process($c);
- if ($ret==1
- and $c->res->content_type =~ m{text/html}) {
- my $ct=$c->res->content_type;
- $ct=~s{text/html}{application/xhtml+xml};
- $c->res->content_type($ct);
- }
- return $ret;
-}
-
=head1 NAME
Bookmarks::V::TT - TT View Component
diff --git a/root/add_form b/root/add_form
index 10e83bb..ce0d181 100644
--- a/root/add_form
+++ b/root/add_form
@@ -1,15 +1,18 @@
-<?xml version="1.0" encoding="utf-8"?>
-<html xmlns="http://www.w3.org/1999/xhtml">
+<html>
<head>
-<title>add</title>
+<title>[% IF mode=='edit'; 'Edit link'; ELSE; 'Add link'; END %]</title>
+[% c.prototype.auto_complete_stylesheet() %]
+[% c.prototype.define_javascript_functions() %]
</head>
<body>
<form action="[% href.add_action() %]" method="post">
<p>Link: <input name="url" type="text" value="[% link.url %]" /></p>
<p>Title: <input name="title" type="text" value="[% link.title %]" /></p>
<p>Description: <input name="descr" type="text" value="[% link.descr %]" /></p>
-<p>Tags: <input name="tag" type="text" value="[% tags.join(' ') %]" /></p>
-<input type="submit" />
+<p>Tags: <input autocomplete="off" id="tag_field" name="tag" type="text" value="[% tags.join(' ') %]" /></p>
+<div id="tag_field_auto_complete" class="auto_complete"></div>
+<script type="text/javascript">new Ajax.Autocompleter('tag_field', 'tag_field_auto_complete', '[% href.tag_autocomplete() %]', { tokens: ' ' })</script>
+<input type="submit" name="add" value="Submit" /> [% IF mode=='edit' %]<input type="submit" name="delete" value="Delete" />[% END %]
</form>
</body>
</html> \ No newline at end of file
diff --git a/root/links b/root/links
index 210a7e9..a23eaff 100644
--- a/root/links
+++ b/root/links
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<html xmlns="http://www.w3.org/1999/xhtml">
+<html>
<head>
<title>
Links for
@@ -51,6 +50,9 @@
<span class="link title">
<a href="[% href.link(link) %]">»[% link.title %]«</a>
</span>
+ <span class="link edit">
+ <a href="[% href.edit_link(link) %]">edit</a>
+ </span>
<ul>
[% FOR rtag IN link.tags %]
<li>
diff --git a/root/tags b/root/tags
index 888f50e..2df62e5 100644
--- a/root/tags
+++ b/root/tags
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<html xmlns="http://www.w3.org/1999/xhtml">
+<html>
<head>
<title>tags</title>
</head>
diff --git a/script/bookmarks_load.pl b/script/bookmarks_load.pl
index 7b16fa1..6433f24 100755
--- a/script/bookmarks_load.pl
+++ b/script/bookmarks_load.pl
@@ -30,16 +30,20 @@ for my $link (@$links) {
my $dblink=Bookmarks::M::DB::Links->find_or_create({
url => $link->{href},
});
- if (!Bookmarks::Utils::check_link($link->{href})) {
- warn "Link $link->{href} non valido, marco come tale\n";
- $link->{description}.=' [INVALID]';
- }
+ if (!Bookmarks::Utils::check_link($link->{href})) {
+ warn "Link $link->{href} non valido, marco come tale\n";
+ $link->{description}.=' [INVALID]';
+ }
+ else {
+ my ($icon,$type)=Bookmarks::Utils::get_site_icon($link->{href});
+ $dblink->set_icon($icon);
+ $dblink->icon_type($type);
+ }
$link->{created}||=time();
$link->{modified}||=time();
while (my ($f1,$f2) = each %fields) {
$dblink->$f2($link->{$f1});
}
- $dblink->set_icon(Bookmarks::Utils::get_site_icon($link->{href}));
$dblink->update();
Bookmarks::M::DB::LinksTags->search({link => $dblink->pk()})->delete_all();
diff --git a/script/bookmarks_makedb.pl b/script/bookmarks_makedb.pl
index 7b3ee1c..991cdd6 100644
--- a/script/bookmarks_makedb.pl
+++ b/script/bookmarks_makedb.pl
@@ -28,6 +28,7 @@ create table links (
title text,
descr text,
icon text,
+ icon_type text,
add_date integer,
last_access_date integer,
access_count integer
diff --git a/script/check_icons.pl b/script/check_icons.pl
new file mode 100644
index 0000000..2afdc7d
--- /dev/null
+++ b/script/check_icons.pl
@@ -0,0 +1,39 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use FindBin;
+use DBI;
+use MIME::Base64;
+use File::MMagic;
+use Path::Class;
+
+my $DBHOME=dir($FindBin::Bin)->parent->file('bookmarks.db');
+my $db=DBI->connect("dbi:SQLite:$DBHOME");
+
+my $magic=File::MMagic->new();
+
+my $sth=$db->prepare('select pk,icon from links');
+$sth->execute();
+my ($pk,$icon,$type);
+my @to_clean=();my %to_update;
+while (($pk,$icon)=$sth->fetchrow_array()) {
+ $icon=decode_base64($icon);
+ $type=$magic->checktype_contents($icon);
+ if ($type =~ /^text/) {
+ push @to_clean,$pk;
+ }
+ else {
+ $to_update{$pk}=$type;
+ }
+}
+
+$sth=$db->prepare(q{update links set icon='' where pk=?});
+for $pk (@to_clean) {
+ $sth->execute($pk);
+}
+$sth=$db->prepare(q{update links set icon_type=? where pk=?});
+while (($pk,$type)=each %to_update) {
+ $sth->execute($type,$pk);
+}
+
+$db->disconnect;
diff --git a/script/xbel2yaml.pl b/script/xbel2yaml.pl
new file mode 100644
index 0000000..6cfb186
--- /dev/null
+++ b/script/xbel2yaml.pl
@@ -0,0 +1,77 @@
+#!/usr/bin/perl
+use XML::SAX::ParserFactory;
+use YAML;
+
+my $handler=XBEL::Handler->new();
+my $parser=XML::SAX::ParserFactory->parser(Handler=>$handler);
+$parser->parse_uri($ARGV[0]);
+
+print Dump($handler->bookmarks());
+
+package XBEL::Handler;
+use base 'XML::SAX::Base';
+use Date::Parse;
+
+sub new {
+ my ($class)=@_;
+ return bless +{
+ bookmarks=>[],
+ status=>'out',
+ tags=>[],
+ },$class;
+}
+
+sub start_element {
+ my ($self,$el)=@_;
+
+ if ($el->{LocalName} eq 'folder') {
+ $self->{status}='folder';
+ push @{$self->{tags}},'';
+ }
+ elsif ($el->{LocalName} eq 'bookmark') {
+ $self->{status}='mark';
+ my $mark={};
+ $mark->{href}=$el->{Attributes}{'{}href'}{Value};
+ $mark->{created}=convert_date($el->{Attributes}{'{}added'}{Value});
+ $mark->{modified}=convert_date($el->{Attributes}{'{}modified'}{Value});
+ $mark->{tags}=[@{$self->{tags}}]; # force a copy
+ push @{$self->{bookmarks}},$mark;
+ }
+ elsif ($el->{LocalName} eq 'title' and $self->{status} eq 'folder') {
+ $self->{status}='folder-title';
+ }
+ elsif ($el->{LocalName} eq 'title' and $self->{status} eq 'mark') {
+ $self->{status}='mark-title';
+ }
+}
+
+sub end_element {
+ my ($self,$el)=@_;
+
+ if ($el->{LocalName} eq 'folder') {
+ pop @{$self->{tags}};
+ }
+ $self->{status}='';
+}
+
+sub characters {
+ my ($self,$data)=@_;
+
+ if ($self->{status} eq 'mark-title') {
+ $self->{bookmarks}[-1]{description}.=$data->{Data};
+ }
+ elsif ($self->{status} eq 'folder-title') {
+ $self->{tags}[-1].=$data->{Data};
+ }
+}
+
+sub convert_date {
+ return str2time($_[0]);
+}
+
+sub bookmarks {
+ my ($self)=@_;
+ return $self->{bookmarks};
+}
+
+1;