bootstrap = true; $this->context = Context::getContext(); $this->table = 'guest_reg_purpose'; $this->className = 'GuestRegPurpose'; $this->identifier = 'id_guest_reg_purpose'; $this->lang = true; parent::__construct(); $this->fields_options = array( 'general' => array( 'title' => $this->l('Guest Registration Card settings'), 'icon' => 'icon-cogs', 'fields' => array( self::CONF_ENABLE_HEADER => array( 'title' => $this->l('Enable PDF header'), 'desc' => $this->l('Display the standard QloApps PDF header on the Guest Registration Card.'), 'cast' => 'intval', 'type' => 'bool', ), self::CONF_OPTIONAL_SECTIONS => array( 'title' => $this->l('Optional sections'), 'desc' => $this->l('Choose which optional sections should appear on the Guest Registration Card.'), 'type' => 'checkbox', 'auto_value' => false, 'choices' => $this->getOptionalSectionChoices(), ), ), 'submit' => array( 'title' => $this->l('Save'), ), ), ); } public function initContent() { $this->display = 'options'; $this->initToolbar(); $this->initPageHeaderToolbar(); $this->content = $this->renderOptions(); $this->content .= $this->renderDynamicFieldManagement(); $this->context->smarty->assign(array( 'content' => $this->content, 'url_post' => self::$currentIndex.'&token='.$this->token, 'show_page_header_toolbar' => $this->show_page_header_toolbar, 'page_header_toolbar_title' => $this->page_header_toolbar_title, 'page_header_toolbar_btn' => $this->page_header_toolbar_btn, )); } public function initToolbarTitle() { $this->toolbar_title = array($this->l('Guest Registration Card')); } public function initPageHeaderToolbar() { parent::initPageHeaderToolbar(); unset($this->page_header_toolbar_btn['cancel']); } public function postProcess() { if (Tools::isSubmit('submitBulkGuestRegistrationValues')) { $this->processBulkDynamicFieldSave(); if (!count($this->errors)) { Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token.'&conf=4'); } return; } parent::postProcess(); } public function renderOptions() { $this->fields_options['general']['fields'][self::CONF_OPTIONAL_SECTIONS]['value'] = ''; $html = parent::renderOptions(); $this->context->smarty->assign(array( 'guest_reg_preview_img_url' => $this->context->link->getBaseLink().'img/admin/guest_registration_preview.jpg', 'guest_reg_selected_sections' => $this->getSelectedOptionalSections(), 'guest_reg_conf_key' => self::CONF_OPTIONAL_SECTIONS, 'guest_reg_preview_title' => $this->l('Guest Registration Card Preview'), 'guest_reg_preview_btn_title' => $this->l('Preview'), )); $html .= $this->createTemplate('preview_modal.tpl')->fetch(); return $html; } protected function updateOptionQloGuestRegOptionalSections($value) { if (!is_array($value)) { $value = array(); } $allowed = array_map('intval', array_keys($this->getOptionalSectionChoices())); $selected = array(); foreach ($value as $sectionId) { $sectionId = (int)$sectionId; if (in_array($sectionId, $allowed)) { $selected[] = $sectionId; } } Configuration::updateValue(self::CONF_OPTIONAL_SECTIONS, Tools::jsonEncode(array_values(array_unique($selected)))); } protected function renderDynamicFieldManagement() { $languages = Language::getLanguages(false); $defaultFormLanguage = (int)Configuration::get('PS_LANG_DEFAULT'); $this->context->smarty->assign(array( 'languages' => $languages, 'default_form_language' => $defaultFormLanguage, 'dynamic_form_action' => self::$currentIndex.'&token='.$this->token, 'guest_reg_purpose_rows' => $this->getEntityRowsForDisplay('purpose', $languages), 'guest_reg_id_proof_rows' => $this->getEntityRowsForDisplay('id_proof', $languages), 'guest_reg_payment_method_rows' => $this->getEntityRowsForDisplay('payment_method', $languages), )); return $this->createTemplate('dynamic_tables.tpl')->fetch(); } protected function processBulkDynamicFieldSave() { $languages = Language::getLanguages(false); $savedRows = array(); foreach ($this->getManagedEntities() as $entityKey => $entity) { $postedRows = Tools::getValue($entity['table'], array()); if (!is_array($postedRows)) { $postedRows = array(); } $savedRows[$entityKey] = $this->prepareEntityRowsForSave($entityKey, $postedRows, $languages); } if (count($this->errors)) { return false; } foreach ($savedRows as $entityKey => $rows) { $this->persistEntityRows($entityKey, $rows); } return true; } protected function prepareEntityRowsForSave($entityKey, $postedRows, $languages) { $entity = $this->getManagedEntity($entityKey); $rows = array(); // Get the system's default language ID $idLangDefault = (int)Configuration::get('PS_LANG_DEFAULT'); foreach ($postedRows as $rowKey => $row) { if (!is_array($row)) { continue; } if ($this->isEmptyEntityRow($row, $languages)) { continue; } $preparedRow = array( 'id' => !empty($row['id']) ? (int)$row['id'] : 0, 'active' => !empty($row['active']) ? 1 : 0, 'name' => array(), ); // Capture the default language value first to use as a fallback $defaultValue = ''; if (isset($row['name'][$idLangDefault])) { $defaultValue = trim($row['name'][$idLangDefault]); } foreach ($languages as $language) { $idLang = (int)$language['id_lang']; $value = ''; if (isset($row['name'][$idLang])) { $value = trim($row['name'][$idLang]); } // AUTOMATIC FALLBACK: If current language is blank, use the default language text if ($value === '' && $defaultValue !== '') { $value = $defaultValue; } // Validation if ($value === '') { $this->errors[] = sprintf($this->l('%s: name is required for %s (or for the default language).'), $entity['title'], $language['name']); } elseif (!Validate::isCatalogName($value)) { $this->errors[] = sprintf($this->l('%s: name is invalid for %s.'), $entity['title'], $language['name']); } $preparedRow['name'][$idLang] = $value; } $rows[$rowKey] = $preparedRow; } return $rows; } protected function persistEntityRows($entityKey, $rows) { $entity = $this->getManagedEntity($entityKey); $existingIds = $this->getEntityIds($entityKey); $savedIds = array(); foreach ($rows as $row) { $object = $row['id'] ? new $entity['class']((int)$row['id']) : new $entity['class'](); $object->active = (int)$row['active']; $object->name = $row['name']; if (!$object->save()) { $this->errors[] = sprintf($this->l('An error occurred while saving %s.'), Tools::strtolower($entity['title'])); continue; } $savedIds[] = (int)$object->id; } if (count($this->errors)) { return false; } foreach (array_diff($existingIds, $savedIds) as $idToDelete) { $object = new $entity['class']((int)$idToDelete); if (Validate::isLoadedObject($object)) { $object->delete(); } } return true; } /** * @param string $entityKey * @param array $languages * * @return array */ protected function getEntityRowsForDisplay($entityKey, $languages) { if (Tools::isSubmit('submitBulkGuestRegistrationValues') && count($this->errors)) { return $this->getPostedEntityRowsForDisplay($entityKey, $languages); } return $this->getEntityRows($entityKey); } /** * @param string $entityKey * @param array $languages * * @return array */ protected function getPostedEntityRowsForDisplay($entityKey, $languages) { $entity = $this->getManagedEntity($entityKey); $postedRows = Tools::getValue($entity['table'], array()); $rows = array(); if (!is_array($postedRows)) { return $rows; } foreach ($postedRows as $rowKey => $row) { if (!is_array($row)) { continue; } $displayRow = array( 'id' => !empty($row['id']) ? (int)$row['id'] : 0, 'form_key' => $this->sanitizeDynamicRowKey($rowKey), 'active' => !empty($row['active']) ? 1 : 0, 'date_add' => '', 'name' => array(), ); foreach ($languages as $language) { $idLang = (int)$language['id_lang']; $displayRow['name'][$idLang] = isset($row['name'][$idLang]) ? (string)$row['name'][$idLang] : ''; } $rows[] = $displayRow; } return $rows; } /** * @param string|int $rowKey * * @return string */ protected function sanitizeDynamicRowKey($rowKey) { $rowKey = (string)$rowKey; if (preg_match('/^[a-zA-Z0-9_-]+$/', $rowKey)) { return $rowKey; } return 'new_'.time(); } protected function getEntityRows($entityKey) { $entity = $this->getManagedEntity($entityKey); $languages = Language::getLanguages(false); $rows = array(); $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS( 'SELECT a.`'.$entity['identifier'].'`, a.`active`, a.`date_add`, al.`id_lang`, al.`name` FROM `'._DB_PREFIX_.$entity['table'].'` a LEFT JOIN `'._DB_PREFIX_.$entity['table'].'_lang` al ON (a.`'.$entity['identifier'].'` = al.`'.$entity['identifier'].'`) ORDER BY a.`'.$entity['identifier'].'` ASC' ); if ($result) { foreach ($result as $row) { $idEntity = (int)$row[$entity['identifier']]; if (!isset($rows[$idEntity])) { $rows[$idEntity] = array( 'id' => $idEntity, 'form_key' => $idEntity, 'active' => (int)$row['active'], 'date_add' => $row['date_add'], 'name' => array(), ); foreach ($languages as $language) { $rows[$idEntity]['name'][(int)$language['id_lang']] = ''; } } if ((int)$row['id_lang']) { $rows[$idEntity]['name'][(int)$row['id_lang']] = $row['name']; } } } return array_values($rows); } protected function getManagedEntity($entityKey) { $entities = $this->getManagedEntities(); return $entities[$entityKey]; } protected function getManagedEntities() { return array( 'purpose' => array( 'class' => 'GuestRegPurpose', 'table' => 'guest_reg_purpose', 'identifier' => 'id_guest_reg_purpose', 'title' => $this->l('Purpose of visit'), ), 'id_proof' => array( 'class' => 'GuestRegIdProof', 'table' => 'guest_reg_id_proof', 'identifier' => 'id_guest_reg_id_proof', 'title' => $this->l('Identity proof'), ), 'payment_method' => array( 'class' => 'GuestRegPaymentMethod', 'table' => 'guest_reg_payment_method', 'identifier' => 'id_guest_reg_payment_method', 'title' => $this->l('Payment method'), ), ); } protected function getOptionalSectionChoices() { return array( 1 => $this->l('Property Logo'), 2 => $this->l('Additional Guests'), 3 => $this->l('Billing & Corporate Details'), 4 => $this->l('Payment & Deposit'), 5 => $this->l('Property Regulations'), 6 => $this->l('For Office Use Only'), ); } protected function getSelectedOptionalSections() { $value = Configuration::get(self::CONF_OPTIONAL_SECTIONS); if ($value === false || $value === '') { return array(1, 2, 3, 4, 5, 6); } $value = Tools::jsonDecode($value, true); if (!is_array($value)) { return array(); } return array_map('intval', $value); } protected function getEntityIds($entityKey) { $entity = $this->getManagedEntity($entityKey); $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS( 'SELECT `'.$entity['identifier'].'` FROM `'._DB_PREFIX_.$entity['table'].'`' ); if (!$result) { return array(); } return array_map('intval', array_column($result, $entity['identifier'])); } protected function isEmptyEntityRow($row, $languages) { if (!empty($row['id'])) { return false; } if (!isset($row['name']) || !is_array($row['name'])) { return true; } foreach ($languages as $language) { $idLang = (int)$language['id_lang']; if (!empty($row['name'][$idLang])) { return false; } } return true; } }