module Scrivito # @api public # The Binary class represents the data stored in a binary attribute of an Obj # or Widget class Binary attr_reader :id, :transformation_definition def initialize(id, is_public, transformation_definition = nil, original = nil) @id = id @is_public = !!is_public @transformation_definition = transformation_definition @original = original end # @api public # Some Scrivito data is considered private, i.e. it is not currently intended # for the general public, for example content in a workspace that has not # been published yet. # @return [Boolean] def private? !@is_public end def public? @is_public end # @api public # The URL for accessing the binary data and downloading it using an HTTP GET request. # # @note URLs for private content have an expiration time in order to protect them. # Therefore, the URL should be accessed immediately after it has been returned # (i.e. within a couple of minutes). Accessing it after expiration causes an error. # # The URLs should not be used for long-term storage since they are no longer # accessible hours or days after they have been generated. # @return [String] the URL at which this content is available. def url find_url('get') end def url_from_cache blob_data = CmsBackend.instance .find_blob_data_from_cache(id, access_type, 'get', transformation_definition) if blob_data blob_data['url'] end end # @api public # the filename of this binary data, for example "my_image.jpg" # @return [String] the filename of binary def filename File.basename(URI(url).path) end # @api public # the content type of this binary data, for example "image/jpeg" # @return [String] content type def content_type headers[:content_type] end # @api public # the length of this binary data, in bytes. # @return [Integer] number of bytes def content_length headers[:content_length].to_i end # # Returns a transformed {Scrivito::Binary}. # # @api beta # # Calling this method will not change the binary, but instead return a copy of it, # transformed using the +definition+. # # If the original binary has already been transformed, then the returned binary will be a # combination of the transformations. Thus the transformations can be chained (see examples). # # The transformed data is calculated "lazily", so calling {Scrivito::Binary#transform} will not # trigger any calculation. The calculation will be triggered only if data is accessed, for example # via {Scrivito::Binary#url}. # # @param [Hash] definition transformation definition # # @option definition [Fixnum,String] :width The width in pixels of the output image. Must be a # positive integer. # # If only this dimension is specified, the other dimension will be calculated automatically to # preserve the aspect ratio of the input image. # # If the +fit+ parameter is set to +:clip+, then the actual output one of width and height may # be equal to or less than the dimensions you specify to prevent distortion. # # If neither +width+ nor +height+ is given, the width and height of the input image # will be used. # # The maximum output image size width + height = 4096 pixels. The given width and height may be # adjusted to accomodate this limit. The output image will never be larger than the source # image, i.e. the given width and height may be adjusted to keep the output image from exceeding # the dimensions of the input image. # # When the given width and height are adjusted, the aspect ratio is preserved. # # @option definition [Fixnum,String] :height The height in pixels of the output image. Must be a # positive integer. # # If only this dimension is specified, the other dimension will be calculated automatically to # preserve the aspect ratio of the input image. # # If the +fit+ parameter is set to +:clip+, then the actual output one of width and height may # be equal to or less than the dimensions you specify to prevent distortion. # # If neither +width+ nor +height+ is given, the width and height of the input image # will be used. # # The maximum output image size width + height = 4096 pixels. The given width and height may be # adjusted to accomodate this limit. The output image will never be larger than the source # image, i.e. the given width and height may be adjusted to keep the output image from exceeding # the dimensions of the input image. # # When the given width and height are adjusted, the aspect ratio is preserved. # # @option definition [Symbol,String] :fit Controls how the tranformed image is fitted to the # given width and heigth. Valid values are +:clip+ and +:crop+. The default value is +:clip+. # # If set to +:clip+ it resizes the image to fit within the width and height boundaries without # cropping or distorting the image. The resulting image is assured to match one of the # constraining dimensions, while the other dimension is altered to maintain the same aspect # ratio of the input image. # # If set to +:crop+ it resizes the image to fill the given width and height and preserves the # aspect ration by cropping any excess image data. The resulting image will match both the given # width and height without distorting the image. The crop is done centered, i.e. the center of # the image is preserved. # # @option definition [Fixnum,String] :quality Controls the output quality of lossy file formats. # Applies when the format is +"jpg"+. Valid values are in the range from +0+ to +100+. # The default value is +75+. # # @return [Scrivito::Binary] transformed binary # # @example Crop image to fit into 50 x 50 pixel square # @obj.blob.transform(width: 50, height: 50, fit: :crop) # # @example Convert image to a low quality JPEG # @obj.blob.transform(quality: 25) # # @example Combine the both transformations # @obj.blob.transform(width: 50, height: 50, fit: :crop).transform(quality: 25) # def transform(definition) self.class.new(id, public?, (transformation_definition || {}).merge(definition), original) end # # Returns whether a binary is transformed. # @api beta # def transformed? !!transformation_definition end # # Returns the transformation original of a binary. # # @api beta # # If a binary is a result of a transformation, then its original binary is returned. # Otherwise +self+. # # @return [Scrivito::Binary] original binary # # @example # @obj.blob.id # => "abc123" # @obj.blob.original.id # => "abc123" # @obj.blob.transform(width: 50).original.id # => "abc123" # @obj.blob.transform(width: 50).transform(height: 50).original.id # => "abc123" # def original @original || self end private def public_content? !!@public_content end def headers CmsBackend.instance.find_blob_metadata(id, find_url('head')) end def find_url(verb) CmsBackend.instance.find_blob_data(id, access_type, verb, transformation_definition)['url'] rescue ClientError => e case e.backend_code when 'binary.unprocessable.image.transform.source_too_large', 'binary.unprocessable.image.transform.source_type_invalid' raise TransformationSourceError.new(e.message, e.backend_code) when 'binary.unprocessable.image.transform.invalid_config' raise TransformationDefinitionError.new(e.message, e.backend_code) else raise e end end def access_type public? ? 'public_access' : 'private_access' end end end