* @copyright 2007-2022 PrestaShop SA * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) * International Registered Trademark & Property of PrestaShop SA */ use PrestaShop\PrestaShop\Core\Domain\Customer\Exception\CustomerException; use PrestaShop\PrestaShop\Core\Grid\Column\Type\DataColumn; use PrestaShop\PrestaShop\Core\Grid\Definition\GridDefinitionInterface; use PrestaShop\PrestaShop\Core\Grid\Filter\Filter; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; if (!defined('_PS_VERSION_')) { exit; } include_once dirname(__FILE__) . '/models/PchCustomerfieldModel.php'; class Pchcustomerfield extends Module { protected $config_form = false; private $tab_class = 'AdminPchCustomerFields'; public function __construct() { $this->name = 'pchcustomerfield'; $this->tab = 'front_office_features'; $this->version = '1.0.0'; $this->author = 'Prestachamps'; $this->need_instance = 0; /** * Set $this->bootstrap to true if your module is compliant with bootstrap (PrestaShop 1.6) */ $this->bootstrap = true; parent::__construct(); $this->displayName = $this->l('Additional Customer Field'); $this->description = $this->l('Display specialization field on the customer form'); $this->confirmUninstall = $this->l('Are you sure you want to uninstall the module?'); $this->ps_versions_compliancy = array('min' => '1.7', 'max' => _PS_VERSION_); } /** * Don't forget to create update methods if needed: * http://doc.prestashop.com/display/PS16/Enabling+the+Auto-Update */ public function install() { if (!$this->existsTab()) { if (!$this->addTab()) { return false; } } Configuration::updateValue('PCHCUSTOMERFIELD_LIVE_MODE', false); include dirname(__FILE__) . '/sql/install.php'; return parent::install() && $this->registerHook('backOfficeHeader') && $this->registerHook('displayAdminCustomers') && $this->registerHook('actionCustomerGridDefinitionModifier') && $this->registerHook('actionCustomerGridQueryBuilderModifier') && $this->registerHook('additionalCustomerFormFields') && $this->registerHook('actionCustomerFormBuilderModifier') && $this->registerHook('actionAfterCreateCustomerFormHandler') && $this->registerHook('actionAfterUpdateCustomerFormHandler') && $this->alterCustomerTable(); } public function uninstall() { if (!$this->removeTab()) { return false; } Configuration::deleteByName('PCHCUSTOMERFIELD_LIVE_MODE'); include dirname(__FILE__) . '/sql/uninstall.php'; return parent::uninstall() && $this->uninstallAlterCustomerTable(); } private function addTab() { $return = true; $tab = new Tab(); $tab->class_name = $this->tab_class; $tab->id_parent = 0; $tab->module = $this->name; $tab->name[(int) Configuration::get('PS_LANG_DEFAULT')] = $this->l('Customer specialization fields'); $return &= $tab->add(); $subTab = new Tab(); $subTab->class_name = 'AdminPchCustomerfield'; $subTab->id_parent = $tab->id; $subTab->module = $this->name; $subTab->name[(int) Configuration::get('PS_LANG_DEFAULT')] = $this->l('Manage Customer specialization values'); if (true === Tools::version_compare(_PS_VERSION_, '1.7', '>=')) { $subTab->icon = 'settings'; } $return &= $subTab->add(); return $return; } private function removeTab() { $return = true; $tabs = ['PchCustomerfield', $this->tab_class]; foreach ($tabs as $tab) { if (Validate::isLoadedObject($tab = Tab::getInstanceFromClassName($tab))) { return $return &= $tab->delete(); } } return $return; } public function existsTab() { $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS('SELECT id_tab AS id FROM `' . _DB_PREFIX_ . 'tab` t WHERE LOWER(t.`class_name`) = \'' . pSQL($this->tab_class) . '\''); if (count($result) == 0) { return false; } return true; } /** * Alter customer table, add module fields * * @return bool true if success or already done. */ protected function alterCustomerTable() { // check if the column already exists: $column_exists = Db::getInstance()->getValue("SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '" . pSQL(_DB_NAME_) . "' AND TABLE_NAME = '" . pSQL(_DB_PREFIX_) . "customer' AND COLUMN_NAME = 'specialization'"); if((int) !$column_exists) { $sql = 'ALTER TABLE `' . pSQL(_DB_PREFIX_) . 'customer` ADD `specialization` INT NOT NULL'; // CLEAN_INSTALATION 1/2 (if you want to delete all data after an installation) // comment: Db::getInstance()->execute($sql); return true; // and uncomment: // return Db::getInstance()->execute($sql); } return true; } /** * Uninstalls sample tables required for demonstration. * * @return bool */ private function uninstallAlterCustomerTable() { // CLEAN_INSTALATION 2/2 (if you want to delete all data after an installation) // uncomment: // $sql = 'ALTER TABLE `' . pSQL(_DB_PREFIX_) . 'customer` DROP `specialization`'; // return Db::getInstance()->execute($sql); // // and comment: return true; } /** * Load the configuration form */ public function getContent() { /** * If values have been submitted in the form, process. */ if (((bool)Tools::isSubmit('submitPchcustomerfieldModule')) == true) { $this->postProcess(); } $output = $this->renderForm(); return $output; } /** * Create the form that will be displayed in the configuration of your module. */ protected function renderForm() { $helper = new HelperForm(); $helper->show_toolbar = false; $helper->table = $this->table; $helper->module = $this; $helper->default_form_language = $this->context->language->id; $helper->allow_employee_form_lang = Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG', 0); $helper->identifier = $this->identifier; $helper->submit_action = 'submitPchcustomerfieldModule'; $helper->currentIndex = $this->context->link->getAdminLink('AdminModules', false) .'&configure='.$this->name.'&tab_module='.$this->tab.'&module_name='.$this->name; $helper->token = Tools::getAdminTokenLite('AdminModules'); $helper->tpl_vars = array( 'fields_value' => $this->getConfigFormValues(), /* Add values for your inputs */ 'languages' => $this->context->controller->getLanguages(), 'id_language' => $this->context->language->id, ); return $helper->generateForm(array($this->getConfigForm())); } /** * Create the structure of your form. */ protected function getConfigForm() { return array( 'form' => array( 'legend' => array( 'title' => $this->l('Settings'), 'icon' => 'icon-cogs', ), 'input' => array( array( 'type' => 'switch', 'label' => $this->l('Live mode'), 'name' => 'PCHCUSTOMERFIELD_LIVE_MODE', 'is_bool' => true, 'desc' => $this->l('Use this module in live mode'), 'values' => array( array( 'id' => 'active_on', 'value' => true, 'label' => $this->l('Enabled') ), array( 'id' => 'active_off', 'value' => false, 'label' => $this->l('Disabled') ) ), ), ), 'submit' => array( 'title' => $this->l('Save'), ), ), ); } /** * Set values for the inputs. */ protected function getConfigFormValues() { return array( 'PCHCUSTOMERFIELD_LIVE_MODE' => Configuration::get('PCHCUSTOMERFIELD_LIVE_MODE', true), ); } /** * Save form data. */ protected function postProcess() { $form_values = $this->getConfigFormValues(); foreach (array_keys($form_values) as $key) { Configuration::updateValue($key, Tools::getValue($key)); } } /** * Add the CSS & JavaScript files you want to be loaded in the BO. */ public function hookBackOfficeHeader() { if (Tools::getValue('controller') == 'AdminCustomers') { $this->context->controller->addJS($this->_path.'views/js/back.js'); } } /** * This hook displays a new block on the admin customer page * * @param array $params * * @return string */ public function hookDisplayAdminCustomers(array $params) { if (isset($params['id_customer'])) { if (!$specialization = PchCustomerfieldModel::getSpecializationByCustomerId($this->context->language->id, $params['id_customer'])) { return; } $this->smarty->assign([ 'specialization' => $specialization, ]); return $this->fetch('module:pchcustomerfield/views/templates/hook/displayAdminCustomers.tpl'); } } /** * Hook allows to modify Customers grid definition. * This hook is a right place to add/remove columns or actions (bulk, grid). * * @param array $params */ public function hookActionCustomerGridDefinitionModifier(array $params) { if (empty($params['definition'])) { return; } /** @var GridDefinitionInterface $definition */ $definition = $params['definition']; $definition ->getColumns() ->addBefore( 'social_title', (new DataColumn('specialization')) ->setName($this->l('Specialization')) ->setOptions([ 'field' => 'specialization', ]) ); if (!$specializationFields = PchCustomerfieldModel::getSpecializationValues($this->context->language->id, true)) { return; } $specializationFieldsKeys = array_column($specializationFields, 'id_pchcustomerfield'); $specializationFieldsValues = array_column($specializationFields, 'title'); $specializationFieldsKeyValues = array_flip(array_combine($specializationFieldsKeys, $specializationFieldsValues)); $definition->getFilters()->add( (new Filter('specialization', ChoiceType::class)) ->setTypeOptions([ 'choices' => array_merge(['--' => 0], $specializationFieldsKeyValues), 'required' => false ]) ->setAssociatedColumn('specialization') ); } /** * Hook allows to modify Customers query builder and add custom sql statements. * * @param array $params */ public function hookActionCustomerGridQueryBuilderModifier(array $params) { /** @var QueryBuilder $searchQueryBuilder */ $searchQueryBuilder = $params['search_query_builder']; /** @var CustomerFilters $searchCriteria */ $searchCriteria = $params['search_criteria']; $id_lang = (int)Context::getContext()->language->id; $select_specialization_sql = '(SELECT cfl.`title` FROM `'._DB_PREFIX_.'pchcustomerfield_lang` cfl WHERE c.specialization = cfl.id_pchcustomerfield AND cfl.id_lang = '.(int)$id_lang.')'; $searchQueryBuilder->addSelect( 'IF(' . $select_specialization_sql . ' IS NULL,"--",'.$select_specialization_sql.') AS `specialization`' ); if ('specialization' === $searchCriteria->getOrderBy()) { $searchQueryBuilder->orderBy('specialization', $searchCriteria->getOrderWay()); } foreach ($searchCriteria->getFilters() as $filterName => $filterValue) { if ('specialization' === $filterName) { $searchQueryBuilder->andWhere('c.`specialization` = :specialization'); $searchQueryBuilder->setParameter('specialization', $filterValue); //dump($filterValue);die(); if (!$filterValue) { $searchQueryBuilder->orWhere('c.`specialization` IS NULL'); } } } } /** * Hook allows to modify Customers form and add additional form fields as well as modify or add new data to the forms. * FRONT_END * @param array $params * @return array */ public function hookAdditionalCustomerFormFields($params) { if (!Configuration::get('PCHCUSTOMERFIELD_LIVE_MODE')) { return; } if (!$specializationFields = PchCustomerfieldModel::getSpecializationValues($this->context->language->id)) { return; } $specializationFieldsKeys = array_column($specializationFields, 'id_pchcustomerfield'); $specializationFieldsValues = array_column($specializationFields, 'title'); $specializationFieldsKeyValues = array_combine($specializationFieldsKeys, $specializationFieldsValues); $specializationField = [ (new FormField) ->setName('specialization') ->setType('select') ->setRequired(true) // is Required ->setAvailableValues($specializationFieldsKeyValues) ->setLabel($this->l('Specialization')) ]; // We want to insert it after Email if (isset($params['fields'])) { // Where is Email? $position = (int)array_search('email', array_keys($params['fields']), null) + 1; // How many fields do we have? $fieldCount = count($params['fields']); // Lets insert it... $result = array_merge( array_slice($params['fields'], 0, $position), $specializationField, array_slice($params['fields'], $position - $fieldCount) ); $params['fields'] = $result; return; } else { return $specializationField; } } /** * Hook allows to modify Customers form and add additional form fields as well as modify or add new data to the forms. * BACK_END * @param array $params */ public function hookActionCustomerFormBuilderModifier(array $params) { /** @var FormBuilderInterface $formBuilder */ $formBuilder = $params['form_builder']; if (!$specializationFields = PchCustomerfieldModel::getSpecializationValues($this->context->language->id, false)) { return; } $specializationFieldsKeys = array_column($specializationFields, 'id_pchcustomerfield'); $specializationFieldsValues = array_column($specializationFields, 'title'); $specializationFieldsKeyValues = array_flip(array_combine($specializationFieldsKeys, $specializationFieldsValues)); $formBuilder->add('specialization', ChoiceType::class, [ 'choices' => $specializationFieldsKeyValues, 'label' => $this->l('Specialization'), 'required' => true, 'placeholder' => $this->l('Please select'), ]); $customer = new Customer($params['id']); $params['data']['specialization'] = $customer->specialization; $formBuilder->setData($params['data']); } /** * Hook allows to modify Customers form and add additional form fields as well as modify or add new data to the forms. * * @param array $params * * @throws CustomerException * @throws PrestaShopDatabaseException * @throws PrestaShopException */ public function hookActionAfterUpdateCustomerFormHandler(array $params) { $this->updateCustomerSpecialization($params); } /** * Hook allows to modify Customers form and add additional form fields as well as modify or add new data to the forms. * * @param array $params * * @throws CustomerException * @throws PrestaShopDatabaseException * @throws PrestaShopException */ public function hookActionAfterCreateCustomerFormHandler(array $params) { $this->updateCustomerSpecialization($params); } /** * Update / Create * * @param array $params * * @throws CustomerException * @throws PrestaShopDatabaseException * @throws PrestaShopException */ private function updateCustomerSpecialization(array $params) { $customerId = (int)$params['id']; /** @var array $customerFormData */ $customerFormData = $params['form_data']; $specialization = $customerFormData['specialization']; try { $customer = new Customer($customerId); $customer->specialization = $specialization; $customer->update(); } catch (CustomerException $exception) { throw new CustomerException($exception); } catch (PrestaShopDatabaseException $e) { throw new PrestaShopDatabaseException($e); } catch (PrestaShopException $e) { throw new PrestaShopException($e); } } public function getSpecializationBySpecializationId($specializationId) { if (!(int)$specializationId) { return false; } return PchCustomerfieldModel::getSpecializationBySpecializationId($this->context->language->id, (int)$specializationId); } }