source: extensions/pLoader/trunk/src/Uploader/Images.pm @ 6426

Last change on this file since 6426 was 6426, checked in by ronosman, 14 years ago

Bug 1710 fixed : pLoader lack of concurrency support causes data inconsistency.

File size: 11.6 KB
Line 
1package Uploader::Images;
2use strict;
3use base qw/Uploader::Object/;
4use Uploader::Image;
5use Digest::MD5::File qw/file_md5_hex md5_hex/;
6require Win32 if($^O =~ /MSWin32/);
7use Storable;
8use Data::Dumper;
9
10$|=1;
11
12my @cbk_properties = qw/
13    add_images_cbk
14    delete_images_cbk
15    create_wx_thumbnail_cbk
16    default_caption_cbk
17    default_caption_pattern_cbk
18/;
19
20my @storable_properties = qw/
21    ordered_image_ids
22    selection
23    _images
24    current_image
25    selection_tags
26    selection_privacy_level
27    selection_name
28    selection_comment
29    selection_author
30    selection_create_date
31    author
32    type
33/;
34
35my @app_properties = qw/
36    eng_caption_patterns
37/;
38
39__PACKAGE__->mk_accessors(@cbk_properties);
40__PACKAGE__->mk_accessors(@storable_properties);
41__PACKAGE__->mk_accessors(@app_properties);
42
43my $_global_rank = -1;
44
45sub Init {
46    my ( $self ) = @_;
47
48    $self->_images({}) if !defined $self->_images;
49    $self->ordered_image_ids([]) if !defined $self->ordered_image_ids;
50    $self->selection([]) if !defined $self->selection;
51}
52
53
54sub add_images {
55    my ( $self, $file_paths ) = @_;
56
57    my $files = [
58        map {
59            # to make sure that unicode chars in filenames are supported
60            {
61                ANSIPathName => $^O =~ /MSWin32/ ? Win32::GetANSIPathName($_) : $_,
62                PathName => $_,
63            },
64        }@$file_paths
65    ];
66
67    @$files = sort { $a->{PathName} cmp $b->{PathName} } @$files;   
68
69
70
71    foreach my $file ( @{$files} ) {
72        # to append at the end of list
73        $self->add_image_from_file($file);
74    }
75   
76    $self->Store;
77   
78}
79
80
81sub add_image_from_file {
82    my ( $self, $file ) = @_;   
83
84    # pLoader image id
85    my $image_id = $self->new_image_id(
86        $file->{ANSIPathName}
87    );
88
89    my $i = $self->image_count;
90    $self->ordered_image_ids->[$i] = $image_id ;
91
92
93    my $image = $self->_images->{
94        $image_id
95    };
96    if ( !defined $image ){
97        $image = Uploader::Image->new(
98            {
99                file              => $file->{ANSIPathName},
100                image_id          => $image_id,
101                caption           => $self->default_caption_cbk->(),
102                site_author       => $self->author,
103                add_rank          => $i,
104                site_categories   => [],
105                site_tags         => [],
106                site_high_file    => $file->{ANSIPathName},
107                global_rank       => ++$_global_rank,
108            }
109        );
110
111        $image->site_name(
112            $self->init_caption_from_pattern(
113                $image->file,
114                $image->create_date,
115                $image->add_rank,
116                $self->default_caption_cbk->(),
117                $self->default_caption_pattern_cbk->()
118            )
119        );
120
121        $self->create_wx_thumbnail_cbk->($image)
122            if 'CODE' eq ref $self->create_wx_thumbnail_cbk;
123
124        $self->_images->{$image_id} = $image ;
125    }
126
127    $self->add_images_cbk->($image->wx_thumb_file)
128       if 'CODE' eq ref $self->add_images_cbk;
129
130    $image;
131}
132
133
134sub new_image_id {
135    my ( $self, $filename ) = @_;
136
137    my $image_id = file_md5_hex(
138        $filename
139    );
140
141    $image_id;
142}
143
144
145sub Store {
146    my ( $self ) = @_;
147   
148    my $data = $self->get_storable(
149        [ 
150            qw/
151                version
152                storable_file
153            /,
154            @storable_properties
155        ] 
156   
157    );
158    eval {
159        #print Dumper $data;
160        store $data, $self->storable_file if defined $self->storable_file;
161    };
162    if($@){
163        print $@, "\n";   
164    }
165}
166
167
168sub set_current_image {
169    my ( $self, $indx ) = @_;
170    $self->current_image(
171        $indx != -1 ? $self->get_image($indx) : Uploader::Image->new()
172    );
173}
174
175
176sub get_image {
177    my ( $self, $indx ) = @_;
178   
179    my $id = $self->ordered_image_ids->[$indx];
180
181    $self->_images->{$id};
182}
183
184
185sub Image {
186    my ( $self, $id ) = @_;
187   
188    $self->_images->{$id};
189}
190
191
192sub is_empty {
193    my ( $self ) = @_;
194
195    !$self->image_count;
196}
197
198
199sub image_count {
200    my ( $self ) = @_;
201
202    scalar @{$self->ordered_image_ids};
203}
204
205
206sub selection_count {
207    my ( $self ) = @_;
208
209    scalar @{$self->selection};
210}
211
212
213sub remove_selection {
214    my ( $self ) = @_;
215   
216    return if ( $self->is_empty );
217    return if (! defined $self->selection );
218   
219    $self->_remove_selection($self->selection);
220    # clear image selection
221    $self->selection([]);
222}
223
224
225sub _remove_selection {
226    my ( $self, $list ) = @_;
227    # the list is sorted, ascendant
228    # we reverse it to have
229    # higher first, and keep same indexes while deleting
230    @$list = reverse @$list;     
231    map {
232        $self->delete_image($_);
233        $self->delete_images_cbk->($_);
234        splice @{$self->ordered_image_ids}, $_, 1 ;
235        shift @$list;
236    }
237    @$list;
238
239}
240
241sub delete_image {
242    my ( $self, $indx ) = @_;
243   
244    my $id = $self->ordered_image_ids->[$indx];
245
246    # have to check if that id is used more than once
247    my $count = grep { $id eq $_} @{$self->ordered_image_ids};
248
249    delete $self->_images->{$id} unless $count > 1;
250}
251
252
253sub multi_selection_mode {
254    my ( $self ) = @_;
255
256    scalar @{$self->selection} > 1;
257}
258
259
260sub set_image_selection_tags {
261    my ( $self, $tags ) = @_;
262
263    $self->selection_tags($tags) if 'ARRAY' eq ref $tags;
264
265    # append to each image
266    # if multiple selection
267    if($self->multi_selection_mode){
268        map {
269            # need to dedup
270            my $tags = [
271                @{$self->get_image($_)->site_tags},
272                @{$self->selection_tags},
273            ];
274            #deduplicate
275            my $uniq = {
276                 map { $_ => 1 } @$tags
277            };
278            @$tags = keys %$uniq;
279            $self->get_image($_)->site_tags(
280                $tags
281            );
282        }@{$self->selection};
283    }
284
285    $self->selection_tags;
286}
287
288
289sub set_image_selection_privacy_level {
290    my ( $self, $privacy_level ) = @_;
291
292    # append to each image
293    # if multiple selection
294    if($self->multi_selection_mode){
295        if(defined $privacy_level){
296            $self->selection_privacy_level($privacy_level);
297            map {
298                $self->get_image($_)->privacy_level(
299                    $privacy_level
300                ) ;
301            }@{$self->selection}
302        };
303    }
304
305    $self->selection_privacy_level;
306}
307
308
309sub set_image_selection_name {
310    my ( $self, $name, $param ) = @_;
311   
312    # works in single and multi selection mode
313    if(defined $name){
314        map {
315            my $_name;
316            if( 'CODE' eq ref $name ){
317                $_name = $name->($_, $param);
318            }
319            else{
320                $_name = $name;
321                $self->get_image($_)->caption(
322                    $_name
323                ) ;
324            }
325
326            $self->selection_name($_name);
327            $self->get_image($_)->site_name(
328                $_name
329            ) ;
330        }@{$self->selection}
331    }
332}
333
334
335sub set_image_selection_author {
336    my ( $self, $author ) = @_;
337
338    # append to each image
339    # if multiple selection
340    if($self->multi_selection_mode){
341        if(defined $author){
342            $self->selection_author($author);
343            map {
344                $self->get_image($_)->site_author(
345                    $author
346                ) ;
347            }@{$self->selection}
348        };
349    }
350
351    $self->selection_author;
352}
353
354sub set_image_selection_comment {
355    my ( $self, $comment ) = @_;
356
357    # append to each image
358    # if multiple selection
359    if($self->multi_selection_mode){
360        if(defined $comment){
361            $self->selection_comment($comment);
362            map {
363                $self->get_image($_)->site_comment(
364                    $comment
365                ) ;
366            }@{$self->selection}
367        };
368    }
369
370    $self->selection_comment;
371}
372
373
374sub set_image_selection_create_date {
375    my ( $self, $date ) = @_;
376
377    # append to each image
378    # if multiple selection
379    if($self->multi_selection_mode){
380        if(defined $date){
381            $self->selection_create_date($date);
382            map {
383                $self->get_image($_)->create_date(
384                    $date
385                ) ;
386            }@{$self->selection}
387        };
388    }
389
390    $self->selection_create_date;
391}
392
393
394sub get_current_image_caption {
395    my ( $self, $index, $pattern ) = @_;
396
397    $pattern = $self->eng_caption_patterns->{$pattern};
398
399    $self->set_current_image($index);
400
401    my $img = $self->current_image;
402
403    $self->init_caption_from_pattern(
404        $img->file,
405        $img->create_date,
406        $index,
407        $self->current_image->caption,
408        $pattern
409    );
410}
411
412
413sub init_caption_from_pattern {
414    my ( $self, $file, $create_date, $i, $caption, $pattern ) = @_;
415
416    my ( $yyyy, $mm, $dd, $hh, $mi, $ss ) = split /[:\s]/, $create_date ;
417 
418    my $chrono = join('', $yyyy, $mm, $dd);
419
420    my $caption_from_pattern;
421    my $ext;
422    my ( $vol, $path, $filename ) = File::Spec->splitpath($file);
423    ( $filename, $ext ) = split /\.\w+$/, $filename;
424   
425
426    if('Caption' eq $pattern){
427        $caption_from_pattern = $caption
428    }
429    elsif('File name' eq $pattern){
430        $caption_from_pattern = $filename
431    }
432    elsif('File path and name' eq $pattern){
433        $caption_from_pattern = sprintf(
434            "%s", 
435            File::Spec->catfile($path, $filename), 
436        )       
437    }   
438    elsif('Caption + rank number' eq $pattern){
439        $caption_from_pattern = sprintf(
440            "%s %s", 
441            $caption, 
442            1+$i,
443        )       
444    }   
445    elsif('Rank number + caption' eq $pattern){
446        $caption_from_pattern = sprintf(
447            "%s %s", 
448            1+$i,
449            $caption, 
450        )       
451    }   
452    elsif('Caption + create date chrono' eq $pattern){
453        $caption_from_pattern = sprintf(
454            "%s %s", 
455            $caption, 
456            $chrono,
457        )       
458    }   
459    elsif('Create date chrono + caption' eq $pattern){
460        $caption_from_pattern = sprintf(
461            "%s %s", 
462            $chrono,
463            $caption, 
464        )       
465    }
466    elsif('Create date chrono + rank' eq $pattern){
467        $caption_from_pattern = sprintf(
468            "%s %s", 
469            $chrono,
470            1+$i, 
471        )       
472    }
473    elsif('Rank + create date chrono' eq $pattern){
474        $caption_from_pattern = sprintf(
475            "%s %s", 
476            1+$i, 
477            $chrono,
478        )       
479    }
480
481    $caption_from_pattern;
482}
483
484
485# we cannot send objects in other threads
486# and thread use data as they were when the thread is created
487sub get_images {
488    my ( $self, $preferences, $destination_category, $all ) = @_;
489
490    my $image_id_list = $all ?
491        $self->ordered_image_ids :
492        [
493            map {
494                $self->ordered_image_ids->[$_]
495            }@{$self->selection}
496        ];
497
498    $self->get_images_data(
499        $image_id_list,
500        $preferences,
501        $destination_category
502    );
503}
504
505
506my $add_rank = 0;
507# copy data from image objects
508sub get_images_data {
509    my ( $self, $image_id_list, $preferences, $destination_category ) = @_;
510
511
512    return [
513        map{
514            $self->Image($_)->get_data($preferences, $destination_category, $add_rank++)
515        }@$image_id_list
516    ]
517}
518
5191;
Note: See TracBrowser for help on using the repository browser.