diff --git a/includes/class-integration.php b/includes/class-integration.php index 18d3175ba853dfd84232115bf47a2bd74263a493..7a0d33d62dff128a8b725b443508c2b89061f1bb 100644 --- a/includes/class-integration.php +++ b/includes/class-integration.php @@ -10,50 +10,43 @@ abstract class Integration extends Singleton { abstract public function serialize_submission($submission, $form); abstract public function serialize_form($form); - abstract public function get_uploads($submission, $form_data); - abstract public function init(); + abstract protected function get_uploads($submission, $form_data); + abstract protected function init(); + + private $submission = null; + private $uploads = null; protected function __construct() { - add_action('init', [$this, 'init']); - - add_filter('option_wpct-erp-forms_rest-api', function ($setting) { - return $this->populate_refs($setting); - }, 10, 1); - add_filter('option_wpct-erp-forms_rpc-api', function ($setting) { - return $this->populate_refs($setting); - }, 10, 1); - add_action('update_option', function ($option, $from, $to) { - if ($option === 'wpct-erp-forms_rest-api' || $option === 'wpct-erp-forms_rpc-api') { - foreach ($to['forms'] as $form) { - $this->set_form_ref($form['form_id'], $form['ref']); - } - } - }, 10, 3); + add_action('init', function () { + $this->init(); + }); + + add_filter('wpct_erp_forms_submission', function ($null) { + return $this->submission; + }); + + add_filter('wpct_erp_forms_uploads', function ($null) { + return $this->uploads; + }); } - public function submit($payload, $endpoints, $uploads, $form_data) + private function submit($requests) { $success = true; - foreach ($endpoints as $proto => $urls) { - foreach ($urls as $url) { - if (!$success) { - continue; - } - - if ($proto === 'rpc') { - $data = apply_filters('wpct_erp_forms_rpc_payload', $this->rpc_payload($url, $payload), $uploads, $form_data); - } else { - $data = $payload; - } - if (empty($uploads)) { - $response = Wpct_Http_Client::post($url, $data); - } else { - $response = Wpct_Http_Client::post_multipart($url, $data, $uploads); - } + foreach ($requests as $req) { + if (!$success) { + continue; + } - $success = $success && !is_wp_error($response); + extract($req); + if (empty($attachments)) { + $response = Wpct_Http_Client::post($endpoint, $payload); + } else { + $response = Wpct_Http_Client::post_multipart($endpoint, $payload, $attachments); } + + $success = $success && !is_wp_error($response); } if (!$success) { @@ -67,7 +60,7 @@ abstract class Integration extends Singleton $body = "Form ID: {$form_data['id']}\n"; $body .= "Form title: {$form_data['title']}\n"; $body .= 'Submission: ' . print_r($payload, true) . "\n"; - $body .= 'Error: ' . print_r($response->get_error_data(), true) . "\n"; + $body .= 'Error: ' . print_r($response->get_error_data(), true) . "\n"; $success = wp_mail($to, $subject, $body); if (!$success) { throw new Exception('Error while submitting form ' . $form_data['id']); @@ -77,6 +70,68 @@ abstract class Integration extends Singleton return $success; } + private function submit_rpc($models, $payload, $attachments, $form_data) + { + $setting = Settings::get_setting('wpct-erp-forms', 'rpc-api'); + + try { + [ $session_id, $user_id ] = $this->rpc_login($setting['endpoint']); + } catch (Exception) { + return false; + } + + $requests = array_map(function ($model) use ( + $setting, + $payload, + $attachments, + $form_data, + $session_id, + $user_id, + ) { + $payload = apply_filters( + 'wpct_erp_forms_rpc_payload', + $this->rpc_payload( + $session_id, + 'object', + 'execute', + [ + $setting['database'], + $user_id, + $setting['password'], + $model, + 'create', + $payload + ], + ), + $attachments, + $form_data, + ); + + return [ + 'endpoint' => $setting['endpoint'], + 'payload' => $payload, + 'attachments' => $attachments, + 'form_data' => $form_data, + ]; + }, $models); + + return $this->submit($requests); + } + + private function submit_rest($endpoints, $payload, $attachments, $form_data) + { + $requests = array_map(function ($endpoint) use ($payload, $attachments, $form_data) { + return [ + 'endpoint' => $endpoint, + 'payload' => $payload, + 'attachments' => $attachments, + 'form_data' => $form_data, + ]; + }, $endpoints); + + return $this->submit($requests); + } + public function do_submission($submission, $form) { $form_data = $this->serialize_form($form); @@ -84,32 +139,35 @@ abstract class Integration extends Singleton return; } - $uploads = $this->get_uploads($submission, $form_data); - $uploads = apply_filters('wpct_erp_forms_uploads', array_reduce(array_keys($uploads), function ($carry, $name) use ($uploads) { - if ($uploads[$name]['is_multi']) { - for ($i = 1; $i <= count($uploads[$name]['path']); $i++) { - $carry[$name . '_' . $i] = $uploads[$name]['path'][$i - 1]; + $this->uploads = $this->get_uploads($submission, $form_data); + $attachments = apply_filters('wpct_erp_forms_attachments', array_reduce(array_keys($this->uploads), function ($carry, $name) { + if ($this->uploads[$name]['is_multi']) { + for ($i = 1; $i <= count($this->uploads[$name]['path']); $i++) { + $carry[$name . '_' . $i] = $this->uploads[$name]['path'][$i - 1]; } } else { - $carry[$name] = $uploads[$name]['path']; + $carry[$name] = $this->uploads[$name]['path']; } return $carry; }, []), $form_data); - $data = $this->serialize_submission($submission, $form_data); - $this->cleanup_empties($data); - $payload = apply_filters('wpct_erp_forms_payload', $data, $uploads, $form_data); + $this->submission = $this->serialize_submission($submission, $form_data); + $this->cleanup_empties($submission); + $payload = apply_filters('wpct_erp_forms_payload', $this->submission, $attachments, $form_data); + + $endpoints = apply_filters('wpct_erp_forms_endpoints', $this->get_form_endpoints($form_data['id']), $payload, $attachments, $form_data); + $models = apply_filters('wpct_erp_forms_models', $this->get_form_models($form_data['id']), $payload, $attachments, $form_data); - $endpoints = apply_filters('wpct_erp_forms_endpoints', $this->get_form_endpoints($form_data['id']), $payload, $uploads, $form_data); + do_action('wpct_erp_forms_before_submission', $payload, $attachments, $form_data); - do_action('wpct_erp_forms_before_submission', $payload, $uploads, $form_data); - $success = $this->submit($payload, $endpoints, $uploads, $form_data); + $success = $this->submit_rest($endpoints, $payload, $attachments, $form_data); + $success = $success && $this->submit_rpc($models, $payload, $attachments, $form_data); if ($success) { - do_action('wpct_erp_forms_after_submission', $payload, $uploads, $form_data); + do_action('wpct_erp_forms_after_submission', $payload, $attachments, $form_data); } else { - do_action('wpct_erp_forms_on_failure', $payload, $uploads, $form_data); + do_action('wpct_erp_forms_on_failure', $payload, $attachments, $form_data); } } @@ -124,85 +182,43 @@ abstract class Integration extends Singleton return $submission; } - private function get_form_endpoints($form_id) + private function get_form_models($form_id) { - $rest_forms = Settings::get_setting('wpct-erp-forms', 'rest-api', 'forms'); $rpc_forms = Settings::get_setting('wpct-erp-forms', 'rpc-api', 'forms'); - $rpc_endpoint = Settings::get_setting('wpct-erp-forms', 'rpc-api', 'endpoint'); - - $endpoints = [ - 'rpc' => $rpc_forms, - 'rest' => $rest_forms, - ]; - - foreach ($endpoints as $proto => $forms) { - $endpoints[$proto] = array_map(function ($form) use ($rpc_endpoint) { - return isset($form['endpoint']) ? $form['endpoint'] : $rpc_endpoint; - }, array_filter( - $forms, - function ($form) use ($form_id) { - return (string) $form['form_id'] === (string) $form_id; - } - )); - } - - return $endpoints; - } - - public function get_form_ref($form_id) - { - $setting = get_option('wpct-erp-forms_refs', []); - foreach ($setting as $ref_id => $ref) { - if ((string) $ref_id === (string) $form_id) { - return $ref; - } - } - - return null; - } - - public function set_form_ref($form_id, $ref) - { - $setting = get_option('wpct-erp-forms_refs', []); - $setting[$form_id] = $ref; - update_option('wpct-erp-forms_refs', $setting); + return array_unique(array_map(function ($form) { + return $form['model']; + }, array_filter($rpc_forms, function ($form) use ($form_id) { + return (string) $form['form_id'] === (string) $form_id && !empty($form['model']); + }))); } - private function populate_refs($setting) + private function get_form_endpoints($form_id) { - $refs = get_option('wpct-erp-forms_refs', []); - for ($i = 0; $i < count($setting['forms']); $i++) { - $form = $setting['forms'][$i]; - if (!isset($refs[$form['form_id']])) { - continue; - } - $form['ref'] = $refs[$form['form_id']]; - $setting['forms'][$i] = $form; - } - - return $setting; + $rest_forms = Settings::get_setting('wpct-erp-forms', 'rest-api', 'forms'); + return array_unique(array_map(function ($form) { + return $form['endpoint']; + }, array_filter($rest_forms, function ($form) use ($form_id) { + return (string) $form['form_id'] === (string) $form_id && !empty($form['endpoint']); + }))); } - private function rpc_payload($url, $payload) + private function rpc_login($endpoint) { $session_id = time(); $setting = Settings::get_setting('wpct-erp-forms', 'rpc-api'); - $payload = apply_filters('wpct_erp_forms_rpc_login', [ - 'jsonrpc' => '2.0', - 'method' => 'call', - 'id' => $session_id, - 'params' => [ - 'service' => 'common', - 'method' => 'login', - 'args' => [ - $setting['database'], - $setting['user'], - $setting['password'] - ] - ] - ]); - $res = Wpct_Http_Client::post($url, $payload); + $payload = apply_filters('wpct_erp_forms_rpc_login', $this->rpc_payload( + $session_id, + 'common', + 'login', + [ + $setting['database'], + $setting['user'], + $setting['password'], + ], + )); + + $res = Wpct_Http_Client::post($endpoint, $payload); if (is_wp_error($res)) { throw new Exception('Error while establish RPC session'); @@ -210,23 +226,20 @@ abstract class Integration extends Singleton $login = (array) json_decode($res['body'], true); $user_id = $login['result']; + return [$session_id, $user_id]; + } + private function rpc_payload($session_id, $service, $method, $args) + { return [ 'jsonrpc' => '2.0', 'method' => 'call', 'id' => $session_id, 'params' => [ - 'service' => 'object', - 'method' => 'execute', - 'args' => [ - $setting['database'], - $user_id, - $setting['password'], - $setting['model'], - 'create', - $payload - ] - ] + 'service' => $service, + 'method' => $method, + 'args' => $args, + ], ]; } }