Skip to content
Snippets Groups Projects
Commit af931aa3 authored by Lucas García's avatar Lucas García
Browse files

feat: gf vat-id field

parent ca13e46d
No related branches found
No related tags found
No related merge requests found
......@@ -16,15 +16,16 @@ abstract class Integration extends Singleton
{
foreach (static::$fields as $Field) {
$field = $Field::get_instance();
add_action('init', function () use ($field) {
$field->init();
});
}
add_action('init', [$this, 'init']);
}
public function init()
{
foreach (static::$fields as $Field) {
$field = $Field::get_instance();
$field->init();
}
}
public function submit($payload, $endpoints, $files, $form_data)
......
......@@ -34,6 +34,12 @@ class Addon extends GFAddOn
return self::$_instance;
}
function __construct()
{
$this->_full_path = __FILE__;
parent::__construct();
}
/**
* Include the field early so it is available when entry exports are being performed.
*/
......
......@@ -3,6 +3,7 @@
namespace WPCT_ERP_FORMS\GF\Fields\Iban;
use GF_Field;
use Exception;
class GFField extends GF_Field
{
......@@ -142,7 +143,7 @@ class GFField extends GF_Field
*
* @return array
*/
function get_form_editor_field_settings()
public function get_form_editor_field_settings()
{
return [
'conditional_logic_field_setting',
......@@ -193,8 +194,8 @@ class GFField extends GF_Field
$html_input_type = 'password';
}
$logic_event = !$is_form_editor && !$is_entry_detail ? $this->get_conditional_logic_event('keyup') : '';
$id = (int)$this->id;
$logic_event = ''; // !$is_form_editor && !$is_entry_detail ? $this->get_conditional_logic_event('keyup') : '';
$id = (int) $this->id;
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
$value = esc_attr($value);
......@@ -218,15 +219,18 @@ class GFField extends GF_Field
*/
public function validate($value, $form)
{
if (strlen($value) < 5) return false;
$value = strtolower(str_replace(' ', '', $value));
try {
if (strlen($value) < 5) {
throw new Exception();
}
$value = strtolower(str_replace(' ', '', $value));
$country_exists = array_key_exists(substr($value, 0, 2), $this->_countries);
$country_conform = strlen($value) == $this->_countries[substr($value, 0, 2)];
$country_exists = array_key_exists(substr($value, 0, 2), $this->_countries);
$country_conform = strlen($value) == $this->_countries[substr($value, 0, 2)];
try {
if (!($country_exists && $country_conform)) throw new Exception();
if (!($country_exists && $country_conform)) {
throw new Exception();
}
$moved_char = substr($value, 4) . substr($value, 0, 4);
$move_char_array = str_split($moved_char);
......@@ -234,7 +238,9 @@ class GFField extends GF_Field
foreach ($move_char_array as $key => $val) {
if (!is_numeric($move_char_array[$key])) {
if (!isset($this->_chars[$val])) throw new Exception();
if (!isset($this->_chars[$val])) {
throw new Exception();
}
$move_char_array[$key] = $this->_chars[$val];
}
......@@ -244,13 +250,28 @@ class GFField extends GF_Field
if (bcmod($new_string, '97') != 1) {
throw new Exception();
}
} catch (Exception) {
} catch (Exception $e) {
$this->failed_validation = true;
if (!empty($this->errorMessage)) {
$this->validation_message = $this->errorMessage;
} else {
$this->validation_message = __('The IABN you inserted is not valid.');
}
$this->validation_message = empty($this->errorMessage) ? __('The IBAN you\'ve inserted is not valid.', 'wpct-erp-forms') : $this->errorMessage;
}
}
public function get_form_inline_script_on_page_render($form)
{
ob_start();
?>
const input = document.querySelector('#input_<?= $form['id'] ?>_<?= $this->id ?>');
input.addEventListener("input", ({ target }) => {
const value = String(target.value);
const chars = value.split("").filter((c) => c !== " ");
target.value = chars.reduce((repr, char, i) => {
if (i % 4 === 0) {
char = " " + char;
}
return repr + char;
});
});
<?php
return ob_get_clean();
}
}
<?php
namespace WPCT_ERP_FORMS\GF\Fields\VatID;
use GFForms;
use GFAddOn;
use GF_Fields;
GFForms::include_addon_framework();
class Addon extends GFAddOn
{
protected $_version = '1.0';
protected $_slug = 'wpct-erp-forms-vat-id-field';
protected $_title = 'Gravity Forms VatID validated text field';
protected $_short_title = 'VatID field';
protected $_full_path;
/**
* @var object $_instance If available, contains an instance of this class.
*/
private static $_instance = null;
/**
* Returns an instance of this class, and stores it in the $_instance property.
*
* @return object $_instance An instance of this class.
*/
public static function get_instance()
{
if (self::$_instance == null) {
self::$_instance = new self();
}
return self::$_instance;
}
public function __construct()
{
$this->_full_path = __FILE__;
parent::__construct();
}
/**
* Include the field early so it is available when entry exports are being performed.
*/
public function pre_init()
{
parent::pre_init();
if (
$this->is_gravityforms_supported() &&
class_exists('GF_Field') &&
class_exists('GF_Fields')
) {
GF_Fields::register(new GFField());
}
}
}
<?php
namespace WPCT_ERP_FORMS\GF\Fields\VatID;
use WPCT_ERP_FORMS\Abstract\Field as BaseField;
use GFAddOn;
require_once 'class-addon.php';
require_once 'class-field.php';
class FieldAdapter extends BaseField
{
public function __construct()
{
add_action('gform_loaded', [$this, 'register']);
}
public function register()
{
if (!method_exists('GFForms', 'include_addon_framework')) return;
GFAddOn::register(Addon::class);
}
public function init()
{
}
}
<?php
namespace WPCT_ERP_FORMS\GF\Fields\VatID;
use Exception;
use GF_Field;
class GFField extends GF_Field
{
private static $_dni_regex = '/^(\d{8})([A-Z])$/';
private static $_cif_regex = '/^([ABCDEFGHJKLMNPQRSUVW])(\d{7})([0-9A-J])$/';
private static $_nie_regex = '/^[XYZ]\d{7,8}[A-Z]$/';
/**
* @var string $type The field type.
*/
public $type = 'vat-id-field';
/**
* Return the field title, for use in the form editor.
*
* @return string
*/
public function get_form_editor_field_title()
{
return esc_attr__('VAT ID');
}
/**
* Assign the field button to the Advanced Fields group.
*
* @return array
*/
public function get_form_editor_button()
{
return [
'group' => 'advanced_fields',
'text' => $this->get_form_editor_field_title(),
];
}
/**
* The settings which should be available on the field in the form editor.
*
* @return array
*/
public function get_form_editor_field_settings()
{
return [
'conditional_logic_field_setting',
'error_message_setting',
'label_setting',
'label_placement_setting',
'admin_label_setting',
'size_setting',
'password_field_setting',
'rules_setting',
'visibility_setting',
'duplicate_setting',
'default_value_setting',
'placeholder_setting',
'description_setting',
'css_class_setting',
];
}
/**
* Enable this field for use with conditional logic.
*
* @return bool
*/
public function is_conditional_logic_supported()
{
return true;
}
/**
* Define the fields inner markup.
*
* @param array $form The Form Object currently being processed.
* @param string|array $value The field value. From default/dynamic population, $_POST, or a resumed incomplete submission.
* @param null|array $entry Null or the Entry Object currently being edited.
*
* @return string
*/
public function get_field_input($form, $value = '', $entry = null)
{
$form_id = absint($form['id']);
$is_entry_detail = $this->is_entry_detail();
$is_form_editor = $this->is_form_editor();
$html_input_type = 'text';
if ($this->enablePasswordInput && !$is_entry_detail) {
$html_input_type = 'password';
}
$logic_event = ''; // !$is_form_editor && !$is_entry_detail ? $this->get_conditional_logic_event('keyup') : '';
$id = (int) $this->id;
$field_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$id" : 'input_' . $form_id . "_$id";
$value = esc_attr($value);
$size = $this->size;
$class_suffix = $is_entry_detail ? '_admin' : '';
$class = $size . $class_suffix;
$tabindex = $this->get_tabindex();
$disabled_text = $is_form_editor ? 'disabled="disabled"' : '';
$placeholder_attribute = $this->get_field_placeholder_attribute();
$required_attribute = $this->isRequired ? 'aria-required="true"' : '';
$invalid_attribute = $this->failed_validation ? 'aria-invalid="true"' : 'aria-invalid="false"';
$input = "<input name='input_{$id}' id='{$field_id}' type='{$html_input_type}' value='{$value}' class='{$class}' {$tabindex} {$logic_event} {$placeholder_attribute} {$required_attribute} {$invalid_attribute} {$disabled_text}/>";
return sprintf("<div class='ginput_container ginput_container_text'>%s</div>", $input);
}
/**
* Validate Field
*/
public function validate($value, $form)
{
try {
if (strlen($value) < 5) {
throw new Exception();
}
$value = strtolower(str_replace(' ', '', $value));
$value = preg_replace('/\s/', '', strtoupper($value));
$valid = false;
$type = $this->id_type($value);
switch ($type) {
case 'dni':
$valid = $this->validate_dni($value);
break;
case 'nie':
$valid = $this->validate_nie($value);
break;
case 'cif':
$valid = $this->validate_cif($value);
break;
}
if (!$valid) {
throw new Exception();
}
} catch (Exception $e) {
$this->failed_validation = true;
$this->validation_message = empty($this->errorMessage) ? __('The VAT number you\'ve inserted is not valid.', 'wpct-erp-forms') : $this->errorMessage;
}
}
private function id_type($value)
{
if (preg_match(GFField::$_dni_regex, $value)) {
return 'dni';
} elseif (preg_match(GFField::$_nie_regex, $value)) {
return 'nie';
} elseif (preg_match(GFField::$_cif_regex, $value)) {
return 'cif';
}
}
private function validate_dni($value)
{
$dni_letters = 'TRWAGMYFPDXBNJZSQVHLCKE';
$number = (int) substr($value, 0, 8);
$index = $number % 23;
$letter = substr($dni_letters, $index, 1);
return $letter == substr($value, 8, 9);
}
private function validate_nie($value)
{
$nie_prefix = substr($value, 0, 1);
switch ($nie_prefix) {
case 'X':
$nie_prefix = 0;
break;
case 'Y':
$nie_prefix = 1;
break;
case 'Z':
$nie_prefix = 2;
break;
}
return $this->validate_dni($nie_prefix . substr($value, 1, 9));
}
private function validate_cif($value)
{
preg_match(GFField::$_cif_regex, $value, $matches);
$letter = $matches[1];
$number = $matches[2];
$control = $matches[3];
$even_sum = 0;
$odd_sum = 0;
$n = null;
for ($i = 0; $i < strlen($number); $i++) {
$n = (int) $number[$i];
if ($i % 2 === 0) {
// Odd positions are multiplied first.
$n *= 2;
// If the multiplication is bigger than 10 we need to adjust
$odd_sum += $n < 10 ? $n : $n - 9;
// Even positions
// Just sum them
} else {
$even_sum += $n;
}
}
$control_digit = 10 - (int) substr(strval($even_sum + $odd_sum), -1);
$control_letter = substr('JABCDEFGHI', $control_digit, 1);
if (preg_match('/[ABEH]/', $letter)) {
// Control must be a digit
return (int) $control === $control_digit;
} elseif (preg_match('/[KPQS]/', $letter)) {
// Control must be a letter
return (string) $control === $control_letter;
} else {
// Can be either
return (int) $control === $control_digit || (string) $control === $control_letter;
}
}
}
......@@ -6,17 +6,20 @@ use Exception;
use TypeError;
use WPCT_ERP_FORMS\Abstract\Integration as BaseIntegration;
use WPCT_ERP_FORMS\GF\Fields\Iban\FieldAdapter as IbanField;
use WPCT_ERP_FORMS\GF\Fields\VatID\FieldAdapter as VatIDField;
require_once 'attachments.php';
require_once 'fields-population.php';
// Fields
require_once dirname(__FILE__, 3) . '/fields/gf/iban/class-field-adapter.php';
require_once dirname(__FILE__, 3) . '/fields/gf/vat-id/class-field-adapter.php';
class Integration extends BaseIntegration
{
public static $fields = [
IbanField::class
IbanField::class,
VatIDField::class,
];
protected function __construct()
......@@ -24,6 +27,8 @@ class Integration extends BaseIntegration
add_action('gform_after_submission', function ($entry, $form) {
$this->do_submission($entry, $form);
}, 10, 2);
parent::__construct();
}
public function serialize_form($form)
......@@ -58,21 +63,21 @@ class Integration extends BaseIntegration
$inputs = $field->get_entry_inputs();
if (is_array($inputs)) {
$inputs = array_map(function ($input) {
return ['name' => $input['name'], 'label' => $input['label'], 'id' => $input['id']];
}, array_filter($inputs, function ($input) {
return $input['name'];
}));
} else {
$inputs = [];
}
$options = [];
if (is_array($field->choices)) {
$options = array_map(function ($opt) {
return ['value' => $opt['value'], 'label' => $opt['text']];
}, $field->choices);
}
$inputs = array_map(function ($input) {
return ['name' => $input['name'], 'label' => $input['label'], 'id' => $input['id']];
}, array_filter($inputs, function ($input) {
return $input['name'];
}));
} else {
$inputs = [];
}
$options = [];
if (is_array($field->choices)) {
$options = array_map(function ($opt) {
return ['value' => $opt['value'], 'label' => $opt['text']];
}, $field->choices);
}
return [
'id' => $field->id,
......@@ -81,8 +86,8 @@ class Integration extends BaseIntegration
'label' => $field->label,
'required' => $field->isRequired,
'options' => $options,
'inputs' => $inputs,
'conditional' => is_array($field->conditionalLogic) && $field->conditionalLogic['enabled'],
'inputs' => $inputs,
'conditional' => is_array($field->conditionalLogic) && $field->conditionalLogic['enabled'],
];
}
......
......@@ -36,6 +36,9 @@ require_once 'includes/class-settings.php';
require_once 'custom-blocks/form/form.php';
require_once 'custom-blocks/form-control/form-control.php';
require_once 'includes/fields/gf/iban/class-field-adapter.php';
require_once 'includes/fields/gf/vat-id/class-field-adapter.php';
class Wpct_Erp_Forms extends Abstract\Plugin
{
private $_integrations = [];
......@@ -61,10 +64,6 @@ class Wpct_Erp_Forms extends Abstract\Plugin
public function init()
{
foreach ($this->_integrations as $integration) {
$integration->init();
}
add_action('wp_enqueue_scripts', [$this, 'enqueue_scripts']);
}
......@@ -106,4 +105,4 @@ class Wpct_Erp_Forms extends Abstract\Plugin
add_action('plugins_loaded', function () {
$plugin = Wpct_Erp_Forms::get_instance();
}, 10);
}, 5);
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment