From 5d00bb3e663ca1cde7fab547e7ff183ed14ba5d5 Mon Sep 17 00:00:00 2001 From: Guillem Date: Tue, 20 Aug 2024 15:12:57 +0200 Subject: [PATCH] Updated signature tool with PDF Forms --- lib/ilovepdf.rb | 3 + lib/ilovepdf/extra_upload_params/base.rb | 17 +++++ lib/ilovepdf/extra_upload_params/signature.rb | 23 +++++++ lib/ilovepdf/file.rb | 21 +++++- lib/ilovepdf/pdf_page.rb | 15 ++++ lib/ilovepdf/task.rb | 43 +++++++++--- lib/ilovepdf/tool/signature.rb | 10 ++- lib/ilovepdf/version.rb | 2 +- samples/signature_advanced.rb | 5 +- samples/signature_form_pdf.rb | 68 +++++++++++++++++++ 10 files changed, 191 insertions(+), 16 deletions(-) create mode 100644 lib/ilovepdf/extra_upload_params/base.rb create mode 100644 lib/ilovepdf/extra_upload_params/signature.rb create mode 100644 lib/ilovepdf/pdf_page.rb create mode 100644 samples/signature_form_pdf.rb diff --git a/lib/ilovepdf.rb b/lib/ilovepdf.rb index a0c69c5..47b437e 100755 --- a/lib/ilovepdf.rb +++ b/lib/ilovepdf.rb @@ -18,6 +18,9 @@ require "ilovepdf/task" require 'ilovepdf/element' require 'ilovepdf/request_payload/form_url_encoded' +require 'ilovepdf/extra_upload_params/base' +require 'ilovepdf/extra_upload_params/signature' +require 'ilovepdf/pdf_page' # Load tool classes require 'ilovepdf/tool/compress' diff --git a/lib/ilovepdf/extra_upload_params/base.rb b/lib/ilovepdf/extra_upload_params/base.rb new file mode 100644 index 0000000..9d9f255 --- /dev/null +++ b/lib/ilovepdf/extra_upload_params/base.rb @@ -0,0 +1,17 @@ +module Ilovepdf + module ExtraUploadParams + class Base + attr_accessor :extra_params + + def set_value(key,value) + self.extra_params||= {} + self.extra_params[key] = value + end + + def get_values() + self.extra_params + end + + end + end +end \ No newline at end of file diff --git a/lib/ilovepdf/extra_upload_params/signature.rb b/lib/ilovepdf/extra_upload_params/signature.rb new file mode 100644 index 0000000..2cd1f08 --- /dev/null +++ b/lib/ilovepdf/extra_upload_params/signature.rb @@ -0,0 +1,23 @@ +require 'ilovepdf/extra_upload_params/base' +module Ilovepdf + module ExtraUploadParams + + class Signature < Base + + def set_pdf_info(activate = true) + self.set_value(:pdfinfo,!!activate ? "1" : "0") + self + end + + def set_pdf_forms(activate = true) + is_active = !!activate + self.set_value(:pdfforms,is_active ? "1" : "0") + if is_active + self.set_pdf_info(true) + end + self + end + end + + end +end \ No newline at end of file diff --git a/lib/ilovepdf/file.rb b/lib/ilovepdf/file.rb index 85472c6..564336d 100755 --- a/lib/ilovepdf/file.rb +++ b/lib/ilovepdf/file.rb @@ -1,6 +1,6 @@ module Ilovepdf class File - attr_accessor :server_filename, :filename, :password, :info + attr_accessor :server_filename, :filename, :password, :info, :pdf_pages, :pdf_forms, :pdf_page_number attr_reader :rotate ROTATION_VALUES = [0, 90, 180, 270] @@ -21,6 +21,25 @@ def file_options h end + # pageNumber is an integer and it must be greater than 1 (1 is the first page) + def pdf_page_info(pageNumber) + pdf_page_string = self.pdf_pages.at(pageNumber-1) + width,height = 0.0 + return nil if !pdf_page_string.is_a?(String) + PdfPage.initialize_from_string(pdf_page_string) + end + + def last_pdf_page + self.pdf_pages + end + + def each_pdf_form_element + self.pdf_forms&.each do |pdf_form_element| + pdf_page = self.pdf_page_info(pdf_form_element['page']) + yield(pdf_form_element,pdf_page) + end + end + def rotate= degrees raise Errors::ArgumentEnumError.new(ROTATION_VALUES) unless ROTATION_VALUES.include? degrees @rotate = degrees diff --git a/lib/ilovepdf/pdf_page.rb b/lib/ilovepdf/pdf_page.rb new file mode 100644 index 0000000..5c49e64 --- /dev/null +++ b/lib/ilovepdf/pdf_page.rb @@ -0,0 +1,15 @@ +module Ilovepdf + class PdfPage + attr_accessor :width,:height + + def initialize(width, height) + self.width = width + self.height = height + end + + def self.initialize_from_string(string) + width, height = string.split("x").map(&:to_f) + PdfPage.new(width, height) + end + end +end \ No newline at end of file diff --git a/lib/ilovepdf/task.rb b/lib/ilovepdf/task.rb index 446c917..a306274 100755 --- a/lib/ilovepdf/task.rb +++ b/lib/ilovepdf/task.rb @@ -62,17 +62,17 @@ def files @files ||= [] end - def add_file(filepath) + def add_file(filepath, extra_upload_params = nil) raise ArgumentError.new("No file exists in '#{filepath}'") unless ::File.exist?(filepath) - file = perform_upload_request(filepath) + file = perform_upload_request(filepath,extra_upload_params) files << file - files.last + file end - def add_file_from_url(url) - file = perform_upload_url_request(url) + def add_file_from_url(url,extra_upload_params = nil) + file = perform_upload_url_request(url,extra_upload_params) files << file - files.last + file end def download(path=nil, create_directory: false) @@ -209,7 +209,7 @@ def perform_start_request response end - def perform_upload_request filepath + def perform_upload_request filepath, tool_additional_params = nil request_opts = { body: { multipart: true, @@ -218,12 +218,16 @@ def perform_upload_request filepath file: ::File.new(filepath, 'rb') } } + if tool_additional_params.is_a?(::Ilovepdf::ExtraUploadParams::Base) + request_opts[:body].merge!(tool_additional_params.extra_params.transform_keys(&:to_sym)) + end + # filepath response = send_request('post', 'upload', request_opts) - File.new(response.body['server_filename'], Pathname.new(filepath).basename.to_s) + self.get_file_from_response(response.body,filepath) end - def perform_upload_url_request url + def perform_upload_url_request url,tool_additional_params = nil request_opts = { body: { multipart: true, @@ -232,8 +236,11 @@ def perform_upload_url_request url cloud_file: url } } + if tool_additional_params.is_a?(::Ilovepdf::ExtraUploadParams::Base) + request_opts[:body].merge!(tool_additional_params.extra_params.transform_keys(&:to_sym)) + end response = send_request('post', 'upload', request_opts) - File.new(response.body['server_filename'], Pathname.new(url).basename.to_s) + self.get_file_from_response(response.body,url) end def file_submit_params @@ -254,5 +261,21 @@ def extract_api_params result end end + + private + + def get_file_from_response(response_body,filePathOrUrl) + file = File.new(response_body['server_filename'], Pathname.new(filePathOrUrl).basename.to_s) + if response_body['pdf_pages'] + file.pdf_pages = response_body['pdf_pages'] + end + if response_body['pdf_page_number'] + file.pdf_page_number = response_body['pdf_page_number'].to_i + end + if response_body['pdf_forms'] + file.pdf_forms = response_body['pdf_forms'] + end + file + end end end diff --git a/lib/ilovepdf/tool/signature.rb b/lib/ilovepdf/tool/signature.rb index 2449c6a..1f34aa8 100644 --- a/lib/ilovepdf/tool/signature.rb +++ b/lib/ilovepdf/tool/signature.rb @@ -73,10 +73,16 @@ def reminders=(value) value end + def upload_brand_logo_file(logoPath) + perform_upload_request(logoPath) + end + + def upload_brand_logo_file_from_url(logoUrl) + perform_upload_url_request(logoUrl) + end def add_brand(name:,logo:) - brand_logo_file = perform_upload_request(logo) - @brand_logo = brand_logo_file.server_filename + @brand_logo = logo.server_filename @brand_name = name end diff --git a/lib/ilovepdf/version.rb b/lib/ilovepdf/version.rb index 35a7f49..b51fd02 100755 --- a/lib/ilovepdf/version.rb +++ b/lib/ilovepdf/version.rb @@ -1,3 +1,3 @@ module Ilovepdf - VERSION = "1.3.4" + VERSION = "1.4.0" end diff --git a/samples/signature_advanced.rb b/samples/signature_advanced.rb index 24c7406..a59c69d 100644 --- a/samples/signature_advanced.rb +++ b/samples/signature_advanced.rb @@ -6,7 +6,9 @@ priv_key = "YOUR_PRIVATE_KEY" my_task = Ilovepdf::Tool::Signature.new(pub_key, priv_key) -my_task.add_brand(name: "my company name",logo: "/path/to/logo/logo.png") +# Upload brand logo +brand_logo = my_task.upload_brand_logo_file("/path/to/logo/logo.png") +my_task.add_brand(name: "my company name",logo: brand_logo) my_task.language = "es" my_task.lock_order = false # if false, allows receivers of signer type to sign in parallel. # if true receivers of signer type must sign sequentially in order. @@ -23,7 +25,6 @@ signer = Ilovepdf::Signature::Receiver.new(:signer,'name','email@email.com') signer.phone = "34677231431" #Phone number with the country prefix at the beginning => "+34677231431", make sure you have enough credits. -signer.phone = "34677231431" #Phone number with the country prefix at the beginning => "+34677231431", make sure you have enough credits. signature_element = Ilovepdf::Signature::SignatureElement.new(file1) signature_element.set_position(x: 20,y: -20) diff --git a/samples/signature_form_pdf.rb b/samples/signature_form_pdf.rb new file mode 100644 index 0000000..bbd35ed --- /dev/null +++ b/samples/signature_form_pdf.rb @@ -0,0 +1,68 @@ +require "bundler/setup" +require 'ilovepdf' + +# You can call task class directly +pub_key = "YOUR_PUBLIC_KEY" +priv_key = "YOUR_PRIVATE_KEY" +my_task = Ilovepdf::Tool::Signature.new(pub_key, priv_key) + +# Send additional parameters to obtain the information about the PDF and the information about the form elements +extra_params = Ilovepdf::ExtraUploadParams::Signature.new +extra_params.set_pdf_forms(true).set_pdf_info(true) +file = my_task.add_file('/path/to/file/sample.pdf',extra_params) + +# Define the signer +signer = Ilovepdf::Signature::Receiver.new(:signer,'name','email@email.com') + +# Get number of pages +file.pdf_page_number +# get specific pdf page +pdf_page = file.pdf_page_info(1) +puts pdf_page.width +puts pdf_page.height + +# Now we can loop over all of the form elements on the PDF +file.each_pdf_form_element do |form_element, pdf_page_info| + type_of_field = form_element["typeOfField"] + next unless ["textbox", "signature"].include?(type_of_field) + + field_id = form_element["fieldId"] + widgets = form_element["widgetsInformation"] + position = widgets[0] + current_page = position["page"] + + left_pos = position["left"] + top_position = position["top"] - pdf_page_info["height"] + size = (position["left"] - position["bottom"]).floor + + if type_of_field == "textbox" + if form_element["multilineFlag"] || form_element["passwordFlag"] + next + end + + text_value = form_element["textValue"] + # For instance, we want to create an input element if the label of the form contains the word "Input". + if field_id.include?('_input') + input_element = ElementInput.new + input_element.set_position(left_pos, top_position) + .set_size(size) + .set_label(text_value) + .set_pages(current_page.to_s) + elements << input_element + else + text_element = ElementText.new + text_element.set_position(left_pos, top_position) + .set_size(size) + .set_text(text_value) + .set_pages(current_page.to_s) + elements << text_element + end + elsif type_of_field == "signature" + signature_element = ElementSignature.new + signature_element.set_position(left_pos, top_position) + .set_size(size) + elements << signature_element + end +end + + \ No newline at end of file