1 package BSE::TB::SiteCommon;
5 our $VERSION = "1.005";
9 BSE::TB::SiteCommon - methods common to the site and article objects
13 my @steps = $article->set_parents;
14 my @sections = $site->children;
18 Provides methods common to the Article and BSE::TB::Site objects.
29 Articles->getSpecial('stepParents', $self->{id});
32 sub visible_step_parents {
35 my $now = now_sqldate();
36 Articles->getSpecial('visibleStepParents', $self->{id}, $now);
42 return Articles->getSpecial('stepKids', $self->{id});
48 return Articles->getSpecial('stepKids', $self->{id});
51 sub visible_stepkids {
54 use BSE::Util::SQL qw/now_sqldate/;
55 my $today = now_sqldate();
57 if ($self->{generator} eq 'Generate::Catalog') {
58 require 'Products.pm';
60 return Products->getSpecial('visibleStep', $self->{id}, $today);
63 return Articles->getSpecial('visibleStepKids', $self->{id}, $today);
69 # returns a list of all children in the correct sort order
74 require 'OtherParents.pm';
76 my @otherlinks = OtherParents->getBy(parentId=>$self->{id});
77 my @normalkids = Articles->children($self->{id});
79 (map { $_->{id}, $_->{displayOrder} } @normalkids ),
80 (map { $_->{childId}, $_->{parentDisplayOrder} } @otherlinks),
82 my @stepkids = $self->allstepkids;
83 my %kids = map { $_->{id}, $_ } @stepkids, @normalkids;
85 return @kids{ sort { $order{$b} <=> $order{$a} } keys %kids };
88 # returns a list of all visible children in the correct sort order
90 sub all_visible_kids {
93 Articles->all_visible_kids($self->{id});
96 sub all_visible_kid_tags {
99 Articles->all_visible_kid_tags($self->{id});
102 sub all_visible_products {
106 Products->all_visible_children($self->{id});
109 sub all_visible_product_tags {
113 Products->all_visible_product_tags($self->{id});
116 sub all_visible_catalogs {
119 return grep $_->{generator} eq "Generate::Catalog", $self->all_visible_kids;
125 return Articles->listedChildren($self->{id});
130 Returns a list of children meant to be listed in menus.
137 return grep $_->listed_in_menu, $self->visible_kids;
143 Returns a list of allkids meant to be listed in menus.
150 return grep $_->listed_in_menu, $self->all_visible_kids;
155 require BSE::TB::Images;
156 BSE::TB::Images->getBy(articleId=>$self->{id});
162 return sort { $b->{displayOrder} <=> $a->{displayOrder} }
163 Articles->children($self->{id});
169 require BSE::TB::ArticleFiles;
170 return BSE::TB::ArticleFiles->getBy(articleId=>$self->{id});
174 my ($self, $cfg) = @_;
176 my @images = $self->images;
178 my $imagedir = $cfg->entry('paths', 'images', $Constants::IMAGEDIR);
179 for my $image (@images) {
180 if ($image->{storage} ne 'local') {
182 require BSE::StorageMgr::Images;
183 $mgr = BSE::StorageMgr::Images->new(cfg => $cfg);
185 $mgr->unstore($image->{image}, $image->{storage});
188 unlink("$imagedir/$image->{image}");
197 while (my $data = <$in>) {
206 my ($self, $cfg, %opts) = @_;
208 require BSE::TB::ArticleFiles;
209 defined $opts{displayName} && $opts{displayName} =~ /\S/
210 or die "displayName must be non-blank\n";
212 unless ($opts{contentType}) {
213 require BSE::Util::ContentType;
214 $opts{contentType} = BSE::Util::ContentType::content_type($cfg, $opts{displayName});
217 my $src_filename = delete $opts{filename};
218 my $file_dir = BSE::TB::ArticleFiles->download_path($cfg);
221 if ($src_filename =~ /^\Q$file_dir\E/) {
222 # created in the right place, use it
223 $filename = $src_filename;
226 open my $in_fh, "<", $src_filename
227 or die "Cannot open $src_filename: $!\n";
230 require DevHelp::FileUpload;
232 ($filename, my $out_fh) = DevHelp::FileUpload->
233 make_img_filename($file_dir, $opts{displayName}, \$msg)
235 _copy_fh_to_fh($in_fh, $out_fh)
236 or die "Cannot copy file data to $filename: $!\n";
238 or die "Cannot close output data: $!\n";
241 elsif ($opts{file}) {
242 my $file = delete $opts{file};
244 require DevHelp::FileUpload;
246 ($filename, $out_fh) = DevHelp::FileUpload->
247 make_img_filename($file_dir, $opts{displayName}, \$msg)
250 _copy_fh_to_fh($file, $out_fh)
251 or die "Cannot copy file data to $filename: $!\n";
253 or die "Cannot close output data: $!\n";
256 die "No source file provided\n";
259 my $name = $opts{name};
260 $self->id != -1 || defined $name && $name =~ /\S/
261 or die "name is required for global files\n";
262 if (defined $name && $name =~ /\S/) {
264 or die "name must be a single word\n";
265 my ($other) = BSE::TB::ArticleFiles->getBy(articleId => $self->id,
267 and die "Duplicate file name (identifier)\n";
270 require BSE::Util::SQL;
271 my $fullpath = $file_dir . '/' . $filename;
272 $opts{filename} = $filename;
273 $opts{sizeInBytes} = -s $fullpath;
274 $opts{displayOrder} = time;
275 $opts{articleId} = $self->id;
277 my $store = delete $opts{store};
278 my $storage = delete $opts{storage} || '';
280 my $fileobj = BSE::TB::ArticleFiles->make(%opts);
281 $fileobj->set_handler($cfg);
287 $self->apply_storage($cfg, $fileobj, $storage, \$msg);
292 ${$opts{msg}} = $msg;
295 $fileobj->remove($cfg);
304 # only some files can be stored remotely
305 sub select_filestore {
306 my ($self, $mgr, $file, $storage, $rmsg) = @_;
308 my $store = $mgr->select_store($file->{filename}, $storage, $file);
309 if ($store ne 'local') {
310 if ($file->{forSale} || $file->{requireUser}) {
312 $$rmsg = "For sale or user required files can only be stored locally";
314 elsif ($file->{articleId} != -1 && $file->article->is_access_controlled) {
316 $$rmsg = "Files for access controlled articles can only be stored locally";
324 my ($self, $cfg, $file, $storage, $rmsg) = @_;
327 or confess "Missing file option";
329 my $mgr = BSE::TB::ArticleFiles->file_manager($cfg);
330 $storage = $self->select_filestore($mgr, $file, $storage, $rmsg);
331 $file->apply_storage($cfg, $mgr, $storage);
334 =item reorder_child($child_id, $after_id)
336 Change the order of children of $self so that $child_id is after
339 If $after_id is zero then $child_id becomes the first child.
344 my ($self, $child_id, $after_id) = @_;
346 Articles->reorder_child($self->{id}, $child_id, $after_id);
349 sub set_image_order {
350 my ($self, $order) = @_;
352 my @images = $self->images;
353 my %images = map { $_->{id} => $_ } @images;
356 for my $id (@$order) {
358 push @new_order, delete $images{$id};
361 for my $id (map $_->id, @images) {
363 push @new_order, delete $images{$id};
367 my @display_order = map $_->{displayOrder}, @images;
368 for my $index (0 .. $#images) {
369 $new_order[$index]->set_displayOrder($display_order[$index]);
370 $new_order[$index]->save;
384 Tony Cook <tony@develop-help.com>