name = 'visformswffrm'; parent::__construct($subject, $config); $this->initializeLogger($this->name, ''); } // interface public static function getSubscribedEvents(): array { return array_merge([ // 'onVisformsBeforeFormSave' => 'onVisformsBeforeFormSave', 'onVisformsAfterFormSave' => 'onVisformsAfterFormSave', 'onVisformsAfterEditFormSave' => 'onVisformsAfterEditFormSave', ], parent::getSubscribedEvents()); } public function onVisformsAfterFormSave(VisformsAfterFormSaveEvent $event): void { $this->processEvent($event); } public function onVisformsAfterEditFormSave(VisformsAfterEditFormSaveEvent $event): void { $this->processEvent($event); } protected function setPlgTable() { $db = Factory::getContainer()->get(DatabaseInterface::class); $this->plgTable = new plgTable($db); } // implementation private function doINeedToRun(): bool { // skip execution if context is wrong if (($this->context != 'com_visforms.form') && ($this->context != 'mod_visforms.form') && ($this->context != 'plg_vfformview.form')) { return false; } // skip execution if client side $app = Factory::getApplication(); if ($app->isClient('administrator')) { return false; } // skip execution if form id missing if (empty($this->form->id)) { return false; } // get settings from plugin params $this->plgParams = $this->getItem(); if (!$this->plgParams) { return false; } $this->wfiTrigger = $this->getParamInt('wfi_trigger', 1); $this->wfiActive = $this->getParamIntegerToBool('wfi_active', 0); // run if active and either one of: both, 'form only' and not data edit case, 'edit only' and data edit case return $this->wfiActive && ($this->wfiTrigger == 3 || ($this->wfiTrigger == 1 && !$this->edit) || ($this->wfiTrigger == 2 && $this->edit)); } private function initialize() { $this->fid = $this->form->id; $this->model = new VisformsModel(array('ignore_request' => true, 'id' => $this->fid)); // plugin parameter wfi_active and wfi_trigger are already set in doINeedToRun() $this->wfiURL = $this->getParamText('wfi_url',); $this->wfiType = $this->getParamText('wfi_type',); $this->wfiPOSTType = $this->getParamText('wfi_post_type',); $this->wfiPOSTTemplate = $this->getParamText('wfi_post_template',); $this->wfiPOSTTemplateFormat = $this->getParamText('wfi_post_template_type',); $this->wfiPOSTJSON = $this->getParamText('wfi_post_json',); $this->wfiAuthenticationActive = $this->getParamIntegerToBool('wfi_authentication_active'); $this->wfiAuthenticationData = $this->getParamText('wfi_authentication_data',); $this->wfiHTTPBasicAuthenticationActive = $this->getParamIntegerToBool('wfi_authentication_http_basic_active'); $this->wfiHTTPBasicAuthenticationData = $this->getParamText('wfi_authentication_http_basic_data',); $this->wfiShowMessageSuccess = $this->getParamInt('wfi_show_message_success'); $this->wfiShowMessageError = $this->getParamInt('wfi_show_message_error'); $this->wfiCustomMessageSuccess = $this->getParamText('wfi_custom_message_success'); $this->wfiCustomMessageError = $this->getParamText('wfi_custom_message_error'); $this->wfiLoggingType = $this->getParamInt('wfi_logging_type'); $this->replacePlaceholder(); } private function processEvent(VisformsBaseFormSaveEvent $event): void { $this->context = $event->getContext(); $this->form = $event->getForm(); $this->fields = $event->getFields(); $this->edit = ($event instanceof VisformsAfterEditFormSaveEvent); if (empty($this->doINeedToRun())) { return; } $this->initialize(); switch ($this->wfiType) { case 1: $this->processURLParameter(); break; case 2: $this->processPOSTParameter(); break; case 3: $this->processPOSTJSON(); break; case 4: $this->processPOSTTemplate(); break; default: $this->processPOSTParameter(); } } private function getParamText($name, $default = '') { return ((isset($this->plgParams[$this->name . '_params']["$name"])) ? $this->plgParams[$this->name . '_params']["$name"] : $default); } private function getParamInt($name, $default = 0): int { return (int) $this->getParamText($name, $default); } private function getParamIntegerToBool($name, $default = 0): bool { return ((isset($this->plgParams[$this->name . '_params']["$name"])) ? $this->plgParams[$this->name . '_params']["$name"] : $default) == 1; } private function replacePlaceholder() { $this->wfiURL = $this->model->replacePlaceholder($this->form, $this->wfiURL); $this->wfiPOSTTemplate = $this->model->replacePlaceholder($this->form, $this->wfiPOSTTemplate); $this->wfiAuthenticationData = $this->model->replacePlaceholder($this->form, $this->wfiAuthenticationData); $this->wfiCustomMessageSuccess = $this->model->replacePlaceholder($this->form, $this->wfiCustomMessageSuccess); $this->wfiCustomMessageError = $this->model->replacePlaceholder($this->form, $this->wfiCustomMessageError); } private function processURLParameter() { $params = $this->getInterfaceParams(); $URL = ''; if(str_contains($this->wfiURL, '?')) { // URL already contains path and parameter separator '?' $URL = $this->wfiURL . http_build_query($params); } else { // URL is missing path and parameter separator '?' $URL = $this->wfiURL . '?' . http_build_query($params); } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $URL); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, 0); $this->executeCURL($ch); } private function processPOSTParameter() { $params = $this->getInterfaceParams(); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $this->wfiURL); curl_setopt($ch, CURLOPT_POST, true); if($this->wfiPOSTType == 1) { // POST parameter list URL-encoded that does not allow for file uploads curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/x-www-form-urlencoded')); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params)); } else { // simple POST parameter list that allows for file uploads curl_setopt($ch, CURLOPT_POSTFIELDS, $params); } curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // curl_setopt($ch, CURLOPT_NOBODY, true); curl_setopt($ch, CURLOPT_HEADER, 0); $this->executeCURL($ch); } private function processPOSTTemplate() { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $this->wfiURL); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $this->wfiPOSTTemplate); // text/plain // text/xml // application/json // text/html $contentType = ''; switch ($this->wfiPOSTTemplateFormat) { case 1: $contentType = 'Content-Type:text/plain'; break; case 2: $contentType = 'Content-Type:text/xml'; break; case 3: $contentType = 'Content-Type:application/json'; break; case 4: $contentType = 'Content-Type:text/html'; break; default: $contentType = 'Content-Type:text/plain'; } curl_setopt($ch, CURLOPT_HTTPHEADER, array($contentType)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, 0); $this->executeCURL($ch); } private function processPOSTJSON() { $params = $this->getInterfaceParams(); $json = json_encode($params); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $this->wfiURL); curl_setopt($ch, CURLOPT_POST, true); if(empty($this->wfiPOSTJSON)) { curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json')); curl_setopt($ch, CURLOPT_POSTFIELDS, $json); } else { curl_setopt($ch, CURLOPT_POSTFIELDS, [$this->wfiPOSTJSON => $json]); } curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, 0); $this->executeCURL($ch); } private function getInterfaceFieldName($field) { return $this->model->replacePlaceholder($this->form, $field->wfi_name !== '' ? $field->wfi_name : $field->alias); } private function getInterfaceParams(): array { $params = array(); // add all activated fields foreach ($this->fields as $field) { if(property_exists($field, 'wfi_active')) { if($field->wfi_active) { $name = $this->getInterfaceFieldName($field); switch ($field->typefield) { case 'file': if( !empty($data = json_decode($field->dbValue, true))) { // upload file information is available if ($this->wfiType == 2 && $this->wfiPOSTType == 2) { // in case of 'Interface Type' = 'POST-Parameter' and 'POST-Parameter Typ' = File-Upload // we have a real file upload $params[$name] = curl_file_create($data['folder'] . '/' . $data['file']);; } else { // just the relative file path name $params[$name] = realpath($data['folder'] . '/' . $data['file']); } } else { // no upload file information available $params[$name] = ''; } break; default: $params[$name] = $field->dbValue; } } } } // add authentication information if($this->wfiAuthenticationActive) { $elements = json_decode($this->wfiAuthenticationData); foreach ($elements as $key => $value) { $params[$key] = $value; } } return $params; } private function executeCURL($ch) { // for debugging and possible later logging curl_setopt($ch,CURLINFO_HEADER_OUT, true); // add HTTP Basic authentication information if($this->wfiHTTPBasicAuthenticationActive) { curl_setopt($ch, CURLOPT_USERPWD, $this->wfiHTTPBasicAuthenticationData); } // contains the return body // to deactivate the body in the output: curl_setopt($ch, CURLOPT_NOBODY, true); $this->returnOutput = trim(curl_exec($ch)); $this->returnNumber = curl_errno($ch); $this->returnMessage = curl_error($ch); $this->returnHTTPCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $this->headerSent = curl_getinfo($ch,CURLINFO_HEADER_OUT); curl_close($ch); // status codes of the 2xx series of HTTP status codes confirm that a client's request was successfully received, understood, and accepted. $this->finalResult = ($this->returnHTTPCode >= 200 && $this->returnHTTPCode < 300); $this->handleUserMessages(); $this->handleResultLogging(); } private function handleUserMessages() { if($this->finalResult) { // success message if($this->wfiShowMessageSuccess === 2 && $this->wfiCustomMessageSuccess !== '') { // user custom success text: configured and no empty custom message text $this->setUserMessage($this->wfiCustomMessageSuccess, CMSApplicationInterface::MSG_INFO); } elseif($this->wfiShowMessageSuccess === 1 || ($this->wfiShowMessageSuccess === 2 && $this->wfiCustomMessageSuccess === '')) { // user success text: configured or empty custom message text $this->setUserMessage(Text::sprintf('PLG_VISFORMS_WEBFORMSFORM_MESSAGE_SUCCESS'), CMSApplicationInterface::MSG_INFO); } } else { // error message if($this->wfiShowMessageError === 4 && $this->wfiCustomMessageError !== '') { // user custom success text: configured and no empty custom message text $this->setUserMessage($this->wfiCustomMessageError, CMSApplicationInterface::MSG_ERROR); } elseif($this->wfiShowMessageError === 1 || ($this->wfiShowMessageError === 4 && $this->wfiCustomMessageError === '')) { // error text: short or empty custom message text $this->setUserMessage(Text::sprintf('PLG_VISFORMS_WEBFORMSFORM_MESSAGE_FAILED'), CMSApplicationInterface::MSG_ERROR); } elseif($this->wfiShowMessageError === 2){ // user error text: detail $this->setUserMessage(Text::sprintf('PLG_VISFORMS_WEBFORMSFORM_MESSAGE_FAILED_DETAIL', $this->returnHTTPCode, $this->returnNumber, $this->returnMessage), CMSApplicationInterface::MSG_ERROR); } elseif($this->wfiShowMessageError === 3) { // user error text: detail and return body $this->setUserMessage(Text::sprintf('PLG_VISFORMS_WEBFORMSFORM_MESSAGE_FAILED_DETAIL', $this->returnHTTPCode, $this->returnNumber, $this->returnMessage), CMSApplicationInterface::MSG_ERROR); $this->setUserMessage(Text::sprintf('PLG_VISFORMS_WEBFORMSFORM_MESSAGE_FAILED_DETAIL_BODY', $this->returnOutput), CMSApplicationInterface::MSG_ERROR); } } } private function handleResultLogging() { // failed // success // failed and success if(( !$this->finalResult && $this->wfiLoggingType === 1) || ($this->finalResult && $this->wfiLoggingType === 2) || $this->wfiLoggingType === 3) { $code = $this->finalResult ? Log::INFO : Log::ERROR; $this->addLogEntry(Text::sprintf('PLG_VISFORMS_WEBFORMSFIELD_INTERFACE_LOGGING_ENTRY', $this->getRequestTime(), $this->wfiURL, $this->finalResult ? 1 : 0), $code); $this->addLogEntry(Text::sprintf('PLG_VISFORMS_WEBFORMSFIELD_INTERFACE_LOGGING_ENTRY_DETAIL', $this->returnHTTPCode, $this->returnNumber, $this->returnMessage), $code); $this->addLogEntry(Text::sprintf('PLG_VISFORMS_WEBFORMSFIELD_INTERFACE_LOGGING_ENTRY_BODY', $this->returnOutput), $code); } } private function setUserMessage($msg, $type) { $app = Factory::getApplication(); $app->enqueueMessage($msg, $type); } private function getRequestTime(): string { return date('y-m-d h:i:s', $_SERVER['REQUEST_TIME']); } }