Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: tonycoz/bse
base: 343e1a9990
...
head fork: tonycoz/bse
compare: c284ccb458
  • 4 commits
  • 15 files changed
  • 0 commit comments
  • 1 contributor
View
73 site/cgi-bin/modules/BSE/Edit/Article.pm
@@ -16,7 +16,7 @@ use List::Util qw(first);
use constant MAX_FILE_DISPLAYNAME_LENGTH => 255;
use constant ARTICLE_CUSTOM_FIELDS_CFG => "article custom fields";
-our $VERSION = "1.043";
+our $VERSION = "1.045";
=head1 NAME
@@ -1758,6 +1758,27 @@ sub save_columns {
return @columns;
}
+sub _validate_tags {
+ my ($self, $tags, $errors) = @_;
+
+ my $fail = 0;
+ my @errors;
+ for my $tag (@$tags) {
+ my $error;
+ if ($tag =~ /\S/
+ && !BSE::TB::Tags->valid_name($tag, \$error)) {
+ push @errors, "msg:bse/admin/edit/tags/invalid/$error";
+ $errors->{tags} = \@errors;
+ ++$fail;
+ }
+ else {
+ push @errors, undef;
+ }
+ }
+
+ return $fail;
+}
+
sub save_new {
my ($self, $req, $article, $articles) = @_;
@@ -1788,15 +1809,8 @@ sub save_new {
my $save_tags = $cgi->param("_save_tags");
my @tags;
if ($save_tags) {
- @tags = grep /\S/, $cgi->param("tags");
- my $error;
- for my $tag (@tags) {
- BSE::TB::Tags->valid_name($tag, \$error)
- or last;
- }
- if ($error) {
- $errors{tags} = "msg:bse/admin/edit/badtag/$error";
- }
+ @tags = $cgi->param("tags");
+ $self->_validate_tags(\@tags, \%errors);
}
if (keys %errors) {
@@ -1949,7 +1963,7 @@ sub save_new {
if ($save_tags) {
my $error;
- $article->set_tags(\@tags, \$error);
+ $article->set_tags([ grep /\S/, @tags ], \$error);
}
generate_article($articles, $article) if $Constants::AUTO_GENERATE;
@@ -2123,15 +2137,8 @@ sub save {
my $save_tags = $cgi->param("_save_tags");
my @tags;
if ($save_tags) {
- @tags = grep /\S/, $cgi->param("tags");
- my $error;
- for my $tag (@tags) {
- BSE::TB::Tags->valid_name($tag, \$error)
- or last;
- }
- if ($error) {
- $errors{tags} = "msg:bse/admin/edit/badtag/$error";
- }
+ @tags = $cgi->param("tags");
+ $self->_validate_tags(\@tags, \%errors);
}
$self->validate_old($article, \%data, $articles, \%errors, scalar $req->is_ajax)
or return $self->_service_error($req, $article, $articles, undef, \%errors, "FIELD");
@@ -2233,7 +2240,7 @@ sub save {
if ($save_tags) {
my $error;
- $article->set_tags(\@tags, \$error);
+ $article->set_tags([ grep /\S/, @tags ], \$error);
}
# fix the kids too
@@ -3511,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
(
@@ -3529,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});
@@ -3903,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,
@@ -3916,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') {
View
13 site/cgi-bin/modules/BSE/ImageHandler/Img.pm
@@ -4,7 +4,7 @@ use base 'BSE::ImageHandler::Base';
use Carp qw(confess);
use BSE::Util::HTML;
-our $VERSION = "1.004";
+our $VERSION = "1.005";
sub format {
my ($self, %opts) = @_;
@@ -167,9 +167,14 @@ sub thumb {
or return escape_html($error);
if ($field) {
- my $value = $imwork->{$field};
- defined $value or $value = '';
- return escape_html($value);
+ if ($field eq "object") {
+ return $imwork;
+ }
+ else {
+ my $value = $imwork->{$field};
+ defined $value or $value = '';
+ return escape_html($value);
+ }
}
else {
my $class = $cfg->entry('thumb classes', $geo_id, "bse_image_thumb");
View
209 site/cgi-bin/modules/BSE/TB/Image.pm
@@ -3,11 +3,84 @@ 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.008";
+
+=head1 NAME
+
+BSE::TB::Image - images attached to an article or a global image.
+
+=head1 SYNOPSIS
+
+ my @images = $article->images;
+
+=head1 DESCRIPTION
+
+X<images>This class represents an image attached to an article, or a
+global image.
+
+=head1 METHODS
+
+=over
+
+=item id
+
+Unique id for this image.
+
+=item articleId
+
+article this image belongs to. C<-1> for global images.
+
+=item image
+
+image filename as stored in the images directory. See C</image_url>
+to get a URL to the image.
+
+=item alt
+
+alternate text for the image
+
+=item width
+
+=item height
+
+X<image, width>X<image, height>width and height of the
+image in pixels.
+
+=item url
+
+url to link to when the image is inlined.
+
+=item displayOrder
+
+sort key for ordering images belonging to an article (or within the
+global image collection.)
+
+=item name
+
+unique name for the image within the images belonging to an article
+(or withing the global image collection.) Can be an empty string.
+
+=item storage
+
+the external storage used for the image, or C<local> for locally
+stored images.
+
+=item src
+
+for externally stored images, the URL to the image. Use
+C</image_url()>.
+
+=item ftype
+
+the type of image, either C<img> for normal images, or C<flash> for
+flash files.
+
+=cut
sub columns {
return qw/id articleId image alt width height url displayOrder name
@@ -16,6 +89,28 @@ sub columns {
sub table { "image" }
+=item formatted(...)
+
+Call the format() image handler object for this image.
+
+Accepts the following parameters:
+
+=over
+
+=item *
+
+C<align> - sets the align attribute.
+
+=item *
+
+C<extras> - extra C<img> tag attributes.
+
+=back
+
+Returns HTML.
+
+=cut
+
sub formatted {
my ($self, %opts) = @_;
@@ -31,6 +126,22 @@ sub formatted {
);
}
+=item inline(...)
+
+Inline the image, accepts the following parameters:
+
+=over
+
+=item *
+
+C<align> - set class to C<< bse_image_I<align> >>.
+
+=back
+
+Returns HTML.
+
+=cut
+
sub inline {
my ($self, %opts) = @_;
@@ -46,6 +157,30 @@ sub inline {
);
}
+=item popimage(...)
+
+Call the popimage() image handler object for this image, displaying
+the image as a thumbnail that displays a larger version when clicked.
+
+Parameters:
+
+=over
+
+=item *
+
+C<class> - controls the section of the config file that popup
+parameters are taken from.
+
+=item *
+
+C<static> - true to use static URLs for the thumbnails.
+
+=back
+
+Returns HTML.
+
+=cut
+
sub popimage {
my ($im, %opts) = @_;
@@ -61,21 +196,52 @@ sub popimage {
);
}
+=item image_url
+
+Return the image's source URL. This will be the storage URL if the
+image is C<storage> is not C<local>.
+
+=cut
+
sub image_url {
my ($im) = @_;
return $im->src || BSE::TB::Images->base_uri . $im->image;
}
+=item json_data
+
+Returns the image data as a data structure suitable for conversion to
+JSON.
+
+=cut
+
sub json_data {
my ($self) = @_;
my $data = $self->data_only;
$data->{url} = $self->image_url;
+ $data->{tags} = [ $self->tags ];
return $data;
}
+=item dynamic_thumb_url(...)
+
+Return a dynamic URL to a thumbnail of the image.
+
+Requires one named parameter:
+
+=over
+
+=item *
+
+C<geo> - the thumbnail geometry to use.
+
+=back
+
+=cut
+
sub dynamic_thumb_url {
my ($self, %opts) = @_;
@@ -103,6 +269,12 @@ sub filename {
return $self->image;
}
+=item article
+
+The article this image belongs to.
+
+=cut
+
sub article {
my ($self) = @_;
@@ -116,13 +288,26 @@ sub article {
}
}
+=item remove
+
+Remove the image.
+
+=cut
+
sub remove {
my ($self) = @_;
+ $self->remove_tags;
unlink $self->full_filename;
return $self->SUPER::remove();
}
+=item update
+
+Make updates to the image.
+
+=cut
+
sub update {
my ($image, %opts) = @_;
@@ -278,4 +463,24 @@ sub update {
return 1;
}
+sub tag_owner_type {
+ "BI"
+}
+
+sub tableClass {
+ "BSE::TB::Images";
+}
+
1;
+
+=back
+
+=head1 INHERITED BEHAVIOUR
+
+Inherits from L<BSE::TB::TagOwner> and L<BSE::ThumbCommon>
+
+=head1 AUTHOR
+
+Tony Cook <tony@develop-help.com>
+
+=cut
View
5 site/cgi-bin/modules/BSE/TB/Images.pm
@@ -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';
View
47 site/cgi-bin/modules/BSE/TB/SiteCommon.pm
@@ -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.
View
57 site/cgi-bin/modules/BSE/ThumbCommon.pm
@@ -2,7 +2,21 @@ package BSE::ThumbCommon;
use strict;
use Carp ();
-our $VERSION = "1.000";
+our $VERSION = "1.001";
+
+=head1 NAME
+
+BSE::ThumbCommon - behaviour for images with thumbnails.
+
+=head1 SYNOPSIS
+
+ my $thumb = $image->thumb(...)
+
+=head1 DESCRIPTION
+
+=over
+
+=cut
# common code between article images and BSE::TB::File
@@ -17,6 +31,39 @@ sub _handler_object {
my $handler = $module->new(cfg => $cfg);
}
+=item thumb(...)
+
+Calls the thumb method on the image handler object.
+
+Parameters:
+
+=over
+
+=item *
+
+C<geo> - thumbnail geometry
+
+=item *
+
+C<field> - field to return, if any. This can be C<object> to return a
+hash of image information. Fields are otherwise returned HTML
+encoded.
+
+=item *
+
+C<geo> - thumbnail geometry (required)
+
+=item *
+
+C<static> - set to true to return a URL to a pregenerated thumbnail
+image.
+
+=back
+
+Returns HTML unless C<field> is supplied.
+
+=cut
+
sub thumb {
my ($im, %opts) = @_;
@@ -32,3 +79,11 @@ sub thumb {
}
1;
+
+=back
+
+=head1 AUTHOR
+
+Tony Cook <tony@develop-help.com>
+
+=cut
View
12 site/data/db/bse_msg_base.data
@@ -1,5 +1,5 @@
--
-# VERSION=1.006
+# VERSION=1.008
id: bse/
description: BSE messages
@@ -143,12 +143,18 @@ description: flashed when a tag is removed successfully. $1 - tag name
id: bse/admin/edit/tags/cleanup
description: flashed after tags are cleaned up
-id: bse/admin/edit/tags/invalid_empty
+id: bse/admin/edit/tags/invalid/
+description: various invalid tag value error messages
+
+id: bse/admin/edit/tags/invalid/empty
description: field error if the tag name is empty
-id: bse/admin/edit/tags/invalid_badchars
+id: bse/admin/edit/tags/invalid/badchars
description: field error if the tag name contains invalid characters
+id: bse/admin/edit/tags/invalid/emptyvalue
+description: field error if the tag value component is empty
+
id: bse/admin/edit/tags/bad_id
description: tag_id field error if the tag id isn't present or isn't numeric
View
9 site/data/db/bse_msg_defaults.data
@@ -1,5 +1,5 @@
---
-# VERSION=1.006
+# VERSION=1.007
# defaults for the following
language_code: en
priority: 0
@@ -94,12 +94,15 @@ message: Tag '%1:s' removed.
id: bse/admin/edit/tags/cleanup
message: Deleted %1:d unused tags
-id: bse/admin/edit/tags/invalid_empty
+id: bse/admin/edit/tags/invalid/empty
message: Tags must have a non-empty name
-id: bse/admin/edit/tags/invalid_badchars
+id: bse/admin/edit/tags/invalid/badchars
message: Tags cannot contain control characters, backslash (\) or forward slash (/)
+id: bse/admin/edit/tags/invalid/emptyvalue
+message: Tags must have text after the colon (:)
+
id: bse/admin/edit/tags/bad_id
message: Invalid tag id
View
22 site/data/db/sql_statements.data
@@ -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
+
View
2  site/htdocs/js/admin_edit.js
@@ -18,7 +18,7 @@ Event.observe(document, "dom:loaded", function () {
$("tags").insertBefore(new_div, add_div);
ev.stop();
}.bind(this, add_div));
- if ($("#tags")) {
+ if ($("tags")) {
$("tags").appendChild(add_div);
$$('#tags div.tag').each(function(div) {
var del = new Element("a", { href: "#" });
View
18 site/templates/admin/article_img.tmpl
@@ -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>
@@ -55,6 +55,22 @@
</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>
View
15 site/templates/admin/image_edit.tmpl
@@ -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>
@@ -36,6 +36,19 @@
<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>
View
11 site/templates/admin/include/edit_common.tmpl
@@ -10,13 +10,16 @@
<td>
<input type="hidden" name="_save_tags" value="1" />
<div id="tags">
- <:iterator begin tags:>
- <div class="tag"><input type="text" name="tags" value="<:tag name:>" /></div>
- <:iterator end tags:>
+ <:.set tags = cgi.param("_save_tags") ? [ cgi.param("tags") ] : [ article.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 :>
+ <:.if !cgi.param("_save_tags") -:>
<div class="tag"><input type="text" name="tags" value="" /></div>
+ <:.end if-:>
</div>
</td>
- <td class="help"><:help edit tags:><:error_img tags:></td>
+ <td class="help"><:help edit tags:></td>
</tr>
<tr>
<th>Always Dynamic:</th>
View
8 site/templates/preload.tmpl
@@ -127,10 +127,12 @@ Page <:= pages.page :> of <:= pages.pagecount :>
<:.if errors.$field -:>
<:.set msg = errors.$field -:>
<:.set msg = msg.is_list ? msg[index] : msg -:>
- <:.set image = cfg.entry("error_img", "image", dist_image_uri _ "/admin/error.gif") -:>
- <:.set width = cfg.entry("error_img", "width", 16) -:>
- <:.set height = cfg.entry("error_img", "height", 16) -:>
+ <:.if msg.defined -:>
+ <:.set image = cfg.entry("error_img", "image", dist_image_uri _ "/admin/error.gif") -:>
+ <:.set width = cfg.entry("error_img", "width", 16) -:>
+ <:.set height = cfg.entry("error_img", "height", 16) -:>
<img src="<:= image -:>" alt="<:= msg :>" title="<:= msg :>" width="<:= width :>" height="<:= height :>" class="error_img">
+ <:.end if -:>
<:.end if -:>
<:.end define -:>
View
18 t/050-local/020-article.t
@@ -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);
+ }
}
}

No commit comments for this range

Something went wrong with that request. Please try again.