add tagging support for article/globals images
authorTony Cook <tony@develop-help.com>
Fri, 22 Nov 2013 01:00:02 +0000 (12:00 +1100)
committerTony Cook <tony@develop-help.com>
Fri, 22 Nov 2013 01:00:02 +0000 (12:00 +1100)
site/cgi-bin/modules/BSE/Edit/Article.pm
site/cgi-bin/modules/BSE/TB/Image.pm
site/cgi-bin/modules/BSE/TB/Images.pm
site/cgi-bin/modules/BSE/TB/SiteCommon.pm
site/data/db/sql_statements.data
site/templates/admin/article_img.tmpl
site/templates/admin/image_edit.tmpl
t/050-local/020-article.t

index 0d44e29..392910f 100644 (file)
@@ -3518,7 +3518,16 @@ sub add_image {
                                    "You don't have access to add new images to this article");
 
   my $cgi = $req->cgi;
+
   my %errors;
+
+  my $save_tags = $cgi->param("_save_tags");
+  my @tags;
+  if ($save_tags) {
+    @tags = $cgi->param("tags");
+    $self->_validate_tags(\@tags, \%errors);
+  }
+
   my $imageobj =
     $self->do_add_image
       (
@@ -3536,6 +3545,11 @@ sub add_image {
   $imageobj
     or return $self->_service_error($req, $article, $articles, undef, \%errors);
 
+  if ($save_tags) {
+    my $error;
+    $imageobj->set_tags([ grep /\S/, @tags ], \$error);
+  }
+
   # typically a soft failure from the storage
   $errors{flash}
     and $req->flash($errors{flash});
@@ -3910,6 +3924,12 @@ sub req_save_image {
       $errors{image} = "No image file received";
     }
   }
+  my $save_tags = $cgi->param("_save_tags");
+  my @tags;
+  if ($save_tags) {
+    @tags = $cgi->param("tags");
+    $self->_validate_tags(\@tags, \%errors);
+  }
   if (keys %errors) {
     if ($req->want_json_response) {
       return $self->_service_error($req, $article, $articles, undef,
@@ -3923,6 +3943,10 @@ sub req_save_image {
   my $new_storage = $cgi->param('storage');
   defined $new_storage or $new_storage = $image->{storage};
   $image->save;
+  if ($save_tags) {
+    my $error;
+    $image->set_tags([ grep /\S/, @tags ], \$error);
+  }
   my $mgr = $self->_image_manager($req->cfg);
   if ($delete_file) {
     if ($old_storage ne 'local') {
index 568d4c5..f143455 100644 (file)
@@ -3,11 +3,12 @@ use strict;
 # represents an image from the database
 use Squirrel::Row;
 use BSE::ThumbCommon;
+use BSE::TB::TagOwner;
 use vars qw/@ISA/;
-@ISA = qw/Squirrel::Row BSE::ThumbCommon/;
+@ISA = qw/Squirrel::Row BSE::ThumbCommon BSE::TB::TagOwner/;
 use Carp qw(confess);
 
-our $VERSION = "1.006";
+our $VERSION = "1.007";
 
 sub columns {
   return qw/id articleId image alt width height url displayOrder name
@@ -72,6 +73,7 @@ sub json_data {
 
   my $data = $self->data_only;
   $data->{url} = $self->image_url;
+  $data->{tags} = [ $self->tags ];
 
   return $data;
 }
@@ -119,6 +121,7 @@ sub article {
 sub remove {
   my ($self) = @_;
 
+  $self->remove_tags;
   unlink $self->full_filename;
   return $self->SUPER::remove();
 }
@@ -278,4 +281,12 @@ sub update {
   return 1;
 }
 
+sub tag_owner_type {
+  "BI"
+}
+
+sub tableClass {
+  "BSE::TB::Images";
+}
+
 1;
index 0741949..b2d3e91 100644 (file)
@@ -1,11 +1,12 @@
 package BSE::TB::Images;
 use strict;
 use Squirrel::Table;
+require BSE::TB::TagOwners;
 use vars qw(@ISA $VERSION);
-@ISA = qw(Squirrel::Table);
+@ISA = qw(Squirrel::Table BSE::TB::TagOwners);
 use BSE::TB::Image;
 
-our $VERSION = "1.003";
+our $VERSION = "1.004";
 
 sub rowClass {
   return 'BSE::TB::Image';
index 1d6f136..b9e9274 100644 (file)
@@ -2,7 +2,7 @@ package BSE::TB::SiteCommon;
 use strict;
 use Carp qw(confess);
 
-our $VERSION = "1.016";
+our $VERSION = "1.017";
 
 =head1 NAME
 
@@ -171,6 +171,51 @@ sub images {
   return @{$self->{_images}};
 }
 
+=item image_tags
+
+Image tag information within the current article.
+
+=cut
+
+sub image_tags {
+  my ($self) = @_;
+
+  require BSE::TB::Tags;
+  require BSE::TB::TagMembers;
+  return
+    {
+     tags => [ BSE::TB::Tags->getSpecial(images => $self->id) ],
+     members => [ BSE::TB::TagMembers->getSpecial(images => $self->id) ],
+    };
+}
+
+=item images_tagged
+
+Return an arrayref of images for this article (or global images) that
+have the specified tags.
+
+In list context, return the result of collection_with_tags as the
+second parameter.
+
+=cut
+
+sub images_tagged {
+  my ($self, $tags) = @_;
+
+  require BSE::TB::Images;
+  my $result = BSE::TB::Images->collection_with_tags
+    (
+     "images",
+     $tags,
+     {
+      self => $self,
+     },
+    );
+
+  return $result->{objects} unless wantarray;
+  return ( $result->{objects}, $result );
+}
+
 =item image_by_name
 
 Return an image from the site or article given the image name.
index 727bcb6..d6befef 100644 (file)
@@ -1,5 +1,5 @@
 --
-# VERSION=1.005
+# VERSION=1.006
 name: bse_siteuserSeminarBookingsDetail
 sql_statement: <<SQL
 select ar.*, pr.*, se.*, ss.*, sb.*,
@@ -596,6 +596,25 @@ where t.id = m.tag_id
   )
 SQL
 
+name: Tags.images
+sql_statement: <<SQL
+select distinct t.*
+from bse_tags t, bse_tag_members m, image i
+where t.id = m.tag_id
+  and m.owner_type = 'BI'
+  and m.owner_id = i.id
+  and i.articleId = ?
+SQL
+
+name: TagMembers.images
+sql_statement: <<SQL
+select distinct m.*
+from bse_tag_members m, image i
+where m.owner_type = 'BI'
+  and m.owner_id = i.id
+  and i.articleId = ?
+SQL
+
 name: TagCategoryDeps.deleteCat
 sql_statement: <<SQL
 delete from bse_tag_category_deps
@@ -680,3 +699,4 @@ from bse_price_tiers t, bse_coupon_tiers c
 where c.coupon_id = ?
   and c.tier_id = t.id
 SQL
+
index 4aa7c92..e17b97b 100644 (file)
@@ -1,4 +1,4 @@
-<:wrap admin/base.tmpl title=>"Image Wizard" :>
+<:wrap admin/base.tmpl title=>"Image Wizard", js => "admin_edit.js" :>
 <h1><:ifEq [article id] "-1":>Global<:or:><: articleType :><:eif:> Image Wizard</h1>
 <:ifMessage:> 
 <p><b><:message:> </b></p>
             </td>
             <td class="help"><:help image name:> <:error_img name:></td>
           </tr>
+  <tr>
+    <th>Tags</th>
+    <td>
+      <input type="hidden" name="_save_tags" value="1" />
+      <div id="tags">
+      <:- .set tags = [ cgi.param("tags") ] :>
+      <:- .if tags.size == 0 :>
+        <:% tags.push("") :>
+      <:- .end if :>
+      <:.for tag in tags :>
+        <div class="tag"><input type="text" name="tags" value="<:= tag :>" /><:.call "error_img_n", "field":"tags", "index":loop.index :></div>
+      <:.end for:>
+      </div>
+    </td>
+    <td class="help"><:help edit tags:></td>
+  </tr>
           <tr> 
             <th>Storage:</th>
             <td> 
index 89eae22..a66ba68 100644 (file)
@@ -1,4 +1,4 @@
-<:wrap admin/base.tmpl title=>[concatenate "Edit " [articleType] " Image"]:>
+<:wrap admin/base.tmpl title=>[concatenate "Edit " [articleType] " Image"], js => "admin_edit.js" :>
 <h1>Edit <:articleType:> Image</h1>
 <:ifMessage:> 
 <p><b><:message:></b></p>
     <td><input type="text" name="name" value="<:old name eimage name:>" /></td>
     <td class="help"><:help image name:> <:error_img name:></td>
   </tr>
+  <tr>
+    <th>Tags</th>
+    <td>
+      <input type="hidden" name="_save_tags" value="1" />
+      <div id="tags">
+      <:.set tags = cgi.param("_save_tags") ? [ cgi.param("tags") ] : [ eimage.tags, "" ] -:>
+      <:.for tag in tags :>
+        <div class="tag"><input type="text" name="tags" value="<:= tag :>" /><:.call "error_img_n", "field":"tags", "index":loop.index :></div>
+      <:.end for:>
+      </div>
+    </td>
+    <td class="help"><:help edit tags:></td>
+  </tr>
   <tr> 
     <th>Storage:</th>
             <td> 
index 0c977b3..b1abb07 100644 (file)
@@ -1,6 +1,6 @@
 #!perl -w
 use strict;
-use Test::More tests => 12;
+use Test::More tests => 16;
 use BSE::Test ();
 use File::Spec;
 use BSE::Cfg;
@@ -68,7 +68,21 @@ EOS
     $art->set_expire($yesterday);
     ok($art->is_expired, "check true is expired");
 
-    $art->remove($cfg);
+    # add some images
+    my $im1 = BSE::API::bse_add_image($cfg, $art,
+                                     file => "t/data/t101.jpg");
+    $im1->set_tags([ "abc" ]);
+    ok($im1, "add first image");
+    my $im2 = BSE::API::bse_add_image($cfg, $art,
+                                     file => "t/data/govhouse.jpg");
+    ok($im2, "add second image");
+    my $tagged = $art->images_tagged([ "ABC" ]);
+    ok($tagged && @$tagged, "found a tagged image");
+    is($tagged->[0]->id, $im1->id, "found the right image");
+
+    END {
+      $art->remove($cfg);
+    }
   }
 }