add category attribute to articles
authorTony Cook <tony@develop-help.com>
Thu, 25 Aug 2011 00:42:06 +0000 (10:42 +1000)
committerTony Cook <tony@develop-help.com>
Thu, 25 Aug 2011 00:42:06 +0000 (10:42 +1000)
13 files changed:
schema/bse.sql
site/cgi-bin/modules/Article.pm
site/cgi-bin/modules/Articles.pm
site/cgi-bin/modules/BSE/DB/Mysql.pm
site/cgi-bin/modules/BSE/Edit/Article.pm
site/data/db/bse_msg_base.data
site/data/db/bse_msg_defaults.data
site/docs/config.pod
site/htdocs/admin/help/edit.html
site/templates/admin/include/edit_common.tmpl
site/util/initial.pl
site/util/mysql.str
t/t11save.t

index 8d1511f3fd733c9fa1b61ac545ef393bf8aa04fd..2532b5f9a8f18272c62a4aa23c9197d4b81fc9d3 100644 (file)
@@ -102,6 +102,8 @@ CREATE TABLE article (
 
   -- alias used to generate links
   linkAlias varchar(255) not null default '',
+
+  category varchar(40) not null default '',
   
   PRIMARY KEY (id),
 
index 57ce2623b1df577a0e2171be9dd12c800a571679..2a13f3a4bea7ef078c1d32c93425c8fa396f77c3 100644 (file)
@@ -8,7 +8,7 @@ use vars qw/@ISA/;
 @ISA = qw/Squirrel::Row BSE::TB::SiteCommon BSE::TB::TagOwner/;
 use Carp 'confess';
 
-our $VERSION = "1.005";
+our $VERSION = "1.006";
 
 sub columns {
   return qw/id parentid displayOrder title titleImage body
@@ -19,7 +19,8 @@ sub columns {
     customInt1 customInt2 customInt3 customInt4 
     lastModifiedBy created createdBy author pageTitle
     force_dynamic cached_dynamic inherit_siteuser_rights
-    metaDescription metaKeywords summary menu titleAlias linkAlias/;
+    metaDescription metaKeywords summary menu titleAlias linkAlias
+    category/;
 }
 
 sub table {
index 150678a7f16071e3da0fd0d04e8cf9b03c8c7037..eed847bd37edacf450c3c1bdb005a3013b191a41 100644 (file)
@@ -6,7 +6,7 @@ require BSE::TB::TagOwners;
 @ISA = qw(Squirrel::Table BSE::TB::TagOwners);
 use Article;
 
-our $VERSION = "1.002";
+our $VERSION = "1.003";
 
 sub rowClass {
   return 'Article';
@@ -179,4 +179,23 @@ sub all_tags {
     );
 }
 
+sub categories {
+  my $cfg = BSE::Cfg->single;
+
+  my @cat_ids = split /,/, $cfg->entry("article categories", "ids", "");
+  grep $_ eq "", @cat_ids
+    or unshift @cat_ids, "";
+
+  my @cats;
+  for my $id (@cat_ids) {
+    my $section = length $id ? "article category $id" : "article category empty";
+    my $def_name = length $id ? ucfirst $id : "(None)";
+    my $name = $cfg->entry($section, "name",
+                          $cfg->entry("article categories", $id, $def_name));
+    push @cats, +{ id => $id, name => $name };
+  }
+  
+  return @cats;
+}
+
 1;
index cd0c220711cccbc9f95a39dc894779cdcb29533a..975cad76a7f123adcc719f6142e00e3a9b8df00d 100644 (file)
@@ -5,7 +5,7 @@ use vars qw/@ISA/;
 use Carp 'confess';
 @ISA = qw(BSE::DB);
 
-our $VERSION = "1.004";
+our $VERSION = "1.005";
 
 use vars qw($VERSION $MAX_CONNECTION_AGE);
 
@@ -22,9 +22,9 @@ my %statements =
    # don't ever load the entire articles table
    #Articles => 'select * from article',
    replaceArticle =>
-     'replace article values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
+     'replace article values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
    addArticle =>  
-     'insert article values (null, ?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
+     'insert article values (null, ?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
    deleteArticle => 'delete from article where id = ?',
    getArticleByPkey => 'select * from article where id = ?',
    
index b0d3c582bcb1236dae85418bb8966bf6f74dd1b7..606a6e8845793378dfafe4b1b88405b8b0ccbe3e 100644 (file)
@@ -11,9 +11,10 @@ use BSE::Util::Iterate;
 use BSE::Template;
 use BSE::Util::ContentType qw(content_type);
 use DevHelp::Date qw(dh_parse_date dh_parse_sql_date);
+use List::Util qw(first);
 use constant MAX_FILE_DISPLAYNAME_LENGTH => 255;
 
-our $VERSION = "1.009";
+our $VERSION = "1.010";
 
 =head1 NAME
 
@@ -538,6 +539,12 @@ sub extra_templates {
   @templates;
 }
 
+sub categories {
+  my ($self, $articles) = @_;
+
+  return $articles->categories;
+}
+
 sub edit_parent {
   my ($article) = @_;
 
@@ -827,6 +834,19 @@ sub tag_movechild {
   return make_arrows($req->cfg, $down_url, $up_url, $refresh_url, $img_prefix);
 }
 
+sub tag_category {
+  my ($self, $articles, $article) = @_;
+
+  my @cats = $self->categories($articles);
+
+  my %labels = map { $_->{id}, $_->{name} } @cats;
+
+  return popup_menu(-name => 'category',
+                   -values => [ map $_->{id}, @cats ],
+                   -labels => \%labels,
+                   -default => $article->{category});
+}
+
 sub tag_edit_link {
   my ($cfg, $article, $args, $acts, $funcname, $templater) = @_;
   my ($which, $name) = split / /, $args, 2;
@@ -1276,6 +1296,7 @@ sub low_edit_tags {
      $it->make_iterator([ iter_file_stores => $self], 
                        'file_store', 'file_stores'),
      ifGroupRequired => [ \&tag_ifGroupRequired, $article, \$current_group ],
+     category => [ tag_category => $self, $articles, $article ],
      $ito->make
      (
       single => "tag",
@@ -1451,6 +1472,12 @@ sub _validate_common {
       $errors->{linkAlias} = "Link alias must contain only alphanumerics and contain at least one letter";
     }
   }
+
+  if (defined $data->{category}) {
+    unless (first { $_->{id} eq $data->{category} } $self->categories($articles)) {
+      $errors->{category} = "msg:bse/admin/edit/category/unknown";
+    }
+  }
 }
 
 sub validate {
@@ -1692,7 +1719,7 @@ sub save_new {
 # end adrian
 
   $self->fill_new_data($req, \%data, $articles);
-  for my $col (qw(titleImage imagePos template keyword menu titleAlias linkAlias body author summary)) {
+  for my $col (qw(titleImage imagePos template keyword menu titleAlias linkAlias body author summary category)) {
     defined $data{$col} 
       or $data{$col} = $self->default_value($req, \%data, $col);
   }
@@ -4694,6 +4721,7 @@ my %defaults =
    linkAlias => '',
    author => '',
    summary => '',
+   category => '',
   );
 
 sub default_value {
index d3b948c3d600da4489aad8641b2f296ceafb5838..dc0b6903c87533b1330cda344454a11e3ba97d55 100644 (file)
@@ -104,6 +104,12 @@ description: name field error if you try to rename a tag to match another
 id: bse/admin/edit/tags/nochange
 description: name field error if no change is saved
 
+id: bse/admin/edit/category
+description: Category field errors
+
+id: bse/admin/edit/category/unknown
+description: if an unknown article category is received
+
 id: bse/admin/shop/
 description: Shop Administration
 
index 4a2baef1b048b4e80e30e085a32b95b7cda11658..2e8392a2606201d5b425f84615b4bb2acd202b44 100644 (file)
@@ -67,6 +67,9 @@ message: There is already a tag with name '%1:s'
 id: bse/admin/edit/tags/nochange
 message: No changes to save
 
+id: bse/admin/edit/category/unknown
+message: Unknown article category
+
 id: bse/admin/message/noid
 message: Missing id parameter
 
index f9e7d3d1cedf4dd6722b74f301670aeaeeb5d5b4..e1a33b456b1ec4e4ba25771eb400f65a0f6361d4 100644 (file)
@@ -2534,6 +2534,37 @@ replacement.
 
 Replacement is performed case-insenitively.  Regexp metacharacters
 
+=head2 [article categories]
+
+=over
+
+=item *
+
+ids - a comma separated list of category ids.  There are (currently)
+no restrictions on the contents of these ids, but alphanumerics are
+recommended to simplify templates.
+
+=item *
+
+I<id> - a description for a particular category id.  Overridden by the
+C<name> key in C<< [article category I<id>] >>.  Default: ucfirst of
+the id.
+
+=back
+
+=head2 [article category I<id>]
+
+=over
+
+=item *
+
+name - name of the article category.
+
+=back
+
+Other keys may be used as desired, eg. to make it simpler to configure
+article behaviour based on the category.
+
 =head1 AUTHOR
 
 Tony Cook <tony@develop-help.com>
index f6710c24bcd7029832300aa15644a8fb87fbabf3..a560e6438a425d2098a9526d71d531fb5859fd40 100644 (file)
@@ -129,6 +129,15 @@ engine.</p>
 
 </div>
 
+<div>
+<h2><a name="keywords"></a>Category</h2>
+
+  <p>This indicates the type of use that an article is intended for.
+  The possible values and the results will depend on your local
+  configuration.</p>
+
+</div>
+
 <div>
   <h2><a name="listed"></a>List article</h2>
 
@@ -173,4 +182,4 @@ by clicking the &quot;Manage Images&quot; link.</p>
   </div>
  
 
-</body></html>
\ No newline at end of file
+</body></html>
index 083817e1f813b0c41aa90e0ba8039e946ff1cb89..7deb7a1bce8c368ca48c70d4bab47b3c002e7e22 100644 (file)
@@ -25,3 +25,9 @@
               <:or:><:ifArticle force_dynamic :>Yes<:or Article:>No<:eif Article:><:eif:></td>
             <td class="help"><:help edit keywords:> <:error_img keyword:></td>
           </tr>
+          <tr> 
+            <th>Category:</th>
+            <td> 
+              <:if FieldPerm category:><:category:><:or FieldPerm:><: article category :><:eif FieldPerm:></td>
+            <td class="help"><:help edit category:> <:error_img category:></td>
+          </tr>
index f816a4397a3049159ae2f172277432cec554d8d1..6b73d83e56d190d4f44b38e6ebe5bc42f11e4782 100644 (file)
@@ -56,6 +56,7 @@ my @prebuilt =
     summary => '',
     menu => 0,
     titleAlias => '',
+    category => '',
    },
    {
     # the invisible subsection for what's hot
@@ -95,6 +96,7 @@ my @prebuilt =
     summary => '',
     menu => 0,
     titleAlias => '',
+    category => '',
    },
    {
     id=>3,
@@ -133,6 +135,7 @@ my @prebuilt =
     summary => '',
     menu => 0,
     titleAlias => '',
+    category => '',
    },
    {
     id=>4,
@@ -171,6 +174,7 @@ my @prebuilt =
     summary => '',
     menu => 0,
     titleAlias => '',
+    category => '',
    },
    {
     id=>5,
@@ -209,6 +213,7 @@ my @prebuilt =
     summary => '',
     menu => 0,
     titleAlias => '',
+    category => '',
    },
    {
     id=>6,
@@ -477,6 +482,7 @@ EOS
     summary => '',
     menu => 0,
     titleAlias => '',
+    category => '',
    },
    {
     id=>7,
@@ -519,6 +525,7 @@ EOS
     summary => '',
     menu => 0,
     titleAlias => '',
+    category => '',
    },
    {
     id=>8,
@@ -561,6 +568,7 @@ EOS
     summary => '',
     menu => 0,
     titleAlias => '',
+    category => '',
    },
   );
 
index 5e2db23891b92d3285a3c68add90d49b73da5960..9e88ddddec4e95084a845c04684d9868ff0b15dc 100644 (file)
@@ -80,6 +80,7 @@ Column summaryx;text;NO;NULL;
 Column menu;smallint(5);NO;0;
 Column titleAlias;varchar(60);NO;;
 Column linkAlias;varchar(255);NO;;
+Column category;varchar(40);NO;;
 Index PRIMARY;1;[id]
 Index article_alias;0;[linkAlias]
 Index article_date_index;0;[release;expire;id]
index 73249f5c8834eaf38b7a93bb90ab11d66b948171..efd75883d927bc95af44d6b1a5e25e59004d2c2e 100644 (file)
@@ -8,7 +8,7 @@ use Article;
 
 my @cols = Article->columns;
 
-my $base = 113;
+my $base = 119;
 
 my $count = $base + (@cols - 13) * 4;
 
@@ -90,6 +90,26 @@ SKIP:
     }
   }
 
+  { # try to set a bad value for category
+    my %req_data = 
+      (
+       save => 1,
+       id => $art->{id},
+       category => "A" . rand(),
+       lastModified => $art->{lastModified},
+      );
+    my $data = do_req($add_url, \%req_data, "save bad category");
+  SKIP:
+    {
+      $data or skip("Not json from setting bad category", 4);
+      ok(!$data->{success}, "shouldn't be successful");
+      ok(!$data->{article}, "should be no article object");
+      is($data->{error_code}, "FIELD", "should be a field error");
+      ok($data->{errors} && $data->{errors}{category},
+        "should be an error message for category");
+    }
+  }
+
   my $tag_name1 = "YHUIOP";
   my $tag_name2 = "zyx: alpha";
   { # save tags