phtools 0.10.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +43 -0
  3. data/.rubocop_todo.yml +373 -0
  4. data/Guardfile +6 -3
  5. data/History.md +4 -0
  6. data/TODO.md +2 -0
  7. data/exe/phbackup +2 -1
  8. data/exe/phfixdto +2 -1
  9. data/exe/phfixfmd +2 -1
  10. data/exe/phgettags +2 -1
  11. data/exe/phls +2 -1
  12. data/exe/phmove +6 -3
  13. data/exe/phrename +2 -1
  14. data/exe/phtools +3 -1
  15. data/lib/phbackup.rb +2 -2
  16. data/lib/phevent.rb +2 -1
  17. data/lib/phfixdto.rb +4 -3
  18. data/lib/phfixfmd.rb +2 -2
  19. data/lib/phgettags.rb +7 -7
  20. data/lib/phls.rb +5 -6
  21. data/lib/phmove.rb +12 -21
  22. data/lib/phrename.rb +7 -6
  23. data/lib/phtagset.rb +2 -1
  24. data/lib/phtools/error.rb +2 -1
  25. data/lib/phtools/exif_tagger/error.rb +1 -0
  26. data/lib/phtools/exif_tagger/tag_collection.rb +17 -14
  27. data/lib/phtools/exif_tagger/tag_writer.rb +8 -7
  28. data/lib/phtools/exif_tagger/tags/_tag.rb +92 -37
  29. data/lib/phtools/exif_tagger/tags/_tag_array_of_strings.rb +35 -0
  30. data/lib/phtools/exif_tagger/tags/_tag_date.rb +25 -27
  31. data/lib/phtools/exif_tagger/tags/_tag_hash_of_strings.rb +39 -0
  32. data/lib/phtools/exif_tagger/tags/_tag_string.rb +32 -0
  33. data/lib/phtools/exif_tagger/tags/city.rb +7 -21
  34. data/lib/phtools/exif_tagger/tags/coded_character_set.rb +6 -21
  35. data/lib/phtools/exif_tagger/tags/collections.rb +20 -26
  36. data/lib/phtools/exif_tagger/tags/copyright.rb +6 -22
  37. data/lib/phtools/exif_tagger/tags/country.rb +6 -23
  38. data/lib/phtools/exif_tagger/tags/country_code.rb +5 -21
  39. data/lib/phtools/exif_tagger/tags/create_date.rb +17 -13
  40. data/lib/phtools/exif_tagger/tags/creator.rb +14 -25
  41. data/lib/phtools/exif_tagger/tags/date_time_original.rb +18 -13
  42. data/lib/phtools/exif_tagger/tags/gps_created.rb +21 -44
  43. data/lib/phtools/exif_tagger/tags/image_unique_id.rb +12 -27
  44. data/lib/phtools/exif_tagger/tags/keywords.rb +15 -27
  45. data/lib/phtools/exif_tagger/tags/location.rb +6 -23
  46. data/lib/phtools/exif_tagger/tags/modify_date.rb +8 -8
  47. data/lib/phtools/exif_tagger/tags/state.rb +6 -23
  48. data/lib/phtools/exif_tagger/tags/world_region.rb +6 -22
  49. data/lib/phtools/exif_tagger/tags.rb +2 -1
  50. data/lib/phtools/exif_tagger.rb +1 -0
  51. data/lib/phtools/ph_file.rb +35 -14
  52. data/lib/phtools/runner.rb +4 -4
  53. data/lib/phtools/utils.rb +1 -0
  54. data/lib/phtools/version.rb +2 -1
  55. data/lib/phtools.rb +11 -9
  56. metadata +7 -2
data/lib/phfixfmd.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
  # encoding: UTF-8
3
4
  # (c) ANB Andrew Bizyaev
4
5
 
@@ -6,9 +7,8 @@ require 'phtools/runner'
6
7
 
7
8
  module PhTools
8
9
  class Phfixfmd < Runner
9
-
10
10
  def self.about
11
- "fixes FileModifyDate to be equal to date-time-in-the-name"
11
+ 'fixes FileModifyDate to be equal to date-time-in-the-name'
12
12
  end
13
13
 
14
14
  private
data/lib/phgettags.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
  # encoding: UTF-8
3
4
  # (c) ANB Andrew Bizyaev
4
5
 
@@ -8,9 +9,8 @@ require 'phtools/exif_tagger'
8
9
 
9
10
  module PhTools
10
11
  class Phgettags < Runner
11
-
12
12
  def self.about
13
- "extracts the tags stored inside the file"
13
+ 'extracts the tags stored inside the file'
14
14
  end
15
15
 
16
16
  private
@@ -29,10 +29,10 @@ module PhTools
29
29
 
30
30
  puts "******** FILE #{phfile} ********"
31
31
 
32
- if not @options_cli['--full_dump']
33
- puts format('%-29s %s', "FileModifyDate", "#{tags.FileModifyDate}")
32
+ if !@options_cli['--full_dump']
33
+ puts format('%-29s %s', 'FileModifyDate', tags.FileModifyDate.to_s)
34
34
  ExifTagger::TAGS_SUPPORTED.each do |tag|
35
- puts "#{tag.to_s.camelize}"
35
+ puts tag.to_s.camelize
36
36
  ExifTagger::Tag.const_get(tag.to_s.camelize).const_get('EXIFTOOL_TAGS').each do |t|
37
37
  v = tags[t]
38
38
  v = 'EMPTY' if v.respond_to?(:empty?) && v.empty?
@@ -43,8 +43,8 @@ module PhTools
43
43
  end
44
44
  end
45
45
  end
46
- else #full_dump
47
- tags.to_hash.each do |t,v|
46
+ else # full_dump
47
+ tags.to_hash.each do |t, v|
48
48
  puts format('%-29s %-10s %s', t, "(#{v.class})", v)
49
49
  end
50
50
  end
data/lib/phls.rb CHANGED
@@ -1,20 +1,20 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
  # encoding: UTF-8
3
4
  # (c) ANB Andrew Bizyaev
4
5
 
5
6
  require 'phtools/runner'
6
7
 
7
8
  module PhTools
8
- # list generation
9
9
  class Phls < Runner
10
10
  def self.about
11
- %Q{generates list of phtools friendly files}
11
+ %(generates list of phtools friendly files)
12
12
  end
13
13
 
14
14
  def run!
15
15
  @dirs_to_scan.each do |dir|
16
16
  fmask = File.join(dir, @options_cli['--recursive'] ? '**' : '', "{#{@filemasks * ','}}")
17
- Dir.glob(fmask, File::FNM_CASEFOLD).each { |f| output_file(f) if File.file?(f) }
17
+ Dir.glob(fmask, File::FNM_CASEFOLD).each { |f| output_file(PhFile.new(f)) if File.file?(f) }
18
18
  end
19
19
 
20
20
  rescue SignalException
@@ -37,9 +37,8 @@ module PhTools
37
37
  @filemasks = ['*.*'] if @filemasks.empty?
38
38
  end
39
39
 
40
- def output_file(file)
41
- ftype = File.extname(file).empty? ? '' : File.extname(file).slice(1..-1).downcase
42
- @os.output(File.join(File.dirname(file), File.basename(file))) if @file_type.include?(ftype)
40
+ def output_file(phfile)
41
+ @os.output(phfile) if @file_type.include?(phfile.type)
43
42
  end
44
43
  end
45
44
  end
data/lib/phmove.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
  # encoding: UTF-8
3
4
  # (c) ANB Andrew Bizyaev
4
5
 
@@ -7,13 +8,13 @@ require 'phtools/runner'
7
8
  module PhTools
8
9
  class Phmove < Runner
9
10
  def self.about
10
- "moves input files to target folder"
11
+ 'moves input files to target folder'
11
12
  end
12
13
 
13
14
  private
14
15
 
15
16
  def validate_options
16
- @target_folder = @options_cli['TARGET_FOLDER']
17
+ @target_folder = @options_cli['TARGET_FOLDER'] || '.'
17
18
  @arrange = @options_cli['--arrange']
18
19
  if @arrange
19
20
  @raw_folder = File.join(@target_folder, 'RAW')
@@ -39,34 +40,24 @@ module PhTools
39
40
 
40
41
  def process_file(phfile)
41
42
  phfile_out = phfile.clone
42
- file_type = phfile.extname.slice(1..-1).downcase
43
- case
44
- when FILE_TYPE_IMAGE_NORMAL.include?(file_type)
45
- phfile_out.dirname = @target_folder
46
- when FILE_TYPE_IMAGE_RAW.include?(file_type)
47
- phfile_out.dirname = @raw_folder
48
- when FILE_TYPE_VIDEO.include?(file_type)
49
- phfile_out.dirname = @video_folder
50
- when FILE_TYPE_AUDIO.include?(file_type)
51
- phfile_out.dirname = @target_folder
52
- end
43
+ phfile_out.dirname = @target_folder if phfile_out.image_normal?
44
+ phfile_out.dirname = @raw_folder if phfile_out.image_raw?
45
+ phfile_out.dirname = @video_folder if phfile_out.video?
46
+ phfile_out.dirname = @target_folder if phfile_out.audio?
53
47
 
54
48
  FileUtils.mv(phfile.filename, phfile_out.filename, verbose: PhTools.debug) unless phfile == phfile_out
55
49
  phfile_out
50
+
56
51
  rescue SystemCallError => e
57
52
  raise PhTools::Error, 'file moving - ' + e.message
58
53
  end
59
54
 
60
55
  def process_after
61
- if @arrange
62
- Dir.delete @raw_folder if (Dir.exist?(@raw_folder) and
63
- Utils.dir_empty?(@raw_folder))
64
- Dir.delete @video_folder if (Dir.exist?(@video_folder) and
65
- Utils.dir_empty?(@video_folder))
66
- end
56
+ return unless @arrange
57
+ Dir.delete @raw_folder if Dir.exist?(@raw_folder) && Utils.dir_empty?(@raw_folder)
58
+ Dir.delete @video_folder if Dir.exist?(@video_folder) && Utils.dir_empty?(@video_folder)
67
59
  rescue
68
- raise PhTools::Error, "Unable to delete dir"
60
+ raise PhTools::Error, 'Unable to delete dir'
69
61
  end
70
-
71
62
  end
72
63
  end
data/lib/phrename.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
  # encoding: UTF-8
3
4
  # (c) ANB Andrew Bizyaev
4
5
 
@@ -9,7 +10,7 @@ require 'phtools/runner'
9
10
  module PhTools
10
11
  class Phrename < Runner
11
12
  def self.about
12
- "renames input files to phtools standard"
13
+ 'renames input files to phtools standard'
13
14
  end
14
15
 
15
16
  private
@@ -35,11 +36,11 @@ module PhTools
35
36
  info_msg = ''
36
37
  case @mode
37
38
  when :rename
38
- if phfile_out.basename_is_standard? and @user_tag_date.empty?
39
+ if phfile_out.basename_is_standard? && @user_tag_date.empty?
39
40
  # change only author, keeping date-time safe
40
41
  phfile_out.standardize!(author: @author)
41
- info_msg = "'#{phfile.basename+phfile.extname}' already standard name. Keeping date-time part unchanged"
42
- else #full rename
42
+ info_msg = "'#{phfile.basename + phfile.extname}' already standard name. Keeping date-time part unchanged"
43
+ else # full rename
43
44
  begin
44
45
  tags = MiniExiftool.new(phfile.filename,
45
46
  replace_invalid_chars: true,
@@ -94,7 +95,7 @@ module PhTools
94
95
  tag_used = "#{@user_tag_date}"
95
96
  end
96
97
  phfile_out.standardize!(date_time: dto, author: @author)
97
- info_msg = "'#{phfile.basename+phfile.extname}' using tag '#{tag_used}' for date-time"
98
+ info_msg = "'#{phfile.basename + phfile.extname}' using tag '#{tag_used}' for date-time"
98
99
  end
99
100
 
100
101
  when :clean
@@ -102,7 +103,7 @@ module PhTools
102
103
 
103
104
  when :shift_time
104
105
  fail PhTools::Error, 'non-standard file name' unless phfile_out.basename_is_standard?
105
- phfile_out.standardize!(date_time: phfile_out.date_time + @shift_seconds*(1.0/86400))
106
+ phfile_out.standardize!(date_time: phfile_out.date_time + @shift_seconds * (1.0 / 86_400))
106
107
  end
107
108
 
108
109
  FileUtils.mv(phfile.filename, phfile_out.filename, verbose: PhTools.debug) unless phfile == phfile_out
data/lib/phtagset.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
  # encoding: UTF-8
3
4
  # (c) ANB Andrew Bizyaev
4
5
 
@@ -7,7 +8,7 @@ require 'phtools/runner'
7
8
  module PhTools
8
9
  class Phtagset < Runner
9
10
  def self.about
10
- "!UNDER CONSTRUCTION!"
11
+ '!UNDER CONSTRUCTION!'
11
12
  end
12
13
  end
13
14
  end
data/lib/phtools/error.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
  # encoding: UTF-8
3
4
  # (c) ANB Andrew Bizyaev
4
5
 
@@ -18,7 +19,7 @@ module PhTools
18
19
  e.backtrace.each do |b|
19
20
  STDERR.puts "#{prefix}: CAUSE#{level} BACKTRACE: #{b}"
20
21
  end
21
- drill_down_error(e.cause, level+1, prefix)
22
+ drill_down_error(e.cause, level + 1, prefix)
22
23
  end
23
24
 
24
25
  def self.puts_error(msg, e = nil)
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
  # encoding: UTF-8
3
4
  # (c) ANB Andrew Bizyaev
4
5
 
@@ -1,7 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
  # encoding: UTF-8
3
4
  # (c) ANB Andrew Bizyaev
4
5
 
6
+ require 'mini_exiftool'
7
+
5
8
  module ExifTagger
6
9
  # EXIF tags collection
7
10
  class TagCollection
@@ -10,15 +13,15 @@ module ExifTagger
10
13
  def initialize(init_values = nil)
11
14
  @collection = []
12
15
  return if init_values.nil?
13
- case
14
- when init_values.is_a?(Hash)
15
- init_values.each do |k, v|
16
- self[k] = v
17
- end
18
- when init_values.is_a?(ExifTagger::TagCollection)
19
- init_values.each do |item|
20
- self[item.tag_id] = item.value
21
- end
16
+
17
+ if init_values.is_a?(Hash)
18
+ init_values.each { |k, v| self[k] = v }
19
+
20
+ elsif init_values.is_a?(ExifTagger::TagCollection)
21
+ init_values.each { |item| self[item.tag_id] = item.value }
22
+
23
+ elsif init_values.is_a?(MiniExiftool)
24
+ TAGS_SUPPORTED.each { |tag| self[tag] = init_values }
22
25
  end
23
26
  end
24
27
 
@@ -27,7 +30,7 @@ module ExifTagger
27
30
  end
28
31
 
29
32
  def to_s
30
- str = ''
33
+ str = +''
31
34
  @collection.each { |i| str << i.to_s }
32
35
  str
33
36
  end
@@ -35,7 +38,7 @@ module ExifTagger
35
38
  def []=(tag, value)
36
39
  return if value.nil?
37
40
  delete(tag)
38
- @collection << produce_tag(tag, value.dup)
41
+ @collection << produce_tag(tag, value)
39
42
  end
40
43
 
41
44
  def [](tag)
@@ -73,7 +76,7 @@ module ExifTagger
73
76
  def error_message
74
77
  str = ''
75
78
  unless valid?
76
- str = "Tags are NOT VALID:\n"
79
+ str = +"Tags are NOT VALID:\n"
77
80
  @collection.each do |item|
78
81
  item.errors.each { |e| str << ' ' + e + "\n" }
79
82
  end
@@ -82,7 +85,7 @@ module ExifTagger
82
85
  end
83
86
 
84
87
  def warning_message
85
- str = ''
88
+ str = +''
86
89
  if with_warnings?
87
90
  @collection.each do |item|
88
91
  item.warnings.each { |e| str << ' WARNING: ' + e + "\n" }
@@ -97,7 +100,7 @@ module ExifTagger
97
100
  tag_class = ExifTagger::Tag.const_get(tag.to_s.camelize)
98
101
  tag_class.new(value)
99
102
  rescue => e
100
- raise ExifTagger::UnknownTag, "Tag #{tag} - #{e.message}"
103
+ raise ExifTagger::UnknownTag, "Tag #{tag.to_s.camelize}, value '#{value}' - #{e.message}"
101
104
  end
102
105
  end
103
106
  end
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
  # encoding: UTF-8
3
4
  # (c) ANB Andrew Bizyaev
4
5
 
@@ -8,7 +9,7 @@ require 'date'
8
9
  module ExifTagger
9
10
  # batch EXIF tags setter
10
11
  class TagWriter
11
- DEFAULT_OPTIONS = %w(-v0 -FileModifyDate<DateTimeOriginal -overwrite_original -ignoreMinorErrors)
12
+ DEFAULT_OPTIONS = %w(-v0 -FileModifyDate<DateTimeOriginal -overwrite_original -ignoreMinorErrors).freeze
12
13
  attr_reader :script_name, :added_files_count
13
14
 
14
15
  def initialize(script_name: 'exif_tagger.txt',
@@ -22,17 +23,17 @@ module ExifTagger
22
23
  @output.puts "*** Preparing exiftool script '#{@script_name}' ..."
23
24
  end
24
25
 
25
- def add_to_script(phfile: '', tags: {}, options: DEFAULT_OPTIONS)
26
- @script.puts "# **(#{@added_files_count + 1})** Processing file: #{phfile} *****"
26
+ def add_to_script(filename: '', tags: {}, options: DEFAULT_OPTIONS)
27
+ @script.puts "# **(#{@added_files_count + 1})** Processing file: #{filename} *****"
27
28
  # tags
28
29
  tags.each do |k|
29
30
  @script.puts tags.item(k).to_write_script
30
31
  end
31
32
  # file to be altered
32
- @script.puts %Q{#{phfile}}
33
+ @script.puts filename
33
34
  # General options
34
- options.each { |o| @script.puts "#{o}" }
35
- @script.puts %Q{-execute}
35
+ options.each { |o| @script.puts o }
36
+ @script.puts %(-execute)
36
37
  @script.puts
37
38
  @added_files_count += 1
38
39
 
@@ -53,7 +54,7 @@ module ExifTagger
53
54
 
54
55
  def run!
55
56
  close_script
56
- if @added_files_count > 0
57
+ if @added_files_count.positive?
57
58
  @output.puts "*** Running #{command} ..."
58
59
  ok = system(command, out: @output, err: @err)
59
60
  fail if ok.nil?
@@ -1,8 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
  # encoding: UTF-8
3
4
  # (c) ANB Andrew Bizyaev
4
5
 
5
6
  require 'active_support/core_ext'
7
+ require 'mini_exiftool'
6
8
 
7
9
  module ExifTagger
8
10
  module Tag
@@ -10,23 +12,38 @@ module ExifTagger
10
12
  class Tag
11
13
  include Comparable
12
14
 
13
- EXIFTOOL_TAGS = []
14
- attr_reader :errors, :value, :value_invalid, :warnings, :write_script_lines
15
+ EMPTY = ''
16
+ EMPTY_DATE = '0000-01-01 00:00:00'
17
+ EXIFTOOL_TAGS = [].freeze
18
+ MAX_BYTESIZE = 32
19
+
20
+ attr_reader :errors, :value, :raw_values, :value_invalid, :warnings, :write_script_lines
21
+ attr_reader :previous
15
22
  attr_accessor :info, :force_write
16
23
 
17
- def initialize(value_norm = '')
18
- @value = value_norm
19
- @errors = []
20
- @value_invalid = []
21
- @warnings = []
22
- @write_script_lines = []
24
+ def self.empty?(value)
25
+ return true if value.nil?
26
+ return value.empty? if value.is_a?(String)
27
+ return value.join.empty? if value.is_a?(Array)
28
+ return value.values.join.empty? if value.is_a?(Hash)
29
+ false
30
+ end
31
+
32
+ def initialize(value = '', previous = nil)
33
+ @raw_values = {}
34
+ if value.class == MiniExiftool
35
+ init_raw_values(value)
36
+ @value = normalize(get_from_raw)
37
+ else
38
+ @value = normalize(value)
39
+ end
40
+ @previous = (previous.is_a?(self.class) ? previous : nil)
23
41
  @info = ''
24
42
  @force_write = false
43
+
25
44
  validate
26
- @value.freeze
27
- @errors.freeze
28
- @value_invalid.freeze
29
- @warnings.freeze
45
+ validate_vs_previous
46
+ freeze_values
30
47
  end
31
48
 
32
49
  def tag_id
@@ -38,14 +55,12 @@ module ExifTagger
38
55
  end
39
56
 
40
57
  def <=>(other)
41
- if other.respond_to? :tag_id
42
- tag_id <=> other.tag_id
43
- else
44
- tag_id <=> other.to_s.to_sym
45
- end
58
+ return tag_id <=> other.tag_id if other.respond_to?(:tag_id)
59
+ tag_id <=> other.to_s.to_sym
46
60
  end
47
61
 
48
62
  def to_s
63
+ return "#{tag_id} is EMPTY" if Tag.empty?(@value)
49
64
  "#{tag_id} = #{@value}"
50
65
  end
51
66
 
@@ -53,6 +68,7 @@ module ExifTagger
53
68
  @errors.empty?
54
69
  end
55
70
 
71
+ # TODO: remove deprecated method
56
72
  def check_for_warnings(original_values: {})
57
73
  @warnings = []
58
74
  self.class::EXIFTOOL_TAGS.each do |tag|
@@ -72,39 +88,78 @@ module ExifTagger
72
88
  end
73
89
 
74
90
  def to_write_script
75
- str = ''
76
- generate_write_script_lines
91
+ str = +''
92
+ @write_script_lines = []
93
+ generate_write_script_lines unless Tag.empty?(@value)
77
94
  unless @write_script_lines.empty?
78
- str << print_info
79
- str << print_warnings
80
- str << print_lines
95
+ str << (info.empty? ? '' : "# INFO: #{@info}\n")
96
+ @warnings.each do |w|
97
+ str << "# WARNING: #{w}\n"
98
+ end
99
+ @write_script_lines.each do |l|
100
+ unless @warnings.empty?
101
+ str << '# ' unless @force_write
102
+ end
103
+ str << "#{l}\n"
104
+ end
81
105
  end
82
106
  str
83
107
  end
84
108
 
85
109
  private
86
110
 
87
- def print_info
88
- @info.empty? ? '' : "# INFO: #{@info}\n"
111
+ def normalize(value)
112
+ return EMPTY if value.nil?
113
+ return EMPTY if value.is_a?(TrueClass) || value.is_a?(FalseClass)
114
+ if value.is_a?(String)
115
+ return EMPTY if value.strip.empty?
116
+ elsif value.is_a?(Array)
117
+ return value.flatten.map { |i| normalize(i.to_s) }
118
+ elsif value.is_a?(Hash)
119
+ return value.map { |k, v| [k, normalize(v.to_s)] }.to_h
120
+ elsif value.is_a?(DateTime)
121
+ return EMPTY if value.strftime('%F %T') == EMPTY_DATE
122
+ elsif value.is_a?(Time)
123
+ return normalize(value.to_datetime)
124
+ end
125
+ value
89
126
  end
90
127
 
91
- def print_warnings
92
- str = ''
93
- @warnings.each do |w|
94
- str << "# WARNING: #{w}\n"
128
+ def init_raw_values(raw)
129
+ self.class::EXIFTOOL_TAGS.each do |tag|
130
+ @raw_values[tag] = normalize(raw[tag])
95
131
  end
96
- str
97
132
  end
98
133
 
99
- def print_lines
100
- str = ''
101
- @write_script_lines.each do |l|
102
- unless @warnings.empty?
103
- str << '# ' unless @force_write
104
- end
105
- str << "#{l}\n"
134
+ def validate
135
+ @errors = []
136
+ @value_invalid = []
137
+ return if Tag.empty?(@value)
138
+ validate_type
139
+ end
140
+
141
+ def validate_string_size(value)
142
+ bsize = value.bytesize
143
+ return true if bsize <= self.class::MAX_BYTESIZE
144
+ @errors << %(#{tag_name}: '#{value}' is #{bsize - self.class::MAX_BYTESIZE} bytes longer than allowed #{self.class::MAX_BYTESIZE})
145
+ false
146
+ end
147
+
148
+ def validate_vs_previous
149
+ @warnings = []
150
+ return if @previous.nil?
151
+ @previous.raw_values.each do |tag, val|
152
+ @warnings << "#{tag_name} has original value: #{tag}='#{val}'" unless Tag.empty?(val)
106
153
  end
107
- str
154
+ @warnings.freeze
155
+ end
156
+
157
+ def freeze_values
158
+ @value.freeze
159
+ @raw_values.freeze
160
+ @errors.freeze
161
+ @value_invalid.freeze
162
+ @warnings.freeze
108
163
  end
109
164
  end
110
165
  end
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ # encoding: UTF-8
4
+ # (c) ANB Andrew Bizyaev
5
+
6
+ require_relative '_tag'
7
+
8
+ module ExifTagger
9
+ module Tag
10
+ class TagArrayOfStrings < Tag
11
+ private
12
+
13
+ def get_from_raw
14
+ @raw_values.each_value do |v|
15
+ v = v.split('; ') if v.is_a?(String)
16
+ return v unless Tag.empty?(v)
17
+ end
18
+ EMPTY
19
+ end
20
+
21
+ def validate_type
22
+ if @value.is_a?(Array)
23
+ @value.each do |val|
24
+ @value_invalid << val unless validate_string_size(val)
25
+ end
26
+ @value -= @value_invalid
27
+ else
28
+ @errors << %(#{tag_name}: '#{@value}' is a wrong type \(#{@value.class}\))
29
+ @value_invalid << @value
30
+ @value = EMPTY
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
  # encoding: UTF-8
3
4
  # (c) ANB Andrew Bizyaev
4
5
 
@@ -8,37 +9,34 @@ require 'date'
8
9
  module ExifTagger
9
10
  module Tag
10
11
  class TagDate < Tag
11
- MAX_BYTESIZE = 32 # no limit set in EXIF spec for Date
12
-
13
12
  private
14
13
 
15
- def validate
16
- case
17
- when @value.kind_of?(String)
18
- bsize = @value.bytesize
19
- if bsize > MAX_BYTESIZE
20
- @errors << %(#{tag_name}: '#{@value}' ) +
21
- %(is #{bsize - MAX_BYTESIZE} bytes longer than allowed #{MAX_BYTESIZE})
22
- @value_invalid << @value
23
- @value = ''
24
- end
25
- when @value.kind_of?(DateTime)
26
- if @value == DateTime.new(0)
27
- @errors << %(#{tag_name}: '#{@value}' zero Date)
28
- @value_invalid << @value
29
- @value = ''
30
- end
31
- when @value.kind_of?(Time)
32
- if @value == Time.new(0)
33
- @errors << %(#{tag_name}: '#{@value}' zero Date)
34
- @value_invalid << @value
35
- @value = ''
36
- end
14
+ def get_from_raw
15
+ @raw_values.each_value do |value|
16
+ return value unless Tag.empty?(value)
17
+ end
18
+ EMPTY
19
+ end
20
+
21
+ def make_date_from(tag_date = '', tag_time = '')
22
+ dcdt = %(#{tag_date} #{tag_time})
23
+ DateTime.parse(dcdt.sub(/^(\d+):(\d+):/, '\1-\2-'))
24
+ rescue ArgumentError
25
+ EMPTY
26
+ end
27
+
28
+ def validate_type
29
+ if @value.is_a?(String)
30
+ validate_string_size(@value)
31
+
32
+ elsif @value.is_a?(DateTime)
33
+
37
34
  else
38
- @errors << %(#{tag_name}: '#{@value}' is of wrong type (#{@value.class}))
39
- @value_invalid << @value
40
- @value = ''
35
+ @errors << %(#{tag_name}: '#{@value}' is a wrong type \(#{@value.class}\))
41
36
  end
37
+ return if @errors.empty?
38
+ @value_invalid << @value
39
+ @value = EMPTY
42
40
  end
43
41
  end
44
42
  end