From c39db30fce6cb349f1b14bffd48328a20ef4026f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lucas=20Garc=C3=ADa?= <lucas@codeccoop.org>
Date: Tue, 23 Jan 2024 13:38:20 +0100
Subject: [PATCH] feat: custom fields

---
 includes/fields/BaseField.php                 |  25 +++
 .../fields => fields/gf}/iban/Addon.php       |   6 +-
 .../fields => fields/gf}/iban/Field.php       |   4 +-
 includes/fields/gf/iban/index.php             |  24 +++
 includes/fields/gf/index.php                  |   3 +
 includes/fields/index.php                     |  11 ++
 includes/fields/wpcf7/iban/index.php          | 183 ++++++++++++++++++
 includes/fields/wpcf7/index.php               |   3 +
 includes/integrations/Integration.php         |  13 +-
 .../{ => integrations/gf}/attachments.php     |   0
 .../gf}/fields-population.php                 |   0
 .../{gravityforms => gf}/index.php            |   8 +-
 .../gravityforms/fields/iban/index.php        |  13 --
 includes/integrations/index.php               |   8 +-
 .../{contactform7 => wpcf7}/index.php         |   4 +
 wpct-erp-forms.php                            |  18 +-
 16 files changed, 283 insertions(+), 40 deletions(-)
 create mode 100644 includes/fields/BaseField.php
 rename includes/{integrations/gravityforms/fields => fields/gf}/iban/Addon.php (88%)
 rename includes/{integrations/gravityforms/fields => fields/gf}/iban/Field.php (98%)
 create mode 100644 includes/fields/gf/iban/index.php
 create mode 100644 includes/fields/gf/index.php
 create mode 100644 includes/fields/index.php
 create mode 100644 includes/fields/wpcf7/iban/index.php
 create mode 100644 includes/fields/wpcf7/index.php
 rename includes/{ => integrations/gf}/attachments.php (100%)
 rename includes/{ => integrations/gf}/fields-population.php (100%)
 rename includes/integrations/{gravityforms => gf}/index.php (96%)
 delete mode 100644 includes/integrations/gravityforms/fields/iban/index.php
 rename includes/integrations/{contactform7 => wpcf7}/index.php (87%)

diff --git a/includes/fields/BaseField.php b/includes/fields/BaseField.php
new file mode 100644
index 0000000..aa0e311
--- /dev/null
+++ b/includes/fields/BaseField.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace WPCT_ERP_FORMS\Fields;
+
+use Exception;
+
+class BaseField
+{
+    private static $instances = [];
+
+    public static function get_instance()
+    {
+        $cls = static::class;
+        if (!isset(self::$instances[$cls])) {
+            self::$instances[$cls] = new static();
+        }
+
+        return self::$instances[$cls];
+    }
+
+    public function register()
+    {
+        throw new Exception('Method to overwrite by inheritance');
+    }
+}
diff --git a/includes/integrations/gravityforms/fields/iban/Addon.php b/includes/fields/gf/iban/Addon.php
similarity index 88%
rename from includes/integrations/gravityforms/fields/iban/Addon.php
rename to includes/fields/gf/iban/Addon.php
index 3aeac2a..cc9f9ae 100644
--- a/includes/integrations/gravityforms/fields/iban/Addon.php
+++ b/includes/fields/gf/iban/Addon.php
@@ -1,6 +1,6 @@
 <?php
 
-namespace WPCT_ERP_FORMS\IBAN_Field;
+namespace WPCT_ERP_FORMS\Fields\GF\Iban;
 
 use GFForms;
 use GFAddOn;
@@ -10,7 +10,7 @@ GFForms::include_addon_framework();
 
 class Addon extends GFAddOn
 {
-    protected $_version = WPCT_ERP_FORMS_IBAN_FIELD_VERSION;
+    protected $_version = '1.0';
     protected $_slug = 'wpct-erp-forms-iban-field';
     protected $_title = 'Gravity Forms IBAN validated text field';
     protected $_short_title = 'IBAN field';
@@ -45,7 +45,7 @@ class Addon extends GFAddOn
             class_exists('GF_Field') &&
             class_exists('GF_Fields')
         ) {
-            GF_Fields::register(new Field());
+            GF_Fields::register(new GFField());
         }
     }
 }
diff --git a/includes/integrations/gravityforms/fields/iban/Field.php b/includes/fields/gf/iban/Field.php
similarity index 98%
rename from includes/integrations/gravityforms/fields/iban/Field.php
rename to includes/fields/gf/iban/Field.php
index 2685c87..9651ef7 100644
--- a/includes/integrations/gravityforms/fields/iban/Field.php
+++ b/includes/fields/gf/iban/Field.php
@@ -1,11 +1,11 @@
 <?php
 
-namespace WPCT_ERP_FORMS\IBAN_Field;
+namespace WPCT_ERP_FORMS\Fields\GF\Iban;
 
 use Exception;
 use GF_Field;
 
-class Field extends GF_Field
+class GFField extends GF_Field
 {
     /**
      * @var array @type Country codes
diff --git a/includes/fields/gf/iban/index.php b/includes/fields/gf/iban/index.php
new file mode 100644
index 0000000..1f85c9b
--- /dev/null
+++ b/includes/fields/gf/iban/index.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace WPCT_ERP_FORMS\Fields\GF\Iban;
+
+use WPCT_ERP_FORMS\Fields\BaseField;
+use GFAddOn;
+
+class Field extends BaseField
+{
+    public function register()
+    {
+        add_action('gform_loaded', [$this, '_register']);
+    }
+
+    private function _register()
+    {
+        if (!method_exists('GFForms', 'include_addon_framework')) return;
+        require_once 'Addon.php';
+        require_once 'Field.php';
+
+
+        GFAddOn::register(Addon::class);
+    }
+}
diff --git a/includes/fields/gf/index.php b/includes/fields/gf/index.php
new file mode 100644
index 0000000..1f62d02
--- /dev/null
+++ b/includes/fields/gf/index.php
@@ -0,0 +1,3 @@
+<?php
+
+require_once 'iban/index.php';
diff --git a/includes/fields/index.php b/includes/fields/index.php
new file mode 100644
index 0000000..eb4556c
--- /dev/null
+++ b/includes/fields/index.php
@@ -0,0 +1,11 @@
+<?php
+
+require_once 'BaseField.php';
+
+if (defined('WPCF7_VERSION')) {
+    require_once 'wpcf7/index.php';
+}
+
+if (class_exists('GFForms')) {
+    require_once 'gf/index.php';
+}
diff --git a/includes/fields/wpcf7/iban/index.php b/includes/fields/wpcf7/iban/index.php
new file mode 100644
index 0000000..04121ff
--- /dev/null
+++ b/includes/fields/wpcf7/iban/index.php
@@ -0,0 +1,183 @@
+<?php
+
+namespace WPCT_ERP_FORMS\Fields\WPCF7\Iban;
+
+use WPCT_ERP_FORMS\Fields\BaseField;
+use Exception;
+
+class Field extends BaseField
+{
+    /**
+     * @var array @type Country codes
+     */
+    private $_countries = [
+        'al' => 28,
+        'ad' => 24,
+        'at' => 20,
+        'az' => 28,
+        'bh' => 22,
+        'be' => 16,
+        'ba' => 20,
+        'br' => 29,
+        'bg' => 22,
+        'cr' => 21,
+        'hr' => 21,
+        'cy' => 28,
+        'cz' => 24,
+        'dk' => 18,
+        'do' => 28,
+        'ee' => 20,
+        'fo' => 18,
+        'fi' => 18,
+        'fr' => 27,
+        'ge' => 22,
+        'de' => 22,
+        'gi' => 23,
+        'gr' => 27,
+        'gl' => 18,
+        'gt' => 28,
+        'hu' => 28,
+        'is' => 26,
+        'ie' => 22,
+        'il' => 23,
+        'it' => 27,
+        'jo' => 30,
+        'kz' => 20,
+        'kw' => 30,
+        'lv' => 21,
+        'lb' => 28,
+        'li' => 21,
+        'lt' => 20,
+        'lu' => 20,
+        'mk' => 19,
+        'mt' => 31,
+        'mr' => 27,
+        'mu' => 30,
+        'mc' => 27,
+        'md' => 24,
+        'me' => 22,
+        'nl' => 18,
+        'no' => 15,
+        'pk' => 24,
+        'ps' => 29,
+        'pl' => 28,
+        'pt' => 25,
+        'qa' => 29,
+        'ro' => 24,
+        'sm' => 27,
+        'sa' => 24,
+        'rs' => 22,
+        'sk' => 24,
+        'si' => 19,
+        'es' => 24,
+        'se' => 24,
+        'ch' => 21,
+        'tn' => 24,
+        'tr' => 26,
+        'ae' => 23,
+        'gb' => 22,
+        'vg' => 24,
+    ];
+
+    /**
+     * @var array $type Char codes
+     */
+    private $_chars = [
+        'a' => 10,
+        'b' => 11,
+        'c' => 12,
+        'd' => 13,
+        'e' => 14,
+        'f' => 15,
+        'g' => 16,
+        'h' => 17,
+        'i' => 18,
+        'j' => 19,
+        'k' => 20,
+        'l' => 21,
+        'm' => 22,
+        'n' => 23,
+        'o' => 24,
+        'p' => 25,
+        'q' => 26,
+        'r' => 27,
+        's' => 28,
+        't' => 29,
+        'u' => 30,
+        'v' => 31,
+        'w' => 32,
+        'x' => 33,
+        'y' => 34,
+        'z' => 35
+    ];
+
+    public function register()
+    {
+        add_action('wpcf7_init', function () {
+            $this->_register();
+        });
+    }
+
+    private function _register()
+    {
+        wpcf7_add_form_tag(
+            ['iban', 'iban*'],
+            function ($tag) {
+                return $this->handler($tag);
+            },
+            ['name-attr' => true]
+        );
+
+        add_filter('wpcf7_validate_iban*', function ($result, $tag) {
+            return $this->validate($result, $tag);
+        }, 20, 2);
+        add_filter('wpcf7_validate_iban', function ($result, $tag) {
+            return $this->validate($result, $tag);
+        }, 20, 2);
+    }
+
+    private function handler($tag)
+    {
+        $atts = [
+            'type' => 'text',
+            'name' => $tag->name,
+        ];
+
+        $input = sprintf('<input %s />', wpcf7_format_atts($atts));
+        return $input;
+    }
+
+    private function validate($result, $tag)
+    {
+        $value = $_POST[$tag->name];
+        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)];
+
+            if (!($country_exists && $country_conform)) throw new Exception();
+
+            $moved_char = substr($value, 4) . substr($value, 0, 4);
+            $move_char_array = str_split($moved_char);
+            $new_string = '';
+
+            foreach ($move_char_array as $key => $val) {
+                if (!is_numeric($move_char_array[$key])) {
+                    if (!isset($this->_chars[$val])) throw new Exception();
+                    $move_char_array[$key] = $this->_chars[$val];
+                }
+
+                $new_string .= $move_char_array[$key];
+            }
+
+            if (bcmod($new_string, '97') != 1) {
+                throw new Exception();
+            }
+        } catch (Exception) {
+            $result->invalidate($tag, 'Invalid IBAN format');
+        }
+    }
+}
diff --git a/includes/fields/wpcf7/index.php b/includes/fields/wpcf7/index.php
new file mode 100644
index 0000000..1f62d02
--- /dev/null
+++ b/includes/fields/wpcf7/index.php
@@ -0,0 +1,3 @@
+<?php
+
+require_once 'iban/index.php';
diff --git a/includes/integrations/Integration.php b/includes/integrations/Integration.php
index e62be1e..4685e67 100644
--- a/includes/integrations/Integration.php
+++ b/includes/integrations/Integration.php
@@ -6,14 +6,17 @@ use Exception;
 
 class Integration
 {
+    public static $fields = [];
     private static $instances = [];
 
     public function __construct()
     {
-        add_action('init', function () {
-            $integration = self::get_instance();
-            $integration->register();
-        });
+        add_action('init', [$this, 'register']);
+
+        foreach (static::$fields as $field) {
+            $_field = $field::get_instance();
+            $_field->register();
+        }
     }
 
     protected function __clone()
@@ -29,7 +32,7 @@ class Integration
     {
         $cls = static::class;
         if (!isset(self::$instances[$cls])) {
-            self::$instances[$cls] = new static();
+            self::class::$instances[$cls] = new static();
         }
 
         return self::$instances[$cls];
diff --git a/includes/attachments.php b/includes/integrations/gf/attachments.php
similarity index 100%
rename from includes/attachments.php
rename to includes/integrations/gf/attachments.php
diff --git a/includes/fields-population.php b/includes/integrations/gf/fields-population.php
similarity index 100%
rename from includes/fields-population.php
rename to includes/integrations/gf/fields-population.php
diff --git a/includes/integrations/gravityforms/index.php b/includes/integrations/gf/index.php
similarity index 96%
rename from includes/integrations/gravityforms/index.php
rename to includes/integrations/gf/index.php
index 980e290..f967745 100644
--- a/includes/integrations/gravityforms/index.php
+++ b/includes/integrations/gf/index.php
@@ -5,13 +5,17 @@ namespace WPCT_ERP_FORMS\Integrations;
 use WPCT_ERP_FORMS\Integrations\Integration;
 use Exception;
 
-/* Custom fields */
-
 require_once 'fields/iban/index.php';
+require_once 'attachments.php';
+require_once 'fields-population.php';
 
 class GF extends Integration
 {
 
+    public static $fields = [
+        IbanField::class
+    ];
+
     public function register()
     {
         add_action('gform_after_submission', function ($entry, $form) {
diff --git a/includes/integrations/gravityforms/fields/iban/index.php b/includes/integrations/gravityforms/fields/iban/index.php
deleted file mode 100644
index 78a5a95..0000000
--- a/includes/integrations/gravityforms/fields/iban/index.php
+++ /dev/null
@@ -1,13 +0,0 @@
-<?php
-
-define('WPCT_ERP_FORMS_IBAN_FIELD_VERSION', '1.0');
-add_action('gform_loaded', 'wpct_erp_forms_load_iban_field', 5);
-function wpct_erp_forms_load_iban_field()
-{
-    if (!method_exists('GFForms', 'include_addon_framework')) return;
-    require_once 'Addon.php';
-    require_once 'Field.php';
-
-
-    GFAddOn::register(\wpct_erp_FORMS\IBAN_Field\Addon::class);
-}
diff --git a/includes/integrations/index.php b/includes/integrations/index.php
index a2e5cda..5b25f29 100644
--- a/includes/integrations/index.php
+++ b/includes/integrations/index.php
@@ -13,15 +13,15 @@ class WPCTIntegrationsRegistry
 }
 
 if (defined('WPCF7_VERSION')) {
-    require_once 'contactform7/index.php';
+    require_once 'wpcf7/index.php';
     add_action('plugins_loaded', function () {
-        WPCTIntegrationsRegistry::$instances[] = new WPCF7();
+        WPCTIntegrationsRegistry::$instances['wpcf7'] = new WPCF7();
     });
 }
 
 if (class_exists('GFForms')) {
-    require_once 'gravityforms/index.php';
+    require_once 'gf/index.php';
     add_action('plugins_loaded', function () {
-        WPCTIntegrationsRegistry::$instances[] = new GF();
+        WPCTIntegrationsRegistry::$instances['gf'] = new GF();
     });
 }
diff --git a/includes/integrations/contactform7/index.php b/includes/integrations/wpcf7/index.php
similarity index 87%
rename from includes/integrations/contactform7/index.php
rename to includes/integrations/wpcf7/index.php
index 72f9c93..e327c97 100644
--- a/includes/integrations/contactform7/index.php
+++ b/includes/integrations/wpcf7/index.php
@@ -3,9 +3,13 @@
 namespace WPCT_ERP_FORMS\Integrations;
 
 use WPCT_ERP_FORMS\Integrations\Integration;
+use WPCT_ERP_FORMS\Fields\WPCF7\Iban\Field as IbanField;
 
 class WPCF7 extends Integration
 {
+    public static $fields = [
+        IbanField::class
+    ];
 
     public function register()
     {
diff --git a/wpct-erp-forms.php b/wpct-erp-forms.php
index 3246b37..2485dd6 100755
--- a/wpct-erp-forms.php
+++ b/wpct-erp-forms.php
@@ -1,33 +1,29 @@
 <?php
 
 /**
- * Plugin Name:     WPCT CRM Forms
- * Plugin URI:      https://git.coopdevs.org/coopdevs/website/wp/wp-plugins/wpct-crm-forms
- * Description:     Plugin to wire gravity forms submissions with Odoo CRM Leads module
+ * Plugin Name:     Wpct ERP Forms
+ * Plugin URI:      https://git.coopdevs.org/codeccoop/wp/wpct-erp-forms
+ * Description:     Plugin to bridge WP forms submissions to a ERP backend
  * Author:          Còdec Cooperativa
  * Author URI:      https://www.codeccoop.org
  * Text Domain:     wpct-erp-forms
  * Domain Path:     /languages
  * Version:         1.0.0
  *
- * @package         WPCT_ERP_Forms
+ * @package         wpct_erp_forms
  */
 
 /* Settings */
 require_once 'includes/options/index.php';
 
-/* Webhooks */
-require_once 'includes/attachments.php';
-
-/* Fields population */
-require_once 'includes/fields-population.php';
-
 /* Integrations */
 require_once 'includes/integrations/index.php';
 
+/* Fields */
+require_once 'includes/fields/index.php';
+
 /* Dependencies */
 add_filter('wpct_dependencies_check', function ($dependencies) {
-    // $dependencies['Gravity Forms'] = '<a href="https://www.gravityforms.com/">Gravity Forms</a>';
     $dependencies['Wpct Odoo Connect'] = '<a href="https://git.coopdevs.org/coopdevs/website/wp/wp-plugins/wpct-odoo-connect">Wpct Odoo Connect</a>';
     return $dependencies;
 });
-- 
GitLab