page_template.rb 8.74 KB
require 'zip'
require 'kanjai/template_parser'

module Kanjai
  class PageTemplate < ActiveRecord::Base

    self.table_name = 'kanjai_templates'

    validates :title, :presence => true

    has_many :pages, dependent: :nullify
    has_many  :template_parts, :dependent => :destroy

    has_many :page_content_markers, as: :reference, :dependent => :destroy
    accepts_nested_attributes_for :page_content_markers

    has_many :template_statics, dependent: :destroy

    after_destroy :empty_template_content

    default_scope { order('title') }

    after_save :move_file

    def get_file_path
      "templates/#{self.id}/"
    end

    def template_content_path
      "templates/#{self.id}/template_content/"
    end

    def template_content_url
      "https://#{S3_BUCKET.name}.s3.amazonaws.com/templates/#{self.id}/template_content/"
    end

    def unzip_content
      if self.original_file_name
        tempfile = S3_BUCKET.object("#{self.get_file_path}#{self.original_file_name}")
        unless tempfile.nil?
          io = StringIO.new
          tempfile.get({
                         response_target: io
                     })
          self.empty_template_content

          @zip_file = Zip::Zip.new
          @zip_file.read(io)


          @zip_file.get_list_file.each do |file_name|
              content = @zip_file.get_content(file_name)
              #set correct path to js and css file
              if file_name == 'kanjai.html'

                self.template_parts.delete_all

                #find all subparts
                parser = TemplateParser.new(content)
                static_elements = parser.find_static_elements

                #check alredy exist static elements
                self.page_content_markers.each do |item|
                  element = static_elements.select{|p| p[:name] == item.marker}.first
                  if element
                    if item.marker_type == element[:type]
                      item.update_column(:marker_name, element[:itemName]) if item.marker_name != element[:itemName]
                    else
                      item.destroy
                    end
                  else
                    item.destroy
                  end
                end

                self.template_statics.delete_all

                static_elements.each do |item|
                  self.template_statics.create(
                    marker: item[:name],
                    marker_type: item[:type],
                    marker_name: item[:itemName]
                  )
                end

                parser.find_subparts.each do |item|
                  self.template_parts.create(
                      name: item[:name],
                      part_type: item[:type],
                      code: item[:code],
                      source: item[:source],
                      elements: item[:elements],
                      field_options: item[:field_options]
                  )

                  new_markers_general = item[:field_options].select{|item| item[:attributes]['repeat'] == 'false' }.collect{|item| item[:name] }
                  new_markers_repeat = item[:field_options].select{|item| item[:attributes]['repeat'] == 'true' }.collect{|item| item[:name] }

                  Kanjai::PageContent.joins(page: :page_template).where(type_content: item[:code], kanjai_templates: {id: self.id}).each do |page_content|
                    if page_content.page_content_markers.count == 0
                      page_content.build_markers(item[:code], true)
                    else
                      langs = page_content.page_content_markers.pluck(:lang).uniq
                      row_indexes = page_content.page_content_markers.pluck(:row_item).uniq
                      langs.each do |lang|
                        row_indexes.each do |index|

                          work_new_markers = index.to_i == 0 ? new_markers_general : new_markers_repeat
                          #delete not exist more markers
                          page_content.page_content_markers.where(lang: lang, row_item: index).where.not(marker: work_new_markers).delete_all

                          exist_markers = page_content.page_content_markers.where(lang: lang, row_item: index).pluck(:marker)
                          item[:field_options].select{|item| item[:attributes]['repeat'] == (index.to_i == 0 ? 'false' : 'true')  }.each do |marker|
                            unless exist_markers.include?(marker[:name])
                              page_content.page_content_markers.create(
                                marker: marker[:name],
                                row_item: index, 
                                marker_name: marker[:itemName],
                                lang: lang
                              )
                            end
                          end
                        end
                      end
                    end
                  end
                end

                content = parser.without_subparts

                doc = Nokogiri::HTML(content, nil, 'UTF-8')
                doc.css("link").each do |x|
                  css_link = x['href']
                  unless css_link.match(/^(http:|https:)/)
                    x['href'] = self.template_content_url + css_link
                  end
                end

                doc.css("script[@src]").each do |x|
                  js_link = x['src']
                  unless js_link.match(/^(http:|https:)/)
                    x['src'] = self.template_content_url + js_link
                  end
                end

                doc.css("img[@src]").each do |x|
                  image_link = x['src']
                  unless image_link.match(/^(http:|https:)/)
                    x['src'] = self.template_content_url + image_link
                  end
                end

                content = doc.to_html
              end

              if File.extname(file_name) == '.css'
                S3_BUCKET.put_object({
                                       acl: 'public-read',
                                       body: content,
                                       content_type: 'text/css',
                                       key: self.template_content_path + file_name
                                     })
              elsif File.extname(file_name).to_s.downcase == '.svg'
                S3_BUCKET.put_object({
                                       acl: 'public-read',
                                       body: content,
                                       content_type: 'image/svg+xml',
                                       key: self.template_content_path + file_name
                                     })                
              else
                S3_BUCKET.put_object({
                                       acl: 'public-read',
                                       body: content,
                                       key: self.template_content_path + file_name
                                     })
              end




          end


        end
        self.update_attribute(:unzip, true)
      end
    end

    def empty_template_content
      S3_BUCKET.objects(prefix: self.template_content_path).delete
    end

    def get_html_content
      #if self.unzip == true
        if S3_BUCKET.object("#{self.template_content_path}kanjai.html").exists?
          io = StringIO.new
          S3_BUCKET.object("#{self.template_content_path}kanjai.html").get({
            response_target: io
          })
          return io.read
        end

      #end

      return ''
    end

    def self.get_marker(layer)
      layer.scan(/###\w+###/)
    end

    def attachment_file_name=(url)
      self[:attachment_file_name] = url
      uri = URI.parse(url)
      file_name = File.basename(uri.path)
      self.original_file_name = file_name
    end

    def file_expiring_url
      url = nil
      if self.original_file_name.present?
        object = S3_BUCKET.object("#{self.get_file_path}#{self.original_file_name}")
        if object
          url = object.presigned_url(:get, expires_in: 3600)
        end
      end
      url
    end

    def human_title
      if original_file_name.to_s.empty?
        I18n.t('admin.template_status.not_file')
      elsif unzip
        I18n.t('admin.template_status.unzip')
      else
        I18n.t('admin.template_status.zip')
      end
    end

    private 

    def move_file
      if attachment_file_name.present? && attachment_file_name.include?('tmp/templates')
        obj_path = URI.parse(attachment_file_name).path

        file_name = File.basename(obj_path)

        s3 = Aws::S3::Client.new(region: ENV['S3_REGION'])
        s3.copy_object(bucket: ENV['S3_BUCKET'], copy_source: "/#{ENV['S3_BUCKET']}#{obj_path}", key: "#{get_file_path}#{file_name}")
        self.update_column(:attachment_file_name, "#{get_file_path}#{file_name}")
      end
    end


  end
end