commit a2fa49071a85aea922e50b7ff9ad0eb23c7ae9f4 Author: sujan Date: Tue Aug 6 18:06:00 2024 +0545 first commit diff --git a/.htaccess.txt b/.htaccess.txt new file mode 100644 index 0000000..35f245e --- /dev/null +++ b/.htaccess.txt @@ -0,0 +1,89 @@ +## +# READ THIS COMPLETELY IF YOU CHOOSE TO USE THIS FILE! +# +# 1.To use URL Alias you need to be running apache with mod_rewrite enabled. +# 2. In your opencart directory rename .htaccess.txt (this file) to .htaccess +# +# For any support issues please visit: https://www.opencart.com +# +# The line 'Options +FollowSymLinks' may cause problems with some server configurations. +# It is required for the use of Apache mod_rewrite, but it may have already been set by +# your server administrator in a way that disallows changing it in this .htaccess file. +# If you encounter problems (e.g. site is not loading), comment out this line by adding a # in front +# FLOC is a feature suggested by Google, if this header shall not be set, disable the line +# having 'interest-cohort' by adding a # in front +## + +## No directory listings + + IndexIgnore * + + +## No-Referrer-Header + + Header set Referrer-Policy "no-referrer" + + +## Suppress mime type detection in browsers for unknown types and prevent FLOC + + Header always set X-Content-Type-Options "nosniff" + Header always set Permissions-Policy "interest-cohort=()" + + +## Can be commented out if causes errors, see notes above. +Options +FollowSymlinks + +## Prevent Directory listing +Options -Indexes + +## Prevent Direct Access to files + + Require all denied +## For apache 2.2 and older, replace "Require all denied" with these two lines : +# Order deny,allow +# Deny from all + + +## SEO URL Settings +RewriteEngine On +## If your opencart installation does not run on the main web folder make sure you folder it does run in ie. / becomes /shop/ +RewriteBase / +## Rewrite Rules +RewriteRule ^system/storage/(.*) index.php?route=error/not_found [L] +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteCond %{REQUEST_URI} !.*\.(ico|gif|jpg|jpeg|png|webp|js|css|svg) +RewriteRule ^([^?]*) index.php?_route_=$1 [L,QSA] + +## Optional error documents +#ErrorDocument 400 /index.php?route=error/not_found +#ErrorDocument 401 /index.php?route=error/permission +#ErrorDocument 403 /index.php?route=error/not_found +#ErrorDocument 404 /index.php?route=error/not_found +#ErrorDocument 500 /index.php?route=error/not_found +#ErrorDocument 503 /index.php?route=error/not_found + +## Additional Settings that may need to be enabled for some servers +## Uncomment the commands by removing the # sign in front of it. +## If you get an "Internal Server Error 500" after enabling any of the following settings, restore the # as this means your host doesn't allow that. + +# 1. If your cart only allows you to add one item at a time, it is possible register_globals is on. This may work to disable it: +# php_flag register_globals off + +# 2. If your cart has magic quotes enabled, This may work to disable it: +# php_flag magic_quotes_gpc Off + +# 3. Set max upload file size. Most hosts will limit this and not allow it to be overridden but you can try +# php_value upload_max_filesize 999M + +# 4. set max post size. uncomment this line if you have a lot of product options or are getting errors where forms are not saving all fields +# php_value post_max_size 999M + +# 5. set max time script can take. uncomment this line if you have a lot of product options or are getting errors where forms are not saving all fields +# php_value max_execution_time 200 + +# 6. set max time for input to be recieved. Uncomment this line if you have a lot of product options or are getting errors where forms are not saving all fields +# php_value max_input_time 200 + +# 7. disable open_basedir limitations +# php_admin_value open_basedir none diff --git a/admininistrator/config.php b/admininistrator/config.php new file mode 100644 index 0000000..20d8cf6 --- /dev/null +++ b/admininistrator/config.php @@ -0,0 +1,36 @@ +load->language('catalog/attribute'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . (string)$this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . (string)$this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . (int)$this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('catalog/attribute', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('catalog/attribute.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('catalog/attribute.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('catalog/attribute', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('catalog/attribute'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'ad.name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('catalog/attribute.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['attributes'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('catalog/attribute'); + + $attribute_total = $this->model_catalog_attribute->getTotalAttributes(); + + $results = $this->model_catalog_attribute->getAttributes($filter_data); + + foreach ($results as $result) { + $data['attributes'][] = [ + 'attribute_id' => $result['attribute_id'], + 'name' => $result['name'], + 'attribute_group' => $result['attribute_group'], + 'sort_order' => $result['sort_order'], + 'edit' => $this->url->link('catalog/attribute.form', 'user_token=' . $this->session->data['user_token'] . '&attribute_id=' . $result['attribute_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('catalog/attribute.list', 'user_token=' . $this->session->data['user_token'] . '&sort=ad.name' . $url); + $data['sort_attribute_group'] = $this->url->link('catalog/attribute.list', 'user_token=' . $this->session->data['user_token'] . '&sort=attribute_group' . $url); + $data['sort_sort_order'] = $this->url->link('catalog/attribute.list', 'user_token=' . $this->session->data['user_token'] . '&sort=a.sort_order' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $attribute_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('catalog/attribute.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($attribute_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($attribute_total - $this->config->get('config_pagination_admin'))) ? $attribute_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $attribute_total, ceil($attribute_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('catalog/attribute_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('catalog/attribute'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['attribute_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('catalog/attribute', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('catalog/attribute.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('catalog/attribute', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['attribute_id'])) { + $this->load->model('catalog/attribute'); + + $attribute_info = $this->model_catalog_attribute->getAttribute($this->request->get['attribute_id']); + } + + if (isset($this->request->get['attribute_id'])) { + $data['attribute_id'] = (int)$this->request->get['attribute_id']; + } else { + $data['attribute_id'] = 0; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (isset($this->request->get['attribute_id'])) { + $data['attribute_description'] = $this->model_catalog_attribute->getDescriptions($this->request->get['attribute_id']); + } else { + $data['attribute_description'] = []; + } + + $this->load->model('catalog/attribute_group'); + + $data['attribute_groups'] = $this->model_catalog_attribute_group->getAttributeGroups(); + + if (!empty($attribute_info)) { + $data['attribute_group_id'] = $attribute_info['attribute_group_id']; + } else { + $data['attribute_group_id'] = 0; + } + + if (!empty($attribute_info)) { + $data['sort_order'] = $attribute_info['sort_order']; + } else { + $data['sort_order'] = 0; + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('catalog/attribute_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('catalog/attribute'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'catalog/attribute')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if (!$this->request->post['attribute_group_id']) { + $json['error']['attribute_group'] = $this->language->get('error_attribute_group'); + } + + foreach ($this->request->post['attribute_description'] as $language_id => $value) { + if ((oc_strlen(trim($value['name'])) < 1) || (oc_strlen($value['name']) > 64)) { + $json['error']['name_' . $language_id] = $this->language->get('error_name'); + } + } + + if (isset($json['error']) && !isset($json['error']['warning'])) { + $json['error']['warning'] = $this->language->get('error_warning'); + } + + if (!$json) { + $this->load->model('catalog/attribute'); + + if (!$this->request->post['attribute_id']) { + $json['attribute_id'] = $this->model_catalog_attribute->addAttribute($this->request->post); + } else { + $this->model_catalog_attribute->editAttribute($this->request->post['attribute_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('catalog/attribute'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'catalog/attribute')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('catalog/product'); + + foreach ($selected as $attribute_id) { + $product_total = $this->model_catalog_product->getTotalProductsByAttributeId($attribute_id); + + if ($product_total) { + $json['error'] = sprintf($this->language->get('error_product'), $product_total); + } + } + + if (!$json) { + $this->load->model('catalog/attribute'); + + foreach ($selected as $attribute_id) { + $this->model_catalog_attribute->deleteAttribute($attribute_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function autocomplete(): void { + $json = []; + + if (isset($this->request->get['filter_name'])) { + $this->load->model('catalog/attribute'); + + $filter_data = [ + 'filter_name' => $this->request->get['filter_name'], + 'start' => 0, + 'limit' => 5 + ]; + + $results = $this->model_catalog_attribute->getAttributes($filter_data); + + foreach ($results as $result) { + $json[] = [ + 'attribute_id' => $result['attribute_id'], + 'name' => strip_tags(html_entity_decode($result['name'], ENT_QUOTES, 'UTF-8')), + 'attribute_group' => $result['attribute_group'] + ]; + } + } + + $sort_order = []; + + foreach ($json as $key => $value) { + $sort_order[$key] = $value['name']; + } + + array_multisort($sort_order, SORT_ASC, $json); + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/catalog/attribute_group.php b/admininistrator/controller/catalog/attribute_group.php new file mode 100644 index 0000000..9e08cd3 --- /dev/null +++ b/admininistrator/controller/catalog/attribute_group.php @@ -0,0 +1,319 @@ +load->language('catalog/attribute_group'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('catalog/attribute_group', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('catalog/attribute_group.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('catalog/attribute_group.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('catalog/attribute_group', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('catalog/attribute_group'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'agd.name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('catalog/attribute_group.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['attribute_groups'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('catalog/attribute_group'); + + $attribute_group_total = $this->model_catalog_attribute_group->getTotalAttributeGroups(); + + $results = $this->model_catalog_attribute_group->getAttributeGroups($filter_data); + + foreach ($results as $result) { + $data['attribute_groups'][] = [ + 'attribute_group_id' => $result['attribute_group_id'], + 'name' => $result['name'], + 'sort_order' => $result['sort_order'], + 'edit' => $this->url->link('catalog/attribute_group.form', 'user_token=' . $this->session->data['user_token'] . '&attribute_group_id=' . $result['attribute_group_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('catalog/attribute_group.list', 'user_token=' . $this->session->data['user_token'] . '&sort=agd.name' . $url); + $data['sort_sort_order'] = $this->url->link('catalog/attribute_group.list', 'user_token=' . $this->session->data['user_token'] . '&sort=ag.sort_order' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $attribute_group_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('catalog/attribute_group.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($attribute_group_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($attribute_group_total - $this->config->get('config_pagination_admin'))) ? $attribute_group_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $attribute_group_total, ceil($attribute_group_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('catalog/attribute_group_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('catalog/attribute_group'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['attribute_group_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('catalog/attribute_group', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('catalog/attribute_group.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('catalog/attribute_group', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['attribute_group_id'])) { + $this->load->model('catalog/attribute_group'); + + $attribute_group_info = $this->model_catalog_attribute_group->getAttributeGroup($this->request->get['attribute_group_id']); + } + + if (isset($this->request->get['attribute_group_id'])) { + $data['attribute_group_id'] = (int)$this->request->get['attribute_group_id']; + } else { + $data['attribute_group_id'] = 0; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (isset($this->request->get['attribute_group_id'])) { + $data['attribute_group_description'] = $this->model_catalog_attribute_group->getDescriptions($this->request->get['attribute_group_id']); + } else { + $data['attribute_group_description'] = []; + } + + if (!empty($attribute_group_info)) { + $data['sort_order'] = $attribute_group_info['sort_order']; + } else { + $data['sort_order'] = ''; + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('catalog/attribute_group_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('catalog/attribute_group'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'catalog/attribute_group')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + foreach ($this->request->post['attribute_group_description'] as $language_id => $value) { + if ((oc_strlen(trim($value['name'])) < 1) || (oc_strlen($value['name']) > 64)) { + $json['error']['name_' . $language_id] = $this->language->get('error_name'); + } + } + + if (isset($json['error']) && !isset($json['error']['warning'])) { + $json['error']['warning'] = $this->language->get('error_warning'); + } + + if (!$json) { + $this->load->model('catalog/attribute_group'); + + if (!$this->request->post['attribute_group_id']) { + $json['attribute_group_id'] = $this->model_catalog_attribute_group->addAttributeGroup($this->request->post); + } else { + $this->model_catalog_attribute_group->editAttributeGroup($this->request->post['attribute_group_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('catalog/attribute_group'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'catalog/attribute_group')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('catalog/attribute'); + + foreach ($selected as $attribute_group_id) { + $attribute_total = $this->model_catalog_attribute->getTotalAttributesByAttributeGroupId($attribute_group_id); + + if ($attribute_total) { + $json['error'] = sprintf($this->language->get('error_attribute'), $attribute_total); + } + } + + if (!$json) { + $this->load->model('catalog/attribute_group'); + + foreach ($selected as $attribute_group_id) { + $this->model_catalog_attribute_group->deleteAttributeGroup($attribute_group_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/catalog/category.php b/admininistrator/controller/catalog/category.php new file mode 100644 index 0000000..1507392 --- /dev/null +++ b/admininistrator/controller/catalog/category.php @@ -0,0 +1,536 @@ +load->language('catalog/category'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('catalog/category', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['repair'] = $this->url->link('catalog/category.repair', 'user_token=' . $this->session->data['user_token']); + $data['add'] = $this->url->link('catalog/category.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('catalog/category.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('catalog/category', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('catalog/category'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('catalog/category.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['categories'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('catalog/category'); + + $category_total = $this->model_catalog_category->getTotalCategories(); + + $results = $this->model_catalog_category->getCategories($filter_data); + + foreach ($results as $result) { + $data['categories'][] = [ + 'category_id' => $result['category_id'], + 'name' => $result['name'], + 'status' => $result['status'], + 'sort_order' => $result['sort_order'], + 'edit' => $this->url->link('catalog/category.form', 'user_token=' . $this->session->data['user_token'] . '&category_id=' . $result['category_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('catalog/category.list', 'user_token=' . $this->session->data['user_token'] . '&sort=name' . $url); + $data['sort_sort_order'] = $this->url->link('catalog/category.list', 'user_token=' . $this->session->data['user_token'] . '&sort=sort_order' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $category_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('catalog/category.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($category_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($category_total - $this->config->get('config_pagination_admin'))) ? $category_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $category_total, ceil($category_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('catalog/category_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('catalog/category'); + + $this->document->setTitle($this->language->get('heading_title')); + + $this->document->addScript('view/javascript/ckeditor/ckeditor.js'); + $this->document->addScript('view/javascript/ckeditor/adapters/jquery.js'); + + $data['text_form'] = !isset($this->request->get['category_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('catalog/category', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('catalog/category.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('catalog/category', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['category_id'])) { + $this->load->model('catalog/category'); + + $category_info = $this->model_catalog_category->getCategory($this->request->get['category_id']); + } + + if (isset($this->request->get['category_id'])) { + $data['category_id'] = (int)$this->request->get['category_id']; + } else { + $data['category_id'] = 0; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (isset($this->request->get['category_id'])) { + $data['category_description'] = $this->model_catalog_category->getDescriptions($this->request->get['category_id']); + } else { + $data['category_description'] = []; + } + + if (!empty($category_info)) { + $data['path'] = $category_info['path']; + } else { + $data['path'] = ''; + } + + if (!empty($category_info)) { + $data['parent_id'] = $category_info['parent_id']; + } else { + $data['parent_id'] = 0; + } + + $this->load->model('catalog/filter'); + + if (isset($this->request->get['category_id'])) { + $filters = $this->model_catalog_category->getFilters($this->request->get['category_id']); + } else { + $filters = []; + } + + $data['category_filters'] = []; + + foreach ($filters as $filter_id) { + $filter_info = $this->model_catalog_filter->getFilter($filter_id); + + if ($filter_info) { + $data['category_filters'][] = [ + 'filter_id' => $filter_info['filter_id'], + 'name' => $filter_info['group'] . ' > ' . $filter_info['name'] + ]; + } + } + + $data['stores'] = []; + + $data['stores'][] = [ + 'store_id' => 0, + 'name' => $this->language->get('text_default') + ]; + + $this->load->model('setting/store'); + + $stores = $this->model_setting_store->getStores(); + + foreach ($stores as $store) { + $data['stores'][] = [ + 'store_id' => $store['store_id'], + 'name' => $store['name'] + ]; + } + + if (isset($this->request->get['category_id'])) { + $data['category_store'] = $this->model_catalog_category->getStores($this->request->get['category_id']); + } else { + $data['category_store'] = [0]; + } + + if (!empty($category_info)) { + $data['image'] = $category_info['image']; + } else { + $data['image'] = ''; + } + + $this->load->model('tool/image'); + + $data['placeholder'] = $this->model_tool_image->resize('no_image.png', 100, 100); + + if (is_file(DIR_IMAGE . html_entity_decode($data['image'], ENT_QUOTES, 'UTF-8'))) { + $data['thumb'] = $this->model_tool_image->resize(html_entity_decode($data['image'], ENT_QUOTES, 'UTF-8'), 100, 100); + } else { + $data['thumb'] = $data['placeholder']; + } + + if (!empty($category_info)) { + $data['top'] = $category_info['top']; + } else { + $data['top'] = 0; + } + + if (!empty($category_info)) { + $data['column'] = $category_info['column']; + } else { + $data['column'] = 1; + } + + if (!empty($category_info)) { + $data['sort_order'] = $category_info['sort_order']; + } else { + $data['sort_order'] = 0; + } + + if (!empty($category_info)) { + $data['status'] = $category_info['status']; + } else { + $data['status'] = true; + } + + $data['category_seo_url'] = []; + + if (isset($this->request->get['category_id'])) { + $results = $this->model_catalog_category->getSeoUrls($this->request->get['category_id']); + + foreach ($results as $store_id => $languages) { + foreach ($languages as $language_id => $keyword) { + $pos = strrpos($keyword, '/'); + + if ($pos !== false) { + $keyword = substr($keyword, $pos + 1); + } else { + $keyword = $keyword; + } + + $data['category_seo_url'][$store_id][$language_id] = $keyword; + } + } + } + + $this->load->model('design/layout'); + + $data['layouts'] = $this->model_design_layout->getLayouts(); + + if (isset($this->request->get['category_id'])) { + $data['category_layout'] = $this->model_catalog_category->getLayouts($this->request->get['category_id']); + } else { + $data['category_layout'] = []; + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('catalog/category_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('catalog/category'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'catalog/category')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + foreach ($this->request->post['category_description'] as $language_id => $value) { + if ((oc_strlen(trim($value['name'])) < 1) || (oc_strlen($value['name']) > 255)) { + $json['error']['name_' . $language_id] = $this->language->get('error_name'); + } + + if ((oc_strlen(trim($value['meta_title'])) < 1) || (oc_strlen($value['meta_title']) > 255)) { + $json['error']['meta_title_' . $language_id] = $this->language->get('error_meta_title'); + } + } + + $this->load->model('catalog/category'); + + if (isset($this->request->post['category_id']) && $this->request->post['parent_id']) { + $results = $this->model_catalog_category->getPaths($this->request->post['parent_id']); + + foreach ($results as $result) { + if ($result['path_id'] == $this->request->post['category_id']) { + $json['error']['parent'] = $this->language->get('error_parent'); + + break; + } + } + } + + if ($this->request->post['category_seo_url']) { + $this->load->model('design/seo_url'); + + foreach ($this->request->post['category_seo_url'] as $store_id => $language) { + foreach ($language as $language_id => $keyword) { + if ((oc_strlen(trim($keyword)) < 1) || (oc_strlen($keyword) > 64)) { + $json['error']['keyword_' . $store_id . '_' . $language_id] = $this->language->get('error_keyword'); + } + + if (preg_match('/[^a-zA-Z0-9\/_-]|[\p{Cyrillic}]+/u', $keyword)) { + $json['error']['keyword_' . $store_id . '_' . $language_id] = $this->language->get('error_keyword_character'); + } + + $seo_url_info = $this->model_design_seo_url->getSeoUrlByKeyword($keyword, $store_id); + + if ($seo_url_info && (!isset($this->request->post['category_id']) || $seo_url_info['key'] != 'path' || $seo_url_info['value'] != $this->model_catalog_category->getPath($this->request->post['category_id']))) { + $json['error']['keyword_' . $store_id . '_' . $language_id] = $this->language->get('error_keyword_exists'); + } + } + } + } + + if (isset($json['error']) && !isset($json['error']['warning'])) { + $json['error']['warning'] = $this->language->get('error_warning'); + } + + if (!$json) { + if (!$this->request->post['category_id']) { + $json['category_id'] = $this->model_catalog_category->addCategory($this->request->post); + } else { + $this->model_catalog_category->editCategory($this->request->post['category_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function repair(): void { + $this->load->language('catalog/category'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'catalog/category')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('catalog/category'); + + $this->model_catalog_category->repairCategories(); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('catalog/category'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'catalog/category')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('catalog/category'); + + foreach ($selected as $category_id) { + $this->model_catalog_category->deleteCategory($category_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function autocomplete(): void { + $json = []; + + if (isset($this->request->get['filter_name'])) { + $this->load->model('catalog/category'); + + $filter_data = [ + 'filter_name' => '%' . $this->request->get['filter_name'] . '%', + 'sort' => 'name', + 'order' => 'ASC', + 'start' => 0, + 'limit' => 5 + ]; + + $results = $this->model_catalog_category->getCategories($filter_data); + + foreach ($results as $result) { + $json[] = [ + 'category_id' => $result['category_id'], + 'name' => $result['name'] + ]; + } + } + + $sort_order = []; + + foreach ($json as $key => $value) { + $sort_order[$key] = $value['name']; + } + + array_multisort($sort_order, SORT_ASC, $json); + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/catalog/download.php b/admininistrator/controller/catalog/download.php new file mode 100644 index 0000000..45c20c6 --- /dev/null +++ b/admininistrator/controller/catalog/download.php @@ -0,0 +1,596 @@ +load->language('catalog/download'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('catalog/download', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('catalog/download.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('catalog/download.delete', 'user_token=' . $this->session->data['user_token']); + + $data['user_token'] = $this->session->data['user_token']; + + $data['list'] = $this->getList(); + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('catalog/download', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('catalog/download'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'dd.name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('catalog/download.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['downloads'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('catalog/download'); + + $download_total = $this->model_catalog_download->getTotalDownloads(); + + $results = $this->model_catalog_download->getDownloads($filter_data); + + foreach ($results as $result) { + $data['downloads'][] = [ + 'download_id' => $result['download_id'], + 'name' => $result['name'], + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])), + 'edit' => $this->url->link('catalog/download.form', 'user_token=' . $this->session->data['user_token'] . '&download_id=' . $result['download_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('catalog/download.list', 'user_token=' . $this->session->data['user_token'] . '&sort=dd.name' . $url); + $data['sort_date_added'] = $this->url->link('catalog/download.list', 'user_token=' . $this->session->data['user_token'] . '&sort=d.date_added' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $download_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('catalog/download.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($download_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($download_total - $this->config->get('config_pagination_admin'))) ? $download_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $download_total, ceil($download_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('catalog/download_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('catalog/download'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['download_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + // Use the ini_get('upload_max_filesize') for the max file size + $data['error_upload_size'] = sprintf($this->language->get('error_upload_size'), ini_get('upload_max_filesize')); + + $data['config_file_max_size'] = ((int)preg_filter('/[^0-9]/', '', ini_get('upload_max_filesize')) * 1024 * 1024); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('catalog/download', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('catalog/download.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('catalog/download', 'user_token=' . $this->session->data['user_token'] . $url); + $data['upload'] = $this->url->link('catalog/download.upload', 'user_token=' . $this->session->data['user_token']); + + if (isset($this->request->get['download_id'])) { + $this->load->model('catalog/download'); + + $download_info = $this->model_catalog_download->getDownload($this->request->get['download_id']); + } + + if (isset($this->request->get['download_id'])) { + $data['download_id'] = (int)$this->request->get['download_id']; + } else { + $data['download_id'] = 0; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (isset($this->request->get['download_id'])) { + $data['download_description'] = $this->model_catalog_download->getDescriptions($this->request->get['download_id']); + } else { + $data['download_description'] = []; + } + + if (!empty($download_info)) { + $data['filename'] = $download_info['filename']; + } else { + $data['filename'] = ''; + } + + if (!empty($download_info)) { + $data['mask'] = $download_info['mask']; + } else { + $data['mask'] = ''; + } + + $data['report'] = $this->getReport(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('catalog/download_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('catalog/download'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'catalog/download')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + foreach ($this->request->post['download_description'] as $language_id => $value) { + if ((oc_strlen(trim($value['name'])) < 3) || (oc_strlen($value['name']) > 64)) { + $json['error']['name_' . $language_id] = $this->language->get('error_name'); + } + } + + if ((oc_strlen($this->request->post['filename']) < 3) || (oc_strlen($this->request->post['filename']) > 128)) { + $json['error']['filename'] = $this->language->get('error_filename'); + } + + if (substr(str_replace('\\', '/', realpath(DIR_DOWNLOAD . $this->request->post['filename'])), 0, strlen(DIR_DOWNLOAD)) != DIR_DOWNLOAD) { + $json['error']['filename'] = $this->language->get('error_directory'); + } + + if (!is_file(DIR_DOWNLOAD . $this->request->post['filename'])) { + $json['error']['filename'] = $this->language->get('error_exists'); + } + + if (preg_match('/[^a-zA-Z0-9\/._-]|[\p{Cyrillic}]+/u', $this->request->post['filename'])) { + $json['error']['filename'] = $this->language->get('error_filename_character'); + } + + if ((oc_strlen($this->request->post['mask']) < 3) || (oc_strlen($this->request->post['mask']) > 128)) { + $json['error']['mask'] = $this->language->get('error_mask'); + } + + if (preg_match('/[^a-zA-Z0-9\/._-]|[\p{Cyrillic}]+/u', $this->request->post['mask'])) { + $json['error']['mask'] = $this->language->get('error_mask_character'); + } + + if (isset($json['error']) && !isset($json['error']['warning'])) { + $json['error']['warning'] = $this->language->get('error_warning'); + } + + if (!$json) { + $this->load->model('catalog/download'); + + if (!$this->request->post['download_id']) { + $json['download_id'] = $this->model_catalog_download->addDownload($this->request->post); + } else { + $this->model_catalog_download->editDownload($this->request->post['download_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('catalog/download'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'catalog/download')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('catalog/product'); + + foreach ($selected as $download_id) { + $product_total = $this->model_catalog_product->getTotalProductsByDownloadId($download_id); + + if ($product_total) { + $json['error'] = sprintf($this->language->get('error_product'), $product_total); + } + } + + if (!$json) { + $this->load->model('catalog/download'); + + foreach ($selected as $download_id) { + $this->model_catalog_download->deleteDownload($download_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function report(): void { + $this->load->language('catalog/download'); + + $this->response->setOutput($this->getReport()); + } + + /** + * @return string + */ + private function getReport(): string { + if (isset($this->request->get['download_id'])) { + $download_id = (int)$this->request->get['download_id']; + } else { + $download_id = 0; + } + + if (isset($this->request->get['page']) && $this->request->get['route'] == 'catalog/download.report') { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $limit = 10; + + $data['reports'] = []; + + $this->load->model('catalog/download'); + $this->load->model('customer/customer'); + $this->load->model('setting/store'); + + $results = $this->model_catalog_download->getReports($download_id, ($page - 1) * $limit, $limit); + + foreach ($results as $result) { + $store_info = $this->model_setting_store->getStore($result['store_id']); + + if ($store_info) { + $store = $store_info['name']; + } elseif (!$result['store_id']) { + $store = $this->config->get('config_name'); + } else { + $store = ''; + } + + $data['reports'][] = [ + 'ip' => $result['ip'], + 'account' => $this->model_customer_customer->getTotalCustomersByIp($result['ip']), + 'store' => $store, + 'country' => $result['country'], + 'date_added' => date($this->language->get('datetime_format'), strtotime($result['date_added'])), + 'filter_ip' => $this->url->link('customer/customer', 'user_token=' . $this->session->data['user_token'] . '&filter_ip=' . $result['ip']) + ]; + } + + $report_total = $this->model_catalog_download->getTotalReports($download_id); + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $report_total, + 'page' => $page, + 'limit' => $limit, + 'url' => $this->url->link('catalog/download.report', 'user_token=' . $this->session->data['user_token'] . '&download_id=' . $download_id . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($report_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($report_total - $limit)) ? $report_total : ((($page - 1) * $limit) + $limit), $report_total, ceil($report_total / $limit)); + + return $this->load->view('catalog/download_report', $data); + } + + /** + * @return void + */ + public function upload(): void { + $this->load->language('catalog/download'); + + $json = []; + + // Check user has permission + if (!$this->user->hasPermission('modify', 'catalog/download')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (empty($this->request->files['file']['name']) || !is_file($this->request->files['file']['tmp_name'])) { + $json['error'] = $this->language->get('error_upload'); + } + + if (!$json) { + // Sanitize the filename + $filename = basename(html_entity_decode($this->request->files['file']['name'], ENT_QUOTES, 'UTF-8')); + + // Validate the filename length + if ((oc_strlen($filename) < 3) || (oc_strlen($filename) > 128)) { + $json['error'] = $this->language->get('error_filename'); + } + + // Allowed file extension types + $allowed = []; + + $extension_allowed = preg_replace('~\r?\n~', "\n", $this->config->get('config_file_ext_allowed')); + + $filetypes = explode("\n", $extension_allowed); + + foreach ($filetypes as $filetype) { + $allowed[] = trim($filetype); + } + + if (!in_array(strtolower(substr(strrchr($filename, '.'), 1)), $allowed)) { + $json['error'] = $this->language->get('error_file_type'); + } + + // Allowed file mime types + $allowed = []; + + $mime_allowed = preg_replace('~\r?\n~', "\n", $this->config->get('config_file_mime_allowed')); + + $filetypes = explode("\n", $mime_allowed); + + foreach ($filetypes as $filetype) { + $allowed[] = trim($filetype); + } + + if (!in_array($this->request->files['file']['type'], $allowed)) { + $json['error'] = $this->language->get('error_file_type'); + } + + // Return any upload error + if ($this->request->files['file']['error'] != UPLOAD_ERR_OK) { + $json['error'] = $this->language->get('error_upload_' . $this->request->files['file']['error']); + } + } + + if (!$json) { + $file = $filename . '.' . oc_token(32); + + move_uploaded_file($this->request->files['file']['tmp_name'], DIR_DOWNLOAD . $file); + + $json['filename'] = $file; + $json['mask'] = $filename; + + $json['success'] = $this->language->get('text_upload'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function download(): void { + $this->load->language('catalog/download'); + + if (isset($this->request->get['filename'])) { + $filename = basename($this->request->get['filename']); + } else { + $filename = ''; + } + + $file = DIR_DOWNLOAD . $filename; + + if (is_file($file)) { + if (!headers_sent()) { + header('Content-Type: application/octet-stream'); + header('Content-Description: File Transfer'); + header('Content-Disposition: attachment; filename="' . $filename . '"'); + header('Content-Transfer-Encoding: binary'); + header('Expires: 0'); + header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); + header('Pragma: public'); + header('Content-Length: ' . filesize($file)); + + readfile($file, 'rb'); + exit; + } else { + exit($this->language->get('error_headers_sent')); + } + } else { + $this->load->language('error/not_found'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('error/not_found', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('error/not_found', $data)); + } + } + + /** + * @return void + */ + public function autocomplete(): void { + $json = []; + + if (isset($this->request->get['filter_name'])) { + $this->load->model('catalog/download'); + + $filter_data = [ + 'filter_name' => $this->request->get['filter_name'], + 'start' => 0, + 'limit' => 5 + ]; + + $results = $this->model_catalog_download->getDownloads($filter_data); + + foreach ($results as $result) { + $json[] = [ + 'download_id' => $result['download_id'], + 'name' => strip_tags(html_entity_decode($result['name'], ENT_QUOTES, 'UTF-8')) + ]; + } + } + + $sort_order = []; + + foreach ($json as $key => $value) { + $sort_order[$key] = $value['name']; + } + + array_multisort($sort_order, SORT_ASC, $json); + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/catalog/filter.php b/admininistrator/controller/catalog/filter.php new file mode 100644 index 0000000..e1240ac --- /dev/null +++ b/admininistrator/controller/catalog/filter.php @@ -0,0 +1,366 @@ +load->language('catalog/filter'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('catalog/filter', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('catalog/filter.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('catalog/filter.delete', 'user_token=' . $this->session->data['user_token']); + + $data['user_token'] = $this->session->data['user_token']; + + $data['list'] = $this->getList(); + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('catalog/filter', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('catalog/filter'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'fgd.name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('catalog/filter.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['filters'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('catalog/filter'); + + $filter_total = $this->model_catalog_filter->getTotalGroups(); + + $results = $this->model_catalog_filter->getGroups($filter_data); + + foreach ($results as $result) { + $data['filters'][] = [ + 'filter_group_id' => $result['filter_group_id'], + 'name' => $result['name'], + 'sort_order' => $result['sort_order'], + 'edit' => $this->url->link('catalog/filter.form', 'user_token=' . $this->session->data['user_token'] . '&filter_group_id=' . $result['filter_group_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['sort_name'] = $this->url->link('catalog/filter.list', 'user_token=' . $this->session->data['user_token'] . '&sort=fgd.name' . $url); + $data['sort_sort_order'] = $this->url->link('catalog/filter.list', 'user_token=' . $this->session->data['user_token'] . '&sort=fg.sort_order' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $filter_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('catalog/filter.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($filter_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($filter_total - $this->config->get('config_pagination_admin'))) ? $filter_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $filter_total, ceil($filter_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('catalog/filter_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('catalog/filter'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['filter_group_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('catalog/filter', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('catalog/filter.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('catalog/filter', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['filter_group_id'])) { + $this->load->model('catalog/filter'); + + $filter_group_info = $this->model_catalog_filter->getGroup($this->request->get['filter_group_id']); + } + + if (isset($this->request->get['filter_group_id'])) { + $data['filter_group_id'] = (int)$this->request->get['filter_group_id']; + } else { + $data['filter_group_id'] = 0; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (isset($this->request->get['filter_group_id'])) { + $data['filter_group_description'] = $this->model_catalog_filter->getGroupDescriptions($this->request->get['filter_group_id']); + } else { + $data['filter_group_description'] = []; + } + + if (!empty($filter_group_info)) { + $data['sort_order'] = $filter_group_info['sort_order']; + } else { + $data['sort_order'] = ''; + } + + if (!empty($filter_group_info)) { + $data['filters'] = $this->model_catalog_filter->getDescriptions($this->request->get['filter_group_id']); + } else { + $data['filters'] = []; + } + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('catalog/filter_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('catalog/filter'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'catalog/filter')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + foreach ($this->request->post['filter_group_description'] as $language_id => $value) { + if ((oc_strlen(trim($value['name'])) < 1) || (oc_strlen($value['name']) > 64)) { + $json['error']['group_' . $language_id] = $this->language->get('error_group'); + } + } + + if (isset($this->request->post['filter'])) { + foreach ($this->request->post['filter'] as $key => $filter) { + foreach ($filter['filter_description'] as $language_id => $filter_description) { + if ((oc_strlen(trim($filter_description['name'])) < 1) || (oc_strlen($filter_description['name']) > 64)) { + $json['error']['filter_' . $key . '_' . $language_id] = $this->language->get('error_name'); + } + } + } + } else { + $json['error']['warning'] = $this->language->get('error_values'); + } + + if (isset($json['error']) && !isset($json['error']['warning'])) { + $json['error']['warning'] = $this->language->get('error_warning'); + } + + if (!$json) { + $this->load->model('catalog/filter'); + + if (!$this->request->post['filter_group_id']) { + $json['filter_group_id'] = $this->model_catalog_filter->addFilter($this->request->post); + } else { + $this->model_catalog_filter->editFilter($this->request->post['filter_group_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('catalog/filter'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'catalog/filter')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('catalog/filter'); + + foreach ($selected as $filter_id) { + $this->model_catalog_filter->deleteFilter($filter_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function autocomplete(): void { + $json = []; + + if (isset($this->request->get['filter_name'])) { + $this->load->model('catalog/filter'); + + $filter_data = [ + 'filter_name' => $this->request->get['filter_name'], + 'start' => 0, + 'limit' => 5 + ]; + + $filters = $this->model_catalog_filter->getFilters($filter_data); + + foreach ($filters as $filter) { + $json[] = [ + 'filter_id' => $filter['filter_id'], + 'name' => strip_tags(html_entity_decode($filter['group'] . ' > ' . $filter['name'], ENT_QUOTES, 'UTF-8')) + ]; + } + } + + $sort_order = []; + + foreach ($json as $key => $value) { + $sort_order[$key] = $value['name']; + } + + array_multisort($sort_order, SORT_ASC, $json); + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/catalog/information.php b/admininistrator/controller/catalog/information.php new file mode 100644 index 0000000..5ec99e0 --- /dev/null +++ b/admininistrator/controller/catalog/information.php @@ -0,0 +1,417 @@ +load->language('catalog/information'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('catalog/information', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('catalog/information.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('catalog/information.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('catalog/information', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('catalog/information'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'id.title'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('catalog/information.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['informations'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('catalog/information'); + + $information_total = $this->model_catalog_information->getTotalInformations(); + + $results = $this->model_catalog_information->getInformations($filter_data); + + foreach ($results as $result) { + $data['informations'][] = [ + 'information_id' => $result['information_id'], + 'title' => $result['title'], + 'status' => $result['status'], + 'sort_order' => $result['sort_order'], + 'edit' => $this->url->link('catalog/information.form', 'user_token=' . $this->session->data['user_token'] . '&information_id=' . $result['information_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_title'] = $this->url->link('catalog/information.list', 'user_token=' . $this->session->data['user_token'] . '&sort=id.title' . $url); + $data['sort_sort_order'] = $this->url->link('catalog/information.list', 'user_token=' . $this->session->data['user_token'] . '&sort=i.sort_order' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $information_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('catalog/information.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($information_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($information_total - $this->config->get('config_pagination_admin'))) ? $information_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $information_total, ceil($information_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('catalog/information_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('catalog/information'); + + $this->document->setTitle($this->language->get('heading_title')); + + $this->document->addScript('view/javascript/ckeditor/ckeditor.js'); + $this->document->addScript('view/javascript/ckeditor/adapters/jquery.js'); + + $data['text_form'] = !isset($this->request->get['information_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('catalog/information', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('catalog/information.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('catalog/information', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['information_id'])) { + $this->load->model('catalog/information'); + + $information_info = $this->model_catalog_information->getInformation($this->request->get['information_id']); + } + + if (isset($this->request->get['information_id'])) { + $data['information_id'] = (int)$this->request->get['information_id']; + } else { + $data['information_id'] = 0; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (isset($this->request->get['information_id'])) { + $data['information_description'] = $this->model_catalog_information->getDescriptions($this->request->get['information_id']); + } else { + $data['information_description'] = []; + } + + $data['stores'] = []; + + $data['stores'][] = [ + 'store_id' => 0, + 'name' => $this->language->get('text_default') + ]; + + $this->load->model('setting/store'); + + $stores = $this->model_setting_store->getStores(); + + foreach ($stores as $store) { + $data['stores'][] = [ + 'store_id' => $store['store_id'], + 'name' => $store['name'] + ]; + } + + if (isset($this->request->get['information_id'])) { + $data['information_store'] = $this->model_catalog_information->getStores($this->request->get['information_id']); + } else { + $data['information_store'] = [0]; + } + + if (!empty($information_info)) { + $data['bottom'] = $information_info['bottom']; + } else { + $data['bottom'] = 0; + } + + if (!empty($information_info)) { + $data['status'] = $information_info['status']; + } else { + $data['status'] = true; + } + + if (!empty($information_info)) { + $data['sort_order'] = $information_info['sort_order']; + } else { + $data['sort_order'] = ''; + } + + if (isset($this->request->get['information_id'])) { + $data['information_seo_url'] = $this->model_catalog_information->getSeoUrls($this->request->get['information_id']); + } else { + $data['information_seo_url'] = []; + } + + $this->load->model('design/layout'); + + $data['layouts'] = $this->model_design_layout->getLayouts(); + + if (isset($this->request->get['information_id'])) { + $data['information_layout'] = $this->model_catalog_information->getLayouts($this->request->get['information_id']); + } else { + $data['information_layout'] = []; + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('catalog/information_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('catalog/information'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'catalog/information')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + foreach ($this->request->post['information_description'] as $language_id => $value) { + if ((oc_strlen(trim($value['title'])) < 1) || (oc_strlen($value['title']) > 64)) { + $json['error']['title_' . $language_id] = $this->language->get('error_title'); + } + + if ((oc_strlen(trim($value['meta_title'])) < 1) || (oc_strlen($value['meta_title']) > 255)) { + $json['error']['meta_title_' . $language_id] = $this->language->get('error_meta_title'); + } + } + + if ($this->request->post['information_seo_url']) { + $this->load->model('design/seo_url'); + + foreach ($this->request->post['information_seo_url'] as $store_id => $language) { + foreach ($language as $language_id => $keyword) { + if ((oc_strlen(trim($keyword)) < 1) || (oc_strlen($keyword) > 64)) { + $json['error']['keyword_' . $store_id . '_' . $language_id] = $this->language->get('error_keyword'); + } + + if (preg_match('/[^a-zA-Z0-9\/_-]|[\p{Cyrillic}]+/u', $keyword)) { + $json['error']['keyword_' . $store_id . '_' . $language_id] = $this->language->get('error_keyword_character'); + } + + $seo_url_info = $this->model_design_seo_url->getSeoUrlByKeyword($keyword, $store_id); + + if ($seo_url_info && (!isset($this->request->post['information_id']) || $seo_url_info['key'] != 'information_id' || $seo_url_info['value'] != (int)$this->request->post['information_id'])) { + $json['error']['keyword_' . $store_id . '_' . $language_id] = $this->language->get('error_keyword_exists'); + } + } + } + } + + if (isset($json['error']) && !isset($json['error']['warning'])) { + $json['error']['warning'] = $this->language->get('error_warning'); + } + + if (!$json) { + $this->load->model('catalog/information'); + + if (!$this->request->post['information_id']) { + $json['information_id'] = $this->model_catalog_information->addInformation($this->request->post); + } else { + $this->model_catalog_information->editInformation($this->request->post['information_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('catalog/information'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'catalog/information')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('setting/store'); + + foreach ($selected as $information_id) { + if ($this->config->get('config_account_id') == $information_id) { + $json['error'] = $this->language->get('error_account'); + } + + if ($this->config->get('config_checkout_id') == $information_id) { + $json['error'] = $this->language->get('error_checkout'); + } + + if ($this->config->get('config_affiliate_id') == $information_id) { + $json['error'] = $this->language->get('error_affiliate'); + } + + if ($this->config->get('config_return_id') == $information_id) { + $json['error'] = $this->language->get('error_return'); + } + + $store_total = $this->model_setting_store->getTotalStoresByInformationId($information_id); + + if ($store_total) { + $json['error'] = sprintf($this->language->get('error_store'), $store_total); + } + } + + if (!$json) { + $this->load->model('catalog/information'); + + foreach ($selected as $information_id) { + $this->model_catalog_information->deleteInformation($information_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/catalog/manufacturer.php b/admininistrator/controller/catalog/manufacturer.php new file mode 100644 index 0000000..f0840c2 --- /dev/null +++ b/admininistrator/controller/catalog/manufacturer.php @@ -0,0 +1,432 @@ +load->language('catalog/manufacturer'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('catalog/manufacturer', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('catalog/manufacturer.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('catalog/manufacturer.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('catalog/manufacturer', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('catalog/manufacturer'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('catalog/manufacturer.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['manufacturers'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('catalog/manufacturer'); + + $manufacturer_total = $this->model_catalog_manufacturer->getTotalManufacturers(); + + $results = $this->model_catalog_manufacturer->getManufacturers($filter_data); + + foreach ($results as $result) { + $data['manufacturers'][] = [ + 'manufacturer_id' => $result['manufacturer_id'], + 'name' => $result['name'], + 'sort_order' => $result['sort_order'], + 'edit' => $this->url->link('catalog/manufacturer.form', 'user_token=' . $this->session->data['user_token'] . '&manufacturer_id=' . $result['manufacturer_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('catalog/manufacturer.list', 'user_token=' . $this->session->data['user_token'] . '&sort=name' . $url); + $data['sort_sort_order'] = $this->url->link('catalog/manufacturer.list', 'user_token=' . $this->session->data['user_token'] . '&sort=sort_order' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $manufacturer_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('catalog/manufacturer.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($manufacturer_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($manufacturer_total - $this->config->get('config_pagination_admin'))) ? $manufacturer_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $manufacturer_total, ceil($manufacturer_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('catalog/manufacturer_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('catalog/manufacturer'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['manufacturer_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('catalog/manufacturer', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('catalog/manufacturer.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('catalog/manufacturer', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['manufacturer_id'])) { + $this->load->model('catalog/manufacturer'); + + $manufacturer_info = $this->model_catalog_manufacturer->getManufacturer($this->request->get['manufacturer_id']); + } + + if (isset($this->request->get['manufacturer_id'])) { + $data['manufacturer_id'] = (int)$this->request->get['manufacturer_id']; + } else { + $data['manufacturer_id'] = 0; + } + + if (!empty($manufacturer_info)) { + $data['name'] = $manufacturer_info['name']; + } else { + $data['name'] = ''; + } + + $data['stores'] = []; + + $data['stores'][] = [ + 'store_id' => 0, + 'name' => $this->language->get('text_default') + ]; + + $this->load->model('setting/store'); + + $stores = $this->model_setting_store->getStores(); + + foreach ($stores as $store) { + $data['stores'][] = [ + 'store_id' => $store['store_id'], + 'name' => $store['name'] + ]; + } + + if (isset($this->request->get['manufacturer_id'])) { + $data['manufacturer_store'] = $this->model_catalog_manufacturer->getStores($this->request->get['manufacturer_id']); + } else { + $data['manufacturer_store'] = [0]; + } + + if (!empty($manufacturer_info)) { + $data['image'] = $manufacturer_info['image']; + } else { + $data['image'] = ''; + } + + $this->load->model('tool/image'); + + $data['placeholder'] = $this->model_tool_image->resize('no_image.png', 100, 100); + + if (is_file(DIR_IMAGE . html_entity_decode($data['image'], ENT_QUOTES, 'UTF-8'))) { + $data['thumb'] = $this->model_tool_image->resize(html_entity_decode($data['image'], ENT_QUOTES, 'UTF-8'), 100, 100); + } else { + $data['thumb'] = $data['placeholder']; + } + + if (!empty($manufacturer_info)) { + $data['sort_order'] = $manufacturer_info['sort_order']; + } else { + $data['sort_order'] = ''; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (isset($this->request->get['manufacturer_id'])) { + $data['manufacturer_seo_url'] = $this->model_catalog_manufacturer->getSeoUrls($this->request->get['manufacturer_id']); + } else { + $data['manufacturer_seo_url'] = []; + } + + $this->load->model('design/layout'); + + $data['layouts'] = $this->model_design_layout->getLayouts(); + + if (isset($this->request->get['manufacturer_id'])) { + $data['manufacturer_layout'] = $this->model_catalog_manufacturer->getLayouts($this->request->get['manufacturer_id']); + } else { + $data['manufacturer_layout'] = []; + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('catalog/manufacturer_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('catalog/manufacturer'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'catalog/manufacturer')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if ((oc_strlen($this->request->post['name']) < 1) || (oc_strlen($this->request->post['name']) > 64)) { + $json['error']['name'] = $this->language->get('error_name'); + } + + if ($this->request->post['manufacturer_seo_url']) { + $this->load->model('design/seo_url'); + + foreach ($this->request->post['manufacturer_seo_url'] as $store_id => $language) { + foreach ($language as $language_id => $keyword) { + if ((oc_strlen(trim($keyword)) < 1) || (oc_strlen($keyword) > 64)) { + $json['error']['keyword_' . $store_id . '_' . $language_id] = $this->language->get('error_keyword'); + } + + if (preg_match('/[^a-zA-Z0-9\/_-]|[\p{Cyrillic}]+/u', $keyword)) { + $json['error']['keyword_' . $store_id . '_' . $language_id] = $this->language->get('error_keyword_character'); + } + + $seo_url_info = $this->model_design_seo_url->getSeoUrlByKeyword($keyword, $store_id); + + if ($seo_url_info && ($seo_url_info['key'] != 'manufacturer_id' || !isset($this->request->post['manufacturer_id']) || $seo_url_info['value'] != (int)$this->request->post['manufacturer_id'])) { + $json['error']['keyword_' . $store_id . '_' . $language_id] = $this->language->get('error_keyword_exists'); + } + } + } + } + + if (isset($json['error']) && !isset($json['error']['warning'])) { + $json['error']['warning'] = $this->language->get('error_warning'); + } + + if (!$json) { + $this->load->model('catalog/manufacturer'); + + if (!$this->request->post['manufacturer_id']) { + $json['manufacturer_id'] = $this->model_catalog_manufacturer->addManufacturer($this->request->post); + } else { + $this->model_catalog_manufacturer->editManufacturer($this->request->post['manufacturer_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('catalog/manufacturer'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'catalog/manufacturer')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('catalog/product'); + + foreach ($selected as $manufacturer_id) { + $product_total = $this->model_catalog_product->getTotalProductsByManufacturerId($manufacturer_id); + + if ($product_total) { + $json['error'] = sprintf($this->language->get('error_product'), $product_total); + } + } + + if (!$json) { + $this->load->model('catalog/manufacturer'); + + foreach ($selected as $manufacturer_id) { + $this->model_catalog_manufacturer->deleteManufacturer($manufacturer_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function autocomplete(): void { + $json = []; + + if (isset($this->request->get['filter_name'])) { + $this->load->model('catalog/manufacturer'); + + $filter_data = [ + 'filter_name' => $this->request->get['filter_name'], + 'start' => 0, + 'limit' => 5 + ]; + + $results = $this->model_catalog_manufacturer->getManufacturers($filter_data); + + foreach ($results as $result) { + $json[] = [ + 'manufacturer_id' => $result['manufacturer_id'], + 'name' => strip_tags(html_entity_decode($result['name'], ENT_QUOTES, 'UTF-8')) + ]; + } + } + + $sort_order = []; + + foreach ($json as $key => $value) { + $sort_order[$key] = $value['name']; + } + + array_multisort($sort_order, SORT_ASC, $json); + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/catalog/option.php b/admininistrator/controller/catalog/option.php new file mode 100644 index 0000000..2006ae2 --- /dev/null +++ b/admininistrator/controller/catalog/option.php @@ -0,0 +1,481 @@ +load->language('catalog/option'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('catalog/option', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('catalog/option.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('catalog/option.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('catalog/option', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('catalog/option'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'od.name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('catalog/option.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['options'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('catalog/option'); + + $option_total = $this->model_catalog_option->getTotalOptions(); + + $results = $this->model_catalog_option->getOptions($filter_data); + + foreach ($results as $result) { + $data['options'][] = [ + 'option_id' => $result['option_id'], + 'name' => $result['name'], + 'sort_order' => $result['sort_order'], + 'edit' => $this->url->link('catalog/option.form', 'user_token=' . $this->session->data['user_token'] . '&option_id=' . $result['option_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('catalog/option.list', 'user_token=' . $this->session->data['user_token'] . '&sort=od.name' . $url); + $data['sort_sort_order'] = $this->url->link('catalog/option.list', 'user_token=' . $this->session->data['user_token'] . '&sort=o.sort_order' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $option_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('catalog/option.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($option_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($option_total - $this->config->get('config_pagination_admin'))) ? $option_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $option_total, ceil($option_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('catalog/option_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('catalog/option'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['option_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('catalog/option', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('catalog/option.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('catalog/option', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['option_id'])) { + $this->load->model('catalog/option'); + + $option_info = $this->model_catalog_option->getOption($this->request->get['option_id']); + } + + if (isset($this->request->get['option_id'])) { + $data['option_id'] = (int)$this->request->get['option_id']; + } else { + $data['option_id'] = 0; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (isset($this->request->get['option_id'])) { + $data['option_description'] = $this->model_catalog_option->getDescriptions($this->request->get['option_id']); + } else { + $data['option_description'] = []; + } + + if (!empty($option_info)) { + $data['type'] = $option_info['type']; + } else { + $data['type'] = ''; + } + + if (!empty($option_info)) { + $data['sort_order'] = $option_info['sort_order']; + } else { + $data['sort_order'] = ''; + } + + if (isset($this->request->get['option_id'])) { + $option_values = $this->model_catalog_option->getValueDescriptions($this->request->get['option_id']); + } else { + $option_values = []; + } + + $this->load->model('tool/image'); + + $data['option_values'] = []; + + foreach ($option_values as $option_value) { + if (is_file(DIR_IMAGE . html_entity_decode($option_value['image'], ENT_QUOTES, 'UTF-8'))) { + $image = $option_value['image']; + $thumb = $option_value['image']; + } else { + $image = ''; + $thumb = 'no_image.png'; + } + + $data['option_values'][] = [ + 'option_value_id' => $option_value['option_value_id'], + 'option_value_description' => $option_value['option_value_description'], + 'image' => $image, + 'thumb' => $this->model_tool_image->resize(html_entity_decode($thumb, ENT_QUOTES, 'UTF-8'), 100, 100), + 'sort_order' => $option_value['sort_order'] + ]; + } + + $data['placeholder'] = $this->model_tool_image->resize('no_image.png', 100, 100); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('catalog/option_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('catalog/option'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'catalog/option')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + foreach ($this->request->post['option_description'] as $language_id => $value) { + if ((oc_strlen(trim($value['name'])) < 1) || (oc_strlen($value['name']) > 128)) { + $json['error']['name_' . $language_id] = $this->language->get('error_name'); + } + } + + if (($this->request->post['type'] == 'select' || $this->request->post['type'] == 'radio' || $this->request->post['type'] == 'checkbox') && !isset($this->request->post['option_value'])) { + $json['error']['warning'] = $this->language->get('error_type'); + } + + if (isset($this->request->post['option_value'])) { + if (isset($this->request->post['option_id'])) { + $this->load->model('catalog/product'); + + $option_value_data = []; + + foreach ($this->request->post['option_value'] as $option_value) { + if ($option_value['option_value_id']) { + $option_value_data[] = $option_value['option_value_id']; + } + } + + $product_option_values = $this->model_catalog_product->getOptionValuesByOptionId($this->request->post['option_id']); + + foreach ($product_option_values as $product_option_value) { + if (!in_array($product_option_value['option_value_id'], $option_value_data)) { + $json['error']['warning'] = sprintf($this->language->get('error_value'), $this->model_catalog_product->getTotalProductsByOptionValueId($product_option_value['option_value_id'])); + } + } + } + } + + if (isset($this->request->post['option_value'])) { + foreach ($this->request->post['option_value'] as $option_value_id => $option_value) { + foreach ($option_value['option_value_description'] as $language_id => $option_value_description) { + if ((oc_strlen(trim($option_value_description['name'])) < 1) || (oc_strlen($option_value_description['name']) > 128)) { + $json['error']['option_value_' . $option_value_id . '_' . $language_id] = $this->language->get('error_option_value'); + } + } + } + } + + if (isset($json['error']) && !isset($json['error']['warning'])) { + $json['error']['warning'] = $this->language->get('error_warning'); + } + + if (!$json) { + $this->load->model('catalog/option'); + + if (!$this->request->post['option_id']) { + $json['option_id'] = $this->model_catalog_option->addOption($this->request->post); + } else { + $this->model_catalog_option->editOption($this->request->post['option_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('catalog/option'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'catalog/option')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('catalog/product'); + + foreach ($selected as $option_id) { + $product_total = $this->model_catalog_product->getTotalProductsByOptionId($option_id); + + if ($product_total) { + $json['error'] = sprintf($this->language->get('error_product'), $product_total); + } + } + + if (!$json) { + $this->load->model('catalog/option'); + + foreach ($selected as $option_id) { + $this->model_catalog_option->deleteOption($option_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function autocomplete(): void { + $json = []; + + if (isset($this->request->get['filter_name'])) { + $this->load->language('catalog/option'); + + $this->load->model('catalog/option'); + + $this->load->model('tool/image'); + + $filter_data = [ + 'filter_name' => $this->request->get['filter_name'], + 'start' => 0, + 'limit' => 5 + ]; + + $options = $this->model_catalog_option->getOptions($filter_data); + + foreach ($options as $option) { + $option_value_data = []; + + if ($option['type'] == 'select' || $option['type'] == 'radio' || $option['type'] == 'checkbox' || $option['type'] == 'image') { + $option_values = $this->model_catalog_option->getValues($option['option_id']); + + foreach ($option_values as $option_value) { + if (is_file(DIR_IMAGE . html_entity_decode($option_value['image'], ENT_QUOTES, 'UTF-8'))) { + $image = $this->model_tool_image->resize(html_entity_decode($option_value['image'], ENT_QUOTES, 'UTF-8'), 50, 50); + } else { + $image = $this->model_tool_image->resize('no_image.png', 50, 50); + } + + $option_value_data[] = [ + 'option_value_id' => $option_value['option_value_id'], + 'name' => strip_tags(html_entity_decode($option_value['name'], ENT_QUOTES, 'UTF-8')), + 'image' => $image + ]; + } + + $sort_order = []; + + foreach ($option_value_data as $key => $value) { + $sort_order[$key] = $value['name']; + } + + array_multisort($sort_order, SORT_ASC, $option_value_data); + } + + $type = ''; + + if ($option['type'] == 'select' || $option['type'] == 'radio' || $option['type'] == 'checkbox') { + $type = $this->language->get('text_choose'); + } + + if ($option['type'] == 'text' || $option['type'] == 'textarea') { + $type = $this->language->get('text_input'); + } + + if ($option['type'] == 'file') { + $type = $this->language->get('text_file'); + } + + if ($option['type'] == 'date' || $option['type'] == 'datetime' || $option['type'] == 'time') { + $type = $this->language->get('text_date'); + } + + $json[] = [ + 'option_id' => $option['option_id'], + 'name' => strip_tags(html_entity_decode($option['name'], ENT_QUOTES, 'UTF-8')), + 'category' => $type, + 'type' => $option['type'], + 'option_value' => $option_value_data + ]; + } + } + + $sort_order = []; + + foreach ($json as $key => $value) { + $sort_order[$key] = $value['name']; + } + + array_multisort($sort_order, SORT_ASC, $json); + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/catalog/product.php b/admininistrator/controller/catalog/product.php new file mode 100644 index 0000000..0a28a5d --- /dev/null +++ b/admininistrator/controller/catalog/product.php @@ -0,0 +1,1378 @@ +load->language('catalog/product'); + + $this->document->setTitle($this->language->get('heading_title')); + + if (isset($this->request->get['filter_name'])) { + $filter_name = $this->request->get['filter_name']; + } else { + $filter_name = ''; + } + + if (isset($this->request->get['filter_model'])) { + $filter_model = $this->request->get['filter_model']; + } else { + $filter_model = ''; + } + + if (isset($this->request->get['filter_price'])) { + $filter_price = $this->request->get['filter_price']; + } else { + $filter_price = ''; + } + + if (isset($this->request->get['filter_quantity'])) { + $filter_quantity = $this->request->get['filter_quantity']; + } else { + $filter_quantity = ''; + } + + if (isset($this->request->get['filter_status'])) { + $filter_status = $this->request->get['filter_status']; + } else { + $filter_status = ''; + } + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_model'])) { + $url .= '&filter_model=' . urlencode(html_entity_decode($this->request->get['filter_model'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_price'])) { + $url .= '&filter_price=' . $this->request->get['filter_price']; + } + + if (isset($this->request->get['filter_quantity'])) { + $url .= '&filter_quantity=' . $this->request->get['filter_quantity']; + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('catalog/product', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('catalog/product.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['copy'] = $this->url->link('catalog/product.copy', 'user_token=' . $this->session->data['user_token']); + $data['delete'] = $this->url->link('catalog/product.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['filter_name'] = $filter_name; + $data['filter_model'] = $filter_model; + $data['filter_price'] = $filter_price; + $data['filter_quantity'] = $filter_quantity; + $data['filter_status'] = $filter_status; + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('catalog/product', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('catalog/product'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['filter_name'])) { + $filter_name = $this->request->get['filter_name']; + } else { + $filter_name = ''; + } + + if (isset($this->request->get['filter_model'])) { + $filter_model = $this->request->get['filter_model']; + } else { + $filter_model = ''; + } + + if (isset($this->request->get['filter_price'])) { + $filter_price = $this->request->get['filter_price']; + } else { + $filter_price = ''; + } + + if (isset($this->request->get['filter_quantity'])) { + $filter_quantity = $this->request->get['filter_quantity']; + } else { + $filter_quantity = ''; + } + + if (isset($this->request->get['filter_status'])) { + $filter_status = $this->request->get['filter_status']; + } else { + $filter_status = ''; + } + + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'pd.name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_model'])) { + $url .= '&filter_model=' . urlencode(html_entity_decode($this->request->get['filter_model'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_price'])) { + $url .= '&filter_price=' . $this->request->get['filter_price']; + } + + if (isset($this->request->get['filter_quantity'])) { + $url .= '&filter_quantity=' . $this->request->get['filter_quantity']; + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('catalog/product.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['products'] = []; + + $filter_data = [ + 'filter_name' => $filter_name, + 'filter_model' => $filter_model, + 'filter_price' => $filter_price, + 'filter_quantity' => $filter_quantity, + 'filter_status' => $filter_status, + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('catalog/product'); + + $this->load->model('tool/image'); + + $product_total = $this->model_catalog_product->getTotalProducts($filter_data); + + $results = $this->model_catalog_product->getProducts($filter_data); + + foreach ($results as $result) { + if (is_file(DIR_IMAGE . html_entity_decode($result['image'], ENT_QUOTES, 'UTF-8'))) { + $image = $this->model_tool_image->resize(html_entity_decode($result['image'], ENT_QUOTES, 'UTF-8'), 40, 40); + } else { + $image = $this->model_tool_image->resize('no_image.png', 40, 40); + } + + $special = false; + + $product_specials = $this->model_catalog_product->getSpecials($result['product_id']); + + foreach ($product_specials as $product_special) { + if (($product_special['date_start'] == '0000-00-00' || strtotime($product_special['date_start']) < time()) && ($product_special['date_end'] == '0000-00-00' || strtotime($product_special['date_end']) > time())) { + $special = $this->currency->format($product_special['price'], $this->config->get('config_currency')); + + break; + } + } + + $data['products'][] = [ + 'product_id' => $result['product_id'], + 'image' => $image, + 'name' => $result['name'], + 'model' => $result['model'], + 'price' => $this->currency->format($result['price'], $this->config->get('config_currency')), + 'special' => $special, + 'quantity' => $result['quantity'], + 'status' => $result['status'], + 'edit' => $this->url->link('catalog/product.form', 'user_token=' . $this->session->data['user_token'] . '&product_id=' . $result['product_id'] . ($result['master_id'] ? '&master_id=' . $result['master_id'] : '') . $url), + 'variant' => (!$result['master_id'] ? $this->url->link('catalog/product.form', 'user_token=' . $this->session->data['user_token'] . '&master_id=' . $result['product_id'] . $url) : '') + ]; + } + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_model'])) { + $url .= '&filter_model=' . urlencode(html_entity_decode($this->request->get['filter_model'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_price'])) { + $url .= '&filter_price=' . $this->request->get['filter_price']; + } + + if (isset($this->request->get['filter_quantity'])) { + $url .= '&filter_quantity=' . $this->request->get['filter_quantity']; + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('catalog/product.list', 'user_token=' . $this->session->data['user_token'] . '&sort=pd.name' . $url); + $data['sort_model'] = $this->url->link('catalog/product.list', 'user_token=' . $this->session->data['user_token'] . '&sort=p.model' . $url); + $data['sort_price'] = $this->url->link('catalog/product.list', 'user_token=' . $this->session->data['user_token'] . '&sort=p.price' . $url); + $data['sort_quantity'] = $this->url->link('catalog/product.list', 'user_token=' . $this->session->data['user_token'] . '&sort=p.quantity' . $url); + $data['sort_order'] = $this->url->link('catalog/product.list', 'user_token=' . $this->session->data['user_token'] . '&sort=p.sort_order' . $url); + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_model'])) { + $url .= '&filter_model=' . urlencode(html_entity_decode($this->request->get['filter_model'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_price'])) { + $url .= '&filter_price=' . $this->request->get['filter_price']; + } + + if (isset($this->request->get['filter_quantity'])) { + $url .= '&filter_quantity=' . $this->request->get['filter_quantity']; + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $product_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('catalog/product.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($product_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($product_total - $this->config->get('config_pagination_admin'))) ? $product_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $product_total, ceil($product_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('catalog/product_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('catalog/product'); + + $this->document->setTitle($this->language->get('heading_title')); + + $this->document->addScript('view/javascript/ckeditor/ckeditor.js'); + $this->document->addScript('view/javascript/ckeditor/adapters/jquery.js'); + + $data['text_form'] = !isset($this->request->get['product_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $data['error_upload_size'] = sprintf($this->language->get('error_upload_size'), $this->config->get('config_file_max_size')); + + $data['upload'] = $this->url->link('tool/upload', 'user_token=' . $this->session->data['user_token']); + $data['config_file_max_size'] = ((int)$this->config->get('config_file_max_size') * 1024 * 1024); + + if (isset($this->request->get['master_id'])) { + $this->load->model('catalog/product'); + + $url = $this->url->link('catalog/product.form', 'user_token=' . $this->session->data['user_token'] . '&product_id=' . $this->request->get['master_id']); + + $data['text_variant'] = sprintf($this->language->get('text_variant'), $url, $url); + } else { + $data['text_variant'] = ''; + } + + $url = ''; + + if (isset($this->request->get['master_id'])) { + $url .= '&master_id=' . $this->request->get['master_id']; + } + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_model'])) { + $url .= '&filter_model=' . urlencode(html_entity_decode($this->request->get['filter_model'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_price'])) { + $url .= '&filter_price=' . $this->request->get['filter_price']; + } + + if (isset($this->request->get['filter_quantity'])) { + $url .= '&filter_quantity=' . $this->request->get['filter_quantity']; + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('catalog/product', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_model'])) { + $url .= '&filter_model=' . urlencode(html_entity_decode($this->request->get['filter_model'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_price'])) { + $url .= '&filter_price=' . $this->request->get['filter_price']; + } + + if (isset($this->request->get['filter_quantity'])) { + $url .= '&filter_quantity=' . $this->request->get['filter_quantity']; + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['save'] = $this->url->link('catalog/product.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('catalog/product', 'user_token=' . $this->session->data['user_token'] . $url); + $data['upload'] = $this->url->link('tool/upload.upload', 'user_token=' . $this->session->data['user_token']); + + if (isset($this->request->get['product_id'])) { + $data['product_id'] = (int)$this->request->get['product_id']; + } else { + $data['product_id'] = 0; + } + + // If the product_id is the master_id, we need to get the variant info + if (isset($this->request->get['product_id'])) { + $product_id = (int)$this->request->get['product_id']; + } elseif (isset($this->request->get['master_id'])) { + $product_id = (int)$this->request->get['master_id']; + } else { + $product_id = 0; + } + + if ($product_id) { + $this->load->model('catalog/product'); + + $product_info = $this->model_catalog_product->getProduct($product_id); + } + + if (isset($this->request->get['master_id'])) { + $data['master_id'] = (int)$this->request->get['master_id']; + } elseif (!empty($product_info)) { + $data['master_id'] = $product_info['master_id']; + } else { + $data['master_id'] = 0; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (!empty($product_info)) { + $data['product_description'] = $this->model_catalog_product->getDescriptions($product_id); + } else { + $data['product_description'] = []; + } + + if (!empty($product_info)) { + $data['model'] = $product_info['model']; + } else { + $data['model'] = ''; + } + + if (!empty($product_info)) { + $data['sku'] = $product_info['sku']; + } else { + $data['sku'] = ''; + } + + if (!empty($product_info)) { + $data['upc'] = $product_info['upc']; + } else { + $data['upc'] = ''; + } + + if (!empty($product_info)) { + $data['ean'] = $product_info['ean']; + } else { + $data['ean'] = ''; + } + + if (!empty($product_info)) { + $data['jan'] = $product_info['jan']; + } else { + $data['jan'] = ''; + } + + if (!empty($product_info)) { + $data['isbn'] = $product_info['isbn']; + } else { + $data['isbn'] = ''; + } + + if (!empty($product_info)) { + $data['mpn'] = $product_info['mpn']; + } else { + $data['mpn'] = ''; + } + + if (!empty($product_info)) { + $data['location'] = $product_info['location']; + } else { + $data['location'] = ''; + } + + if (!empty($product_info)) { + $data['price'] = $product_info['price']; + } else { + $data['price'] = ''; + } + + $this->load->model('localisation/tax_class'); + + $data['tax_classes'] = $this->model_localisation_tax_class->getTaxClasses(); + + if (!empty($product_info)) { + $data['tax_class_id'] = $product_info['tax_class_id']; + } else { + $data['tax_class_id'] = 0; + } + + if (!empty($product_info)) { + $data['quantity'] = $product_info['quantity']; + } else { + $data['quantity'] = 1; + } + + if (!empty($product_info)) { + $data['minimum'] = $product_info['minimum']; + } else { + $data['minimum'] = 1; + } + + if (!empty($product_info)) { + $data['subtract'] = $product_info['subtract']; + } else { + $data['subtract'] = 1; + } + + $this->load->model('localisation/stock_status'); + + $data['stock_statuses'] = $this->model_localisation_stock_status->getStockStatuses(); + + if (!empty($product_info)) { + $data['stock_status_id'] = $product_info['stock_status_id']; + } else { + $data['stock_status_id'] = 0; + } + + if (!empty($product_info)) { + $data['date_available'] = ($product_info['date_available'] != '0000-00-00') ? $product_info['date_available'] : ''; + } else { + $data['date_available'] = date('Y-m-d'); + } + + if (!empty($product_info)) { + $data['shipping'] = $product_info['shipping']; + } else { + $data['shipping'] = 1; + } + + if (!empty($product_info)) { + $data['length'] = $product_info['length']; + } else { + $data['length'] = ''; + } + + if (!empty($product_info)) { + $data['width'] = $product_info['width']; + } else { + $data['width'] = ''; + } + + if (!empty($product_info)) { + $data['height'] = $product_info['height']; + } else { + $data['height'] = ''; + } + + $this->load->model('localisation/length_class'); + + $data['length_classes'] = $this->model_localisation_length_class->getLengthClasses(); + + if (!empty($product_info)) { + $data['length_class_id'] = $product_info['length_class_id']; + } else { + $data['length_class_id'] = $this->config->get('config_length_class_id'); + } + + if (!empty($product_info)) { + $data['weight'] = $product_info['weight']; + } else { + $data['weight'] = ''; + } + + $this->load->model('localisation/weight_class'); + + $data['weight_classes'] = $this->model_localisation_weight_class->getWeightClasses(); + + if (!empty($product_info)) { + $data['weight_class_id'] = $product_info['weight_class_id']; + } else { + $data['weight_class_id'] = $this->config->get('config_weight_class_id'); + } + + if (!empty($product_info)) { + $data['status'] = $product_info['status']; + } else { + $data['status'] = true; + } + + if (!empty($product_info)) { + $data['sort_order'] = $product_info['sort_order']; + } else { + $data['sort_order'] = 1; + } + + $this->load->model('catalog/manufacturer'); + + if (!empty($product_info)) { + $data['manufacturer_id'] = $product_info['manufacturer_id']; + } else { + $data['manufacturer_id'] = 0; + } + + if (!empty($product_info)) { + $manufacturer_info = $this->model_catalog_manufacturer->getManufacturer($product_info['manufacturer_id']); + + if ($manufacturer_info) { + $data['manufacturer'] = $manufacturer_info['name']; + } else { + $data['manufacturer'] = ''; + } + } else { + $data['manufacturer'] = ''; + } + + // Categories + $this->load->model('catalog/category'); + + if ($product_id) { + $categories = $this->model_catalog_product->getCategories($product_id); + } else { + $categories = []; + } + + $data['product_categories'] = []; + + foreach ($categories as $category_id) { + $category_info = $this->model_catalog_category->getCategory($category_id); + + if ($category_info) { + $data['product_categories'][] = [ + 'category_id' => $category_info['category_id'], + 'name' => ($category_info['path']) ? $category_info['path'] . ' > ' . $category_info['name'] : $category_info['name'] + ]; + } + } + + // Filters + $this->load->model('catalog/filter'); + + if (!empty($product_info)) { + $filters = $this->model_catalog_product->getFilters($product_id); + } else { + $filters = []; + } + + $data['product_filters'] = []; + + foreach ($filters as $filter_id) { + $filter_info = $this->model_catalog_filter->getFilter($filter_id); + + if ($filter_info) { + $data['product_filters'][] = [ + 'filter_id' => $filter_info['filter_id'], + 'name' => $filter_info['group'] . ' > ' . $filter_info['name'] + ]; + } + } + + // Stores + $data['stores'] = []; + + $data['stores'][] = [ + 'store_id' => 0, + 'name' => $this->language->get('text_default') + ]; + + $this->load->model('setting/store'); + + $stores = $this->model_setting_store->getStores(); + + foreach ($stores as $store) { + $data['stores'][] = [ + 'store_id' => $store['store_id'], + 'name' => $store['name'] + ]; + } + + if ($product_id) { + $data['product_store'] = $this->model_catalog_product->getStores($product_id); + } else { + $data['product_store'] = [0]; + } + + // Downloads + $this->load->model('catalog/download'); + + if ($product_id) { + $product_downloads = $this->model_catalog_product->getDownloads($product_id); + } else { + $product_downloads = []; + } + + $data['product_downloads'] = []; + + foreach ($product_downloads as $download_id) { + $download_info = $this->model_catalog_download->getDownload($download_id); + + if ($download_info) { + $data['product_downloads'][] = [ + 'download_id' => $download_info['download_id'], + 'name' => $download_info['name'] + ]; + } + } + + // Related + if ($product_id) { + $product_relateds = $this->model_catalog_product->getRelated($product_id); + } else { + $product_relateds = []; + } + + $data['product_relateds'] = []; + + foreach ($product_relateds as $related_id) { + $related_info = $this->model_catalog_product->getProduct($related_id); + + if ($related_info) { + $data['product_relateds'][] = [ + 'product_id' => $related_info['product_id'], + 'name' => $related_info['name'] + ]; + } + } + + // Attributes + $this->load->model('catalog/attribute'); + + if ($product_id) { + $product_attributes = $this->model_catalog_product->getAttributes($product_id); + } else { + $product_attributes = []; + } + + $data['product_attributes'] = []; + + foreach ($product_attributes as $product_attribute) { + $attribute_info = $this->model_catalog_attribute->getAttribute($product_attribute['attribute_id']); + + if ($attribute_info) { + $data['product_attributes'][] = [ + 'attribute_id' => $product_attribute['attribute_id'], + 'name' => $attribute_info['name'], + 'product_attribute_description' => $product_attribute['product_attribute_description'] + ]; + } + } + + $this->load->model('customer/customer_group'); + + $data['customer_groups'] = $this->model_customer_customer_group->getCustomerGroups(); + + // Options + $this->load->model('catalog/option'); + + if ($product_id) { + $product_options = $this->model_catalog_product->getOptions($product_id); + } else { + $product_options = []; + } + + $data['product_options'] = []; + + foreach ($product_options as $product_option) { + $product_option_value_data = []; + + if (isset($product_option['product_option_value'])) { + foreach ($product_option['product_option_value'] as $product_option_value) { + $option_value_info = $this->model_catalog_option->getValue($product_option_value['option_value_id']); + + if ($option_value_info) { + $product_option_value_data[] = [ + 'product_option_value_id' => $product_option_value['product_option_value_id'], + 'option_value_id' => $product_option_value['option_value_id'], + 'name' => $option_value_info['name'], + 'quantity' => $product_option_value['quantity'], + 'subtract' => $product_option_value['subtract'], + 'price' => $product_option_value['price'], + 'price_prefix' => $product_option_value['price_prefix'], + 'points' => round($product_option_value['points']), + 'points_prefix' => $product_option_value['points_prefix'], + 'weight' => round($product_option_value['weight']), + 'weight_prefix' => $product_option_value['weight_prefix'] + ]; + } + } + } + + $data['product_options'][] = [ + 'product_option_id' => $product_option['product_option_id'], + 'product_option_value' => $product_option_value_data, + 'option_id' => $product_option['option_id'], + 'name' => $product_option['name'], + 'type' => $product_option['type'], + 'value' => isset($product_option['value']) ? $product_option['value'] : '', + 'required' => $product_option['required'] + ]; + } + + $data['option_values'] = []; + + foreach ($data['product_options'] as $product_option) { + if ($product_option['type'] == 'select' || $product_option['type'] == 'radio' || $product_option['type'] == 'checkbox' || $product_option['type'] == 'image') { + if (!isset($data['option_values'][$product_option['option_id']])) { + $data['option_values'][$product_option['option_id']] = $this->model_catalog_option->getValues($product_option['option_id']); + } + } + } + + // Variants + if (!empty($product_info)) { + $data['variant'] = json_decode($product_info['variant'], true); + } else { + $data['variant'] = []; + } + + // Overrides + if (!empty($product_info)) { + $data['override'] = json_decode($product_info['override'], true); + } else { + $data['override'] = []; + } + + $data['options'] = []; + + if (isset($this->request->get['master_id'])) { + $product_options = $this->model_catalog_product->getOptions($this->request->get['master_id']); + + foreach ($product_options as $product_option) { + $product_option_value_data = []; + + foreach ($product_option['product_option_value'] as $product_option_value) { + $option_value_info = $this->model_catalog_option->getValue($product_option_value['option_value_id']); + + if ($option_value_info) { + $product_option_value_data[] = [ + 'product_option_value_id' => $product_option_value['product_option_value_id'], + 'option_value_id' => $product_option_value['option_value_id'], + 'name' => $option_value_info['name'], + 'price' => (float)$product_option_value['price'] ? $product_option_value['price'] : false, + 'price_prefix' => $product_option_value['price_prefix'] + ]; + } + } + + $option_info = $this->model_catalog_option->getOption($product_option['option_id']); + + $data['options'][] = [ + 'product_option_id' => $product_option['product_option_id'], + 'product_option_value' => $product_option_value_data, + 'option_id' => $product_option['option_id'], + 'name' => $option_info['name'], + 'type' => $option_info['type'], + 'value' => isset($data['variant'][$product_option['product_option_id']]) ? $data['variant'][$product_option['product_option_id']] : $product_option['value'], + 'required' => $product_option['required'] + ]; + } + } + + // Subscriptions + $this->load->model('catalog/subscription_plan'); + + $data['subscription_plans'] = $this->model_catalog_subscription_plan->getSubscriptionPlans(); + + if ($product_id) { + $data['product_subscriptions'] = $this->model_catalog_product->getSubscriptions($product_id); + } else { + $data['product_subscriptions'] = []; + } + + // Discount + if ($product_id) { + $product_discounts = $this->model_catalog_product->getDiscounts($product_id); + } else { + $product_discounts = []; + } + + $data['product_discounts'] = []; + + foreach ($product_discounts as $product_discount) { + $data['product_discounts'][] = [ + 'customer_group_id' => $product_discount['customer_group_id'], + 'quantity' => $product_discount['quantity'], + 'priority' => $product_discount['priority'], + 'price' => $product_discount['price'], + 'date_start' => ($product_discount['date_start'] != '0000-00-00') ? $product_discount['date_start'] : '', + 'date_end' => ($product_discount['date_end'] != '0000-00-00') ? $product_discount['date_end'] : '' + ]; + } + + // Special + if ($product_id) { + $product_specials = $this->model_catalog_product->getSpecials($product_id); + } else { + $product_specials = []; + } + + $data['product_specials'] = []; + + foreach ($product_specials as $product_special) { + $data['product_specials'][] = [ + 'customer_group_id' => $product_special['customer_group_id'], + 'priority' => $product_special['priority'], + 'price' => $product_special['price'], + 'date_start' => ($product_special['date_start'] != '0000-00-00') ? $product_special['date_start'] : '', + 'date_end' => ($product_special['date_end'] != '0000-00-00') ? $product_special['date_end'] : '' + ]; + } + + // Image + if (!empty($product_info)) { + $data['image'] = $product_info['image']; + } else { + $data['image'] = ''; + } + + $this->load->model('tool/image'); + + $data['placeholder'] = $this->model_tool_image->resize('no_image.png', 100, 100); + + if (is_file(DIR_IMAGE . html_entity_decode($data['image'], ENT_QUOTES, 'UTF-8'))) { + $data['thumb'] = $this->model_tool_image->resize(html_entity_decode($data['image'], ENT_QUOTES, 'UTF-8'), 100, 100); + } else { + $data['thumb'] = $data['placeholder']; + } + + // Images + if ($product_id) { + $product_images = $this->model_catalog_product->getImages($product_id); + } else { + $product_images = []; + } + + $data['product_images'] = []; + + foreach ($product_images as $product_image) { + if (is_file(DIR_IMAGE . html_entity_decode($product_image['image'], ENT_QUOTES, 'UTF-8'))) { + $image = $product_image['image']; + $thumb = $product_image['image']; + } else { + $image = ''; + $thumb = 'no_image.png'; + } + + $data['product_images'][] = [ + 'image' => $image, + 'thumb' => $this->model_tool_image->resize(html_entity_decode($thumb, ENT_QUOTES, 'UTF-8'), 100, 100), + 'sort_order' => $product_image['sort_order'] + ]; + } + + // Points + if (!empty($product_info)) { + $data['points'] = $product_info['points']; + } else { + $data['points'] = ''; + } + + // Rewards + if ($product_id) { + $data['product_reward'] = $this->model_catalog_product->getRewards($product_id); + } else { + $data['product_reward'] = []; + } + + // SEO + if ($product_id) { + $data['product_seo_url'] = $this->model_catalog_product->getSeoUrls($product_id); + } else { + $data['product_seo_url'] = []; + } + + // Layouts + $this->load->model('design/layout'); + + $data['layouts'] = $this->model_design_layout->getLayouts(); + + if ($product_id) { + $data['product_layout'] = $this->model_catalog_product->getLayouts($product_id); + } else { + $data['product_layout'] = []; + } + + $data['report'] = $this->getReport(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('catalog/product_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('catalog/product'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'catalog/product')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + foreach ($this->request->post['product_description'] as $language_id => $value) { + if ((oc_strlen(trim($value['name'])) < 1) || (oc_strlen($value['name']) > 255)) { + $json['error']['name_' . $language_id] = $this->language->get('error_name'); + } + + if ((oc_strlen(trim($value['meta_title'])) < 1) || (oc_strlen($value['meta_title']) > 255)) { + $json['error']['meta_title_' . $language_id] = $this->language->get('error_meta_title'); + } + } + + if ((oc_strlen($this->request->post['model']) < 1) || (oc_strlen($this->request->post['model']) > 64)) { + $json['error']['model'] = $this->language->get('error_model'); + } + + $this->load->model('catalog/product'); + + if ($this->request->post['master_id']) { + $product_options = $this->model_catalog_product->getOptions($this->request->post['master_id']); + + foreach ($product_options as $product_option) { + if (isset($this->request->post['override']['variant'][$product_option['product_option_id']]) && $product_option['required'] && empty($this->request->post['variant'][$product_option['product_option_id']])) { + $json['error']['option_' . $product_option['product_option_id']] = sprintf($this->language->get('error_required'), $product_option['name']); + } + } + } + + if ($this->request->post['product_seo_url']) { + $this->load->model('design/seo_url'); + + foreach ($this->request->post['product_seo_url'] as $store_id => $language) { + foreach ($language as $language_id => $keyword) { + if ((oc_strlen(trim($keyword)) < 1) || (oc_strlen($keyword) > 64)) { + $json['error']['keyword_' . $store_id . '_' . $language_id] = $this->language->get('error_keyword'); + } + + if (preg_match('/[^a-zA-Z0-9\/_-]|[\p{Cyrillic}]+/u', $keyword)) { + $json['error']['keyword_' . $store_id . '_' . $language_id] = $this->language->get('error_keyword_character'); + } + + $seo_url_info = $this->model_design_seo_url->getSeoUrlByKeyword($keyword, $store_id); + + if ($seo_url_info && ($seo_url_info['key'] != 'product_id' || !isset($this->request->post['product_id']) || $seo_url_info['value'] != (int)$this->request->post['product_id'])) { + $json['error']['keyword_' . $store_id . '_' . $language_id] = $this->language->get('error_keyword_exists'); + } + } + } + } + + if (isset($json['error']) && !isset($json['error']['warning'])) { + $json['error']['warning'] = $this->language->get('error_warning'); + } + + if (!$json) { + if (!$this->request->post['product_id']) { + if (!$this->request->post['master_id']) { + // Normal product add + $json['product_id'] = $this->model_catalog_product->addProduct($this->request->post); + } else { + // Variant product add + $json['product_id'] = $this->model_catalog_product->addVariant($this->request->post['master_id'], $this->request->post); + } + } else { + if (!$this->request->post['master_id']) { + // Normal product edit + $this->model_catalog_product->editProduct($this->request->post['product_id'], $this->request->post); + } else { + // Variant product edit + $this->model_catalog_product->editVariant($this->request->post['master_id'], $this->request->post['product_id'], $this->request->post); + } + + // Variant products edit if master product is edited + $this->model_catalog_product->editVariants($this->request->post['product_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('catalog/product'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'catalog/product')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('catalog/product'); + + foreach ($selected as $product_id) { + $this->model_catalog_product->deleteProduct($product_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function copy(): void { + $this->load->language('catalog/product'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'catalog/product')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('catalog/product'); + + foreach ($selected as $product_id) { + $this->model_catalog_product->copyProduct($product_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function report(): void { + $this->load->language('catalog/product'); + + $this->response->setOutput($this->getReport()); + } + + /** + * @return string + */ + public function getReport(): string { + if (isset($this->request->get['product_id'])) { + $product_id = (int)$this->request->get['product_id']; + } else { + $product_id = 0; + } + + if (isset($this->request->get['page']) && $this->request->get['route'] == 'catalog/product.report') { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $limit = 10; + + $data['reports'] = []; + + $this->load->model('catalog/product'); + $this->load->model('setting/store'); + + $results = $this->model_catalog_product->getReports($product_id, ($page - 1) * $limit, $limit); + + foreach ($results as $result) { + $store_info = $this->model_setting_store->getStore($result['store_id']); + + if ($store_info) { + $store = $store_info['name']; + } elseif (!$result['store_id']) { + $store = $this->config->get('config_name'); + } else { + $store = ''; + } + + $data['reports'][] = [ + 'ip' => $result['ip'], + 'store' => $store, + 'country' => $result['country'], + 'date_added' => date($this->language->get('datetime_format'), strtotime($result['date_added'])) + ]; + } + + $report_total = $this->model_catalog_product->getTotalReports($product_id); + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $report_total, + 'page' => $page, + 'limit' => $limit, + 'url' => $this->url->link('catalog/product.report', 'user_token=' . $this->session->data['user_token'] . '&product_id=' . $product_id . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($report_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($report_total - $limit)) ? $report_total : ((($page - 1) * $limit) + $limit), $report_total, ceil($report_total / $limit)); + + return $this->load->view('catalog/product_report', $data); + } + + /** + * @return void + */ + public function autocomplete(): void { + $json = []; + + if (isset($this->request->get['filter_name'])) { + $filter_name = $this->request->get['filter_name']; + } else { + $filter_name = ''; + } + + if (isset($this->request->get['filter_model'])) { + $filter_model = $this->request->get['filter_model']; + } else { + $filter_model = ''; + } + + if (isset($this->request->get['limit'])) { + $limit = (int)$this->request->get['limit']; + } else { + $limit = 5; + } + + $filter_data = [ + 'filter_name' => $filter_name, + 'filter_model' => $filter_model, + 'start' => 0, + 'limit' => $limit + ]; + + $this->load->model('catalog/product'); + $this->load->model('catalog/option'); + $this->load->model('catalog/subscription_plan'); + + $results = $this->model_catalog_product->getProducts($filter_data); + + foreach ($results as $result) { + $option_data = []; + + $product_options = $this->model_catalog_product->getOptions($result['product_id']); + + foreach ($product_options as $product_option) { + $option_info = $this->model_catalog_option->getOption($product_option['option_id']); + + if ($option_info) { + $product_option_value_data = []; + + foreach ($product_option['product_option_value'] as $product_option_value) { + $option_value_info = $this->model_catalog_option->getValue($product_option_value['option_value_id']); + + if ($option_value_info) { + $product_option_value_data[] = [ + 'product_option_value_id' => $product_option_value['product_option_value_id'], + 'option_value_id' => $product_option_value['option_value_id'], + 'name' => $option_value_info['name'], + 'price' => (float)$product_option_value['price'] ? $this->currency->format($product_option_value['price'], $this->config->get('config_currency')) : false, + 'price_prefix' => $product_option_value['price_prefix'] + ]; + } + } + + $option_data[] = [ + 'product_option_id' => $product_option['product_option_id'], + 'product_option_value' => $product_option_value_data, + 'option_id' => $product_option['option_id'], + 'name' => $option_info['name'], + 'type' => $option_info['type'], + 'value' => $product_option['value'], + 'required' => $product_option['required'] + ]; + } + } + + $subscription_data = []; + + $product_subscriptions = $this->model_catalog_product->getSubscriptions($result['product_id']); + + foreach ($product_subscriptions as $product_subscription) { + $subscription_plan_info = $this->model_catalog_subscription_plan->getSubscriptionPlan($product_subscription['subscription_plan_id']); + + if ($subscription_plan_info) { + $subscription_data[] = [ + 'subscription_plan_id' => $subscription_plan_info['subscription_plan_id'], + 'name' => $subscription_plan_info['name'] + ]; + } + } + + $json[] = [ + 'product_id' => $result['product_id'], + 'name' => strip_tags(html_entity_decode($result['name'], ENT_QUOTES, 'UTF-8')), + 'model' => $result['model'], + 'option' => $option_data, + 'subscription' => $subscription_data, + 'price' => $result['price'] + ]; + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/catalog/review.php b/admininistrator/controller/catalog/review.php new file mode 100644 index 0000000..94b70d1 --- /dev/null +++ b/admininistrator/controller/catalog/review.php @@ -0,0 +1,575 @@ +load->language('catalog/review'); + + $this->document->setTitle($this->language->get('heading_title')); + + if (isset($this->request->get['filter_product'])) { + $filter_product = $this->request->get['filter_product']; + } else { + $filter_product = ''; + } + + if (isset($this->request->get['filter_author'])) { + $filter_author = $this->request->get['filter_author']; + } else { + $filter_author = ''; + } + + if (isset($this->request->get['filter_status'])) { + $filter_status = $this->request->get['filter_status']; + } else { + $filter_status = ''; + } + + if (isset($this->request->get['filter_date_from'])) { + $filter_date_from = $this->request->get['filter_date_from']; + } else { + $filter_date_from = ''; + } + + if (isset($this->request->get['filter_date_to'])) { + $filter_date_to = $this->request->get['filter_date_to']; + } else { + $filter_date_to = ''; + } + + $url = ''; + + if (isset($this->request->get['filter_product'])) { + $url .= '&filter_product=' . urlencode(html_entity_decode($this->request->get['filter_product'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_author'])) { + $url .= '&filter_author=' . urlencode(html_entity_decode($this->request->get['filter_author'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('catalog/review', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('catalog/review.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('catalog/review.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('catalog/review', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('catalog/review'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['filter_product'])) { + $filter_product = $this->request->get['filter_product']; + } else { + $filter_product = ''; + } + + if (isset($this->request->get['filter_author'])) { + $filter_author = $this->request->get['filter_author']; + } else { + $filter_author = ''; + } + + if (isset($this->request->get['filter_status'])) { + $filter_status = $this->request->get['filter_status']; + } else { + $filter_status = ''; + } + + if (isset($this->request->get['filter_date_from'])) { + $filter_date_from = $this->request->get['filter_date_from']; + } else { + $filter_date_from = ''; + } + + if (isset($this->request->get['filter_date_to'])) { + $filter_date_to = $this->request->get['filter_date_to']; + } else { + $filter_date_to = ''; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'DESC'; + } + + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'r.date_added'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['filter_product'])) { + $url .= '&filter_product=' . urlencode(html_entity_decode($this->request->get['filter_product'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_author'])) { + $url .= '&filter_author=' . urlencode(html_entity_decode($this->request->get['filter_author'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('catalog/review.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['reviews'] = []; + + $filter_data = [ + 'filter_product' => $filter_product, + 'filter_author' => $filter_author, + 'filter_status' => $filter_status, + 'filter_date_from' => $filter_date_from, + 'filter_date_to' => $filter_date_to, + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('catalog/review'); + + $review_total = $this->model_catalog_review->getTotalReviews($filter_data); + + $results = $this->model_catalog_review->getReviews($filter_data); + + foreach ($results as $result) { + $data['reviews'][] = [ + 'review_id' => $result['review_id'], + 'name' => $result['name'], + 'author' => $result['author'], + 'rating' => $result['rating'], + 'status' => $result['status'], + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])), + 'edit' => $this->url->link('catalog/review.form', 'user_token=' . $this->session->data['user_token'] . '&review_id=' . $result['review_id'] . $url) + ]; + } + + $url = ''; + + if (isset($this->request->get['filter_product'])) { + $url .= '&filter_product=' . urlencode(html_entity_decode($this->request->get['filter_product'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_author'])) { + $url .= '&filter_author=' . urlencode(html_entity_decode($this->request->get['filter_author'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_product'] = $this->url->link('catalog/review.list', 'user_token=' . $this->session->data['user_token'] . '&sort=pd.name' . $url); + $data['sort_author'] = $this->url->link('catalog/review.list', 'user_token=' . $this->session->data['user_token'] . '&sort=r.author' . $url); + $data['sort_rating'] = $this->url->link('catalog/review.list', 'user_token=' . $this->session->data['user_token'] . '&sort=r.rating' . $url); + $data['sort_date_added'] = $this->url->link('catalog/review.list', 'user_token=' . $this->session->data['user_token'] . '&sort=r.date_added' . $url); + + $url = ''; + + if (isset($this->request->get['filter_product'])) { + $url .= '&filter_product=' . urlencode(html_entity_decode($this->request->get['filter_product'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_author'])) { + $url .= '&filter_author=' . urlencode(html_entity_decode($this->request->get['filter_author'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $review_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('catalog/review.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($review_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($review_total - $this->config->get('config_pagination_admin'))) ? $review_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $review_total, ceil($review_total / $this->config->get('config_pagination_admin'))); + + $data['filter_product'] = $filter_product; + $data['filter_author'] = $filter_author; + $data['filter_status'] = $filter_status; + $data['filter_date_from'] = $filter_date_from; + $data['filter_date_to'] = $filter_date_to; + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('catalog/review_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('catalog/review'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['review_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['filter_product'])) { + $url .= '&filter_product=' . urlencode(html_entity_decode($this->request->get['filter_product'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_author'])) { + $url .= '&filter_author=' . urlencode(html_entity_decode($this->request->get['filter_author'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('catalog/review', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('catalog/review.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('catalog/review', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['review_id'])) { + $this->load->model('catalog/review'); + + $review_info = $this->model_catalog_review->getReview($this->request->get['review_id']); + } + + if (isset($this->request->get['review_id'])) { + $data['review_id'] = (int)$this->request->get['review_id']; + } else { + $data['review_id'] = 0; + } + + if (!empty($review_info)) { + $data['product_id'] = $review_info['product_id']; + } else { + $data['product_id'] = ''; + } + + if (!empty($review_info)) { + $data['product'] = $review_info['product']; + } else { + $data['product'] = ''; + } + + if (!empty($review_info)) { + $data['author'] = $review_info['author']; + } else { + $data['author'] = ''; + } + + if (!empty($review_info)) { + $data['text'] = $review_info['text']; + } else { + $data['text'] = ''; + } + + if (!empty($review_info)) { + $data['rating'] = $review_info['rating']; + } else { + $data['rating'] = ''; + } + + if (!empty($review_info)) { + $data['date_added'] = ($review_info['date_added'] != '0000-00-00 00:00' ? $review_info['date_added'] : date('Y-m-d')); + } else { + $data['date_added'] = date('Y-m-d'); + } + + if (!empty($review_info)) { + $data['status'] = $review_info['status']; + } else { + $data['status'] = ''; + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('catalog/review_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('catalog/review'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'catalog/review')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if ((oc_strlen($this->request->post['author']) < 3) || (oc_strlen($this->request->post['author']) > 64)) { + $json['error']['author'] = $this->language->get('error_author'); + } + + if (!$this->request->post['product_id']) { + $json['error']['product'] = $this->language->get('error_product'); + } + + if (oc_strlen($this->request->post['text']) < 1) { + $json['error']['text'] = $this->language->get('error_text'); + } + + if (!isset($this->request->post['rating']) || $this->request->post['rating'] < 0 || $this->request->post['rating'] > 5) { + $json['error']['rating'] = $this->language->get('error_rating'); + } + + if (isset($json['error']) && !isset($json['error']['warning'])) { + $json['error']['warning'] = $this->language->get('error_warning'); + } + + if (!$json) { + $this->load->model('catalog/review'); + + if (!$this->request->post['review_id']) { + $json['review_id'] = $this->model_catalog_review->addReview($this->request->post); + } else { + $this->model_catalog_review->editReview($this->request->post['review_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('catalog/review'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'catalog/review')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('catalog/review'); + + foreach ($selected as $review_id) { + $this->model_catalog_review->deleteReview($review_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function sync(): void { + $this->load->language('catalog/review'); + + $json = []; + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + if (!$this->user->hasPermission('modify', 'catalog/review')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('catalog/product'); + $this->load->model('catalog/review'); + + $total = $this->model_catalog_product->getTotalProducts(); + $limit = 10; + + $start = ($page - 1) * $limit; + $end = $start > ($total - $limit) ? $total : ($start + $limit); + + $product_data = [ + 'start' => ($page - 1) * $limit, + 'limit' => $limit + ]; + + $results = $this->model_catalog_product->getProducts($product_data); + + foreach ($results as $result) { + $this->model_catalog_product->editRating($result['product_id'], $this->model_catalog_review->getRating($result['product_id'])); + } + + if ($total && $end < $total) { + $json['text'] = sprintf($this->language->get('text_next'), $end, $total); + + $json['next'] = $this->url->link('catalog/review.sync', 'user_token=' . $this->session->data['user_token'] . '&page=' . ($page + 1), true); + } else { + $json['success'] = sprintf($this->language->get('text_next'), $end, $total); + + $json['next'] = ''; + } + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/catalog/subscription_plan.php b/admininistrator/controller/catalog/subscription_plan.php new file mode 100644 index 0000000..29137f2 --- /dev/null +++ b/admininistrator/controller/catalog/subscription_plan.php @@ -0,0 +1,432 @@ +load->language('catalog/subscription_plan'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('catalog/subscription_plan', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('catalog/subscription_plan.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['copy'] = $this->url->link('catalog/subscription_plan.copy', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('catalog/subscription_plan.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('catalog/subscription_plan', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('catalog/subscription_plan'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'rd.name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('catalog/subscription_plan.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['subscription_plans'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('catalog/subscription_plan'); + + $subscription_plan_total = $this->model_catalog_subscription_plan->getTotalSubscriptionPlans(); + + $results = $this->model_catalog_subscription_plan->getSubscriptionPlans($filter_data); + + foreach ($results as $result) { + $data['subscription_plans'][] = [ + 'subscription_plan_id' => $result['subscription_plan_id'], + 'name' => $result['name'], + 'status' => $result['status'], + 'sort_order' => $result['sort_order'], + 'edit' => $this->url->link('catalog/subscription_plan.form', 'user_token=' . $this->session->data['user_token'] . '&subscription_plan_id=' . $result['subscription_plan_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('catalog/subscription_plan.list', 'user_token=' . $this->session->data['user_token'] . '&sort=spd.name' . $url); + $data['sort_sort_order'] = $this->url->link('catalog/subscription_plan.list', 'user_token=' . $this->session->data['user_token'] . '&sort=sp.sort_order' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $subscription_plan_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('catalog/subscription_plan.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($subscription_plan_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($subscription_plan_total - $this->config->get('config_pagination_admin'))) ? $subscription_plan_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $subscription_plan_total, ceil($subscription_plan_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('catalog/subscription_plan_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('catalog/subscription_plan'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['subscription_plan_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('catalog/subscription_plan', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('catalog/subscription_plan.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('catalog/subscription_plan', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['subscription_plan_id'])) { + $this->load->model('catalog/subscription_plan'); + + $subscription_info = $this->model_catalog_subscription_plan->getSubscriptionPlan($this->request->get['subscription_plan_id']); + } + + if (isset($this->request->get['subscription_plan_id'])) { + $data['subscription_plan_id'] = (int)$this->request->get['subscription_plan_id']; + } else { + $data['subscription_plan_id'] = 0; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (isset($this->request->get['subscription_plan_id'])) { + $data['subscription_plan_description'] = $this->model_catalog_subscription_plan->getDescription($this->request->get['subscription_plan_id']); + } else { + $data['subscription_plan_description'] = []; + } + + $data['frequencies'] = []; + + $data['frequencies'][] = [ + 'text' => $this->language->get('text_day'), + 'value' => 'day' + ]; + + $data['frequencies'][] = [ + 'text' => $this->language->get('text_week'), + 'value' => 'week' + ]; + + $data['frequencies'][] = [ + 'text' => $this->language->get('text_semi_month'), + 'value' => 'semi_month' + ]; + + $data['frequencies'][] = [ + 'text' => $this->language->get('text_month'), + 'value' => 'month' + ]; + + $data['frequencies'][] = [ + 'text' => $this->language->get('text_year'), + 'value' => 'year' + ]; + + if (!empty($subscription_info)) { + $data['trial_frequency'] = $subscription_info['trial_frequency']; + } else { + $data['trial_frequency'] = ''; + } + + if (!empty($subscription_info)) { + $data['trial_duration'] = $subscription_info['trial_duration']; + } else { + $data['trial_duration'] = '0'; + } + + if (!empty($subscription_info)) { + $data['trial_cycle'] = $subscription_info['trial_cycle']; + } else { + $data['trial_cycle'] = '1'; + } + + if (!empty($subscription_info)) { + $data['trial_status'] = $subscription_info['trial_status']; + } else { + $data['trial_status'] = 0; + } + + if (!empty($subscription_info)) { + $data['frequency'] = $subscription_info['frequency']; + } else { + $data['frequency'] = ''; + } + + if (!empty($subscription_info)) { + $data['duration'] = $subscription_info['duration']; + } else { + $data['duration'] = 0; + } + + if (!empty($subscription_info)) { + $data['cycle'] = $subscription_info['cycle']; + } else { + $data['cycle'] = 1; + } + + if (!empty($subscription_info)) { + $data['status'] = $subscription_info['status']; + } else { + $data['status'] = 0; + } + + if (!empty($subscription_info)) { + $data['sort_order'] = $subscription_info['sort_order']; + } else { + $data['sort_order'] = 0; + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('catalog/subscription_plan_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('catalog/subscription_plan'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'catalog/subscription_plan')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + foreach ($this->request->post['subscription_plan_description'] as $language_id => $value) { + if ((oc_strlen(trim($value['name'])) < 3) || (oc_strlen($value['name']) > 255)) { + $json['error']['name_' . $language_id] = $this->language->get('error_name'); + } + } + + if ($this->request->post['trial_duration'] && (int)$this->request->post['trial_duration'] < 1) { + $json['error']['trial_duration'] = $this->language->get('error_trial_duration'); + } + + if (isset($json['error']) && !isset($json['error']['warning'])) { + $json['error']['warning'] = $this->language->get('error_warning'); + } + + if (!$json) { + $this->load->model('catalog/subscription_plan'); + + if (!$this->request->post['subscription_plan_id']) { + $json['subscription_plan_id'] = $this->model_catalog_subscription_plan->addSubscriptionPlan($this->request->post); + } else { + $this->model_catalog_subscription_plan->editSubscriptionPlan($this->request->post['subscription_plan_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function copy(): void { + $this->load->language('catalog/subscription_plan'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'catalog/subscription_plan')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('catalog/subscription_plan'); + + foreach ($selected as $subscription_plan_id) { + $this->model_catalog_subscription_plan->copySubscriptionPlan($subscription_plan_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('catalog/subscription_plan'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'catalog/subscription_plan')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('catalog/product'); + + foreach ($selected as $subscription_id) { + $product_total = $this->model_catalog_product->getTotalProductsBySubscriptionPlanId($subscription_id); + + if ($product_total) { + $json['error'] = sprintf($this->language->get('error_product'), $product_total); + } + } + + if (!$json) { + $this->load->model('catalog/subscription_plan'); + + foreach ($selected as $subscription_plan_id) { + $this->model_catalog_subscription_plan->deleteSubscriptionPlan($subscription_plan_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/cms/antispam.php b/admininistrator/controller/cms/antispam.php new file mode 100644 index 0000000..102abad --- /dev/null +++ b/admininistrator/controller/cms/antispam.php @@ -0,0 +1,320 @@ +load->language('cms/antispam'); + + $this->document->setTitle($this->language->get('heading_title')); + + if (isset($this->request->get['filter_keyword'])) { + $filter_keyword = (string)$this->request->get['filter_keyword']; + } else { + $filter_keyword = ''; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('cms/antispam', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('cms/antispam.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('cms/antispam.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['filter_keyword'] = $filter_keyword; + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('cms/antispam', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('cms/antispam'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['filter_keyword'])) { + $filter_keyword = (string)$this->request->get['filter_keyword']; + } else { + $filter_keyword = ''; + } + + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'keyword'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['filter_keyword'])) { + $url .= '&filter_keyword=' . urlencode(html_entity_decode($this->request->get['filter_keyword'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('cms/antispam.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['antispams'] = []; + + $filter_data = [ + 'filter_keyword' => $filter_keyword, + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('cms/antispam'); + + $antispam_total = $this->model_cms_antispam->getTotalAntispams($filter_data); + + $results = $this->model_cms_antispam->getAntispams($filter_data); + + foreach ($results as $result) { + $data['antispams'][] = [ + 'antispam_id' => $result['antispam_id'], + 'keyword' => $result['keyword'], + 'edit' => $this->url->link('cms/antispam.form', 'user_token=' . $this->session->data['user_token'] . '&antispam_id=' . $result['antispam_id'] . $url) + ]; + } + + $url = ''; + + if (isset($this->request->get['filter_keyword'])) { + $url .= '&filter_keyword=' . urlencode(html_entity_decode($this->request->get['filter_keyword'], ENT_QUOTES, 'UTF-8')); + } + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_keyword'] = $this->url->link('cms/antispam.list', 'user_token=' . $this->session->data['user_token'] . '&sort=keyword' . $url); + + $url = ''; + + if (isset($this->request->get['filter_keyword'])) { + $url .= '&filter_keyword=' . urlencode(html_entity_decode($this->request->get['filter_keyword'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $antispam_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('cms/antispam.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($antispam_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($antispam_total - $this->config->get('config_pagination_admin'))) ? $antispam_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $antispam_total, ceil($antispam_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('cms/antispam_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('cms/antispam'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['antispam_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['filter_keyword'])) { + $url .= '&filter_keyword=' . urlencode(html_entity_decode($this->request->get['filter_keyword'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('cms/antispam', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('cms/antispam.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('cms/antispam', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['antispam_id'])) { + $this->load->model('cms/antispam'); + + $antispam_info = $this->model_cms_antispam->getAntispam($this->request->get['antispam_id']); + } + + if (isset($this->request->get['antispam_id'])) { + $data['antispam_id'] = (int)$this->request->get['antispam_id']; + } else { + $data['antispam_id'] = 0; + } + + if (!empty($antispam_info)) { + $data['keyword'] = $antispam_info['keyword']; + } else { + $data['keyword'] = ''; + } + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('cms/antispam_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('cms/antispam'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'cms/antispam')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if ((oc_strlen($this->request->post['keyword']) < 1) || (oc_strlen($this->request->post['keyword']) > 64)) { + $json['error']['keyword'] = $this->language->get('error_keyword'); + } + + if (!$json) { + $this->load->model('cms/antispam'); + + if (!$this->request->post['antispam_id']) { + $json['antispam_id'] = $this->model_cms_antispam->addAntispam($this->request->post); + } else { + $this->model_cms_antispam->editAntispam($this->request->post['antispam_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('cms/antispam'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'cms/antispam')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('cms/antispam'); + + foreach ($selected as $antispam_id) { + $this->model_cms_antispam->deleteAntispam($antispam_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/cms/article.php b/admininistrator/controller/cms/article.php new file mode 100644 index 0000000..5a6ea7c --- /dev/null +++ b/admininistrator/controller/cms/article.php @@ -0,0 +1,431 @@ +load->language('cms/article'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('cms/article', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('cms/article.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('cms/article.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('cms/article', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('cms/article'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'date_added'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('cms/article.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['articles'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('cms/article'); + + $article_total = $this->model_cms_article->getTotalArticles(); + + $results = $this->model_cms_article->getArticles($filter_data); + + foreach ($results as $result) { + $data['articles'][] = [ + 'article_id' => $result['article_id'], + 'name' => $result['name'], + 'author' => $result['author'], + 'status' => $result['status'], + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])), + 'edit' => $this->url->link('cms/article.form', 'user_token=' . $this->session->data['user_token'] . '&article_id=' . $result['article_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('cms/article.list', 'user_token=' . $this->session->data['user_token'] . '&sort=ad.name' . $url); + $data['sort_author'] = $this->url->link('cms/article.list', 'user_token=' . $this->session->data['user_token'] . '&sort=a.author' . $url); + $data['sort_date_added'] = $this->url->link('cms/article.list', 'user_token=' . $this->session->data['user_token'] . '&sort=a.date_added' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $article_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('cms/article.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($article_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($article_total - $this->config->get('config_pagination_admin'))) ? $article_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $article_total, ceil($article_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('cms/article_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('cms/article'); + + $this->document->setTitle($this->language->get('heading_title')); + + $this->document->addScript('view/javascript/ckeditor/ckeditor.js'); + $this->document->addScript('view/javascript/ckeditor/adapters/jquery.js'); + + $data['text_form'] = !isset($this->request->get['article_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('cms/article', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('cms/article.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('cms/article', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['article_id'])) { + $this->load->model('cms/article'); + + $article_info = $this->model_cms_article->getArticle($this->request->get['article_id']); + } + + if (isset($this->request->get['article_id'])) { + $data['article_id'] = (int)$this->request->get['article_id']; + } else { + $data['article_id'] = 0; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + $this->load->model('tool/image'); + + $data['placeholder'] = $this->model_tool_image->resize('no_image.png', 100, 100); + + $data['article_description'] = []; + + if (isset($this->request->get['article_id'])) { + $results = $this->model_cms_article->getDescriptions($this->request->get['article_id']); + + foreach ($results as $key => $result) { + $data['article_description'][$key] = $result; + + if (is_file(DIR_IMAGE . html_entity_decode($result['image'], ENT_QUOTES, 'UTF-8'))) { + $data['article_description'][$key]['thumb'] = $this->model_tool_image->resize(html_entity_decode($result['image'], ENT_QUOTES, 'UTF-8'), 100, 100); + } else { + $data['article_description'][$key]['thumb'] = $data['placeholder']; + } + } + } + + if (!empty($article_info)) { + $data['author'] = $article_info['author']; + } else { + $data['author'] = ''; + } + + $this->load->model('cms/topic'); + + $data['topics'] = $this->model_cms_topic->getTopics(); + + if (!empty($article_info)) { + $data['topic_id'] = $article_info['topic_id']; + } else { + $data['topic_id'] = 0; + } + + $data['stores'] = []; + + $data['stores'][] = [ + 'store_id' => 0, + 'name' => $this->language->get('text_default') + ]; + + $this->load->model('setting/store'); + + $stores = $this->model_setting_store->getStores(); + + foreach ($stores as $store) { + $data['stores'][] = [ + 'store_id' => $store['store_id'], + 'name' => $store['name'] + ]; + } + + if (isset($this->request->get['article_id'])) { + $data['article_store'] = $this->model_cms_article->getStores($this->request->get['article_id']); + } else { + $data['article_store'] = [0]; + } + + if (!empty($article_info)) { + $data['image'] = $article_info['image']; + } else { + $data['image'] = ''; + } + + $this->load->model('tool/image'); + + $data['placeholder'] = $this->model_tool_image->resize('no_image.png', 100, 100); + + if (is_file(DIR_IMAGE . html_entity_decode($data['image'], ENT_QUOTES, 'UTF-8'))) { + $data['thumb'] = $this->model_tool_image->resize(html_entity_decode($data['image'], ENT_QUOTES, 'UTF-8'), 100, 100); + } else { + $data['thumb'] = $data['placeholder']; + } + + if (!empty($article_info)) { + $data['status'] = $article_info['status']; + } else { + $data['status'] = true; + } + + if (isset($this->request->get['article_id'])) { + $data['article_seo_url'] = $this->model_cms_article->getSeoUrls($this->request->get['article_id']); + } else { + $data['article_seo_url'] = []; + } + + $this->load->model('design/layout'); + + $data['layouts'] = $this->model_design_layout->getLayouts(); + + if (isset($this->request->get['article_id'])) { + $data['article_layout'] = $this->model_cms_article->getLayouts($this->request->get['article_id']); + } else { + $data['article_layout'] = []; + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('cms/article_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('cms/article'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'cms/article')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + foreach ($this->request->post['article_description'] as $language_id => $value) { + if ((oc_strlen(trim($value['name'])) < 1) || (oc_strlen($value['name']) > 255)) { + $json['error']['name_' . $language_id] = $this->language->get('error_name'); + } + + if ((oc_strlen(trim($value['meta_title'])) < 1) || (oc_strlen($value['meta_title']) > 255)) { + $json['error']['meta_title_' . $language_id] = $this->language->get('error_meta_title'); + } + } + + if ((oc_strlen($this->request->post['author']) < 3) || (oc_strlen($this->request->post['author']) > 64)) { + $json['error']['author'] = $this->language->get('error_author'); + } + + if ($this->request->post['article_seo_url']) { + $this->load->model('design/seo_url'); + + foreach ($this->request->post['article_seo_url'] as $store_id => $language) { + foreach ($language as $language_id => $keyword) { + if ((oc_strlen(trim($keyword)) < 1) || (oc_strlen($keyword) > 64)) { + $json['error']['keyword_' . $store_id . '_' . $language_id] = $this->language->get('error_keyword'); + } + + if (preg_match('/[^a-zA-Z0-9\/_-]|[\p{Cyrillic}]+/u', $keyword)) { + $json['error']['keyword_' . $store_id . '_' . $language_id] = $this->language->get('error_keyword_character'); + } + + $seo_url_info = $this->model_design_seo_url->getSeoUrlByKeyword($keyword, $store_id); + + if ($seo_url_info && (!isset($this->request->post['article_id']) || $seo_url_info['key'] != 'article_id' || $seo_url_info['value'] != (int)$this->request->post['article_id'])) { + $json['error']['keyword_' . $store_id . '_' . $language_id] = $this->language->get('error_keyword_exists'); + } + } + } + } + + if (isset($json['error']) && !isset($json['error']['warning'])) { + $json['error']['warning'] = $this->language->get('error_warning'); + } + + if (!$json) { + $this->load->model('cms/article'); + + if (!$this->request->post['article_id']) { + $json['article_id'] = $this->model_cms_article->addArticle($this->request->post); + } else { + $this->model_cms_article->editArticle($this->request->post['article_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('cms/article'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'cms/article')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('cms/article'); + + foreach ($selected as $article_id) { + $this->model_cms_article->deleteArticle($article_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/cms/comment.php b/admininistrator/controller/cms/comment.php new file mode 100644 index 0000000..e7e3fc7 --- /dev/null +++ b/admininistrator/controller/cms/comment.php @@ -0,0 +1,396 @@ +load->language('cms/comment'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['breadcrumbs'] = array(); + + $data['breadcrumbs'][] = array( + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ); + + $data['breadcrumbs'][] = array( + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('cms/comment', 'user_token=' . $this->session->data['user_token']) + ); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('cms/comment', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('cms/comment'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + if (isset($this->request->get['filter_keyword'])) { + $filter_keyword = $this->request->get['filter_keyword']; + } else { + $filter_keyword = ''; + } + + if (isset($this->request->get['filter_title'])) { + $filter_title = $this->request->get['filter_title']; + } else { + $filter_title = ''; + } + + if (isset($this->request->get['filter_customer'])) { + $filter_customer = $this->request->get['filter_customer']; + } else { + $filter_customer = ''; + } + + if (isset($this->request->get['filter_status'])) { + $filter_status = $this->request->get['filter_status']; + } else { + $filter_status = 0; + } + + if (isset($this->request->get['filter_date_added'])) { + $filter_date_added = $this->request->get['filter_date_added']; + } else { + $filter_date_added = ''; + } + + if (isset($this->request->get['page'])) { + $page = $this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['filter_keyword'])) { + $url .= '&filter_keyword=' . urlencode(html_entity_decode($this->request->get['filter_keyword'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_title'])) { + $url .= '&filter_title=' . urlencode(html_entity_decode($this->request->get['filter_title'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['filter_date_added'])) { + $url .= '&filter_date_added=' . $this->request->get['filter_date_added']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['comments'] = array(); + + $filter_data = array( + 'filter_keyword' => $filter_keyword, + 'filter_title' => $filter_title, + 'filter_customer' => $filter_customer, + 'filter_status' => $filter_status, + 'filter_date_added' => $filter_date_added, + 'start' => ($page - 1) * 10, + 'limit' => 10 + ); + + $this->load->model('cms/article'); + + $comment_total = $this->model_cms_article->getTotalComments($filter_data); + + $results = $this->model_cms_article->getComments($filter_data); + + foreach ($results as $result) { + if (!$result['status']) { + $approve = $this->url->link('cms/comment.approve', 'user_token=' . $this->session->data['user_token'] . '&comment_id=' . $result['comment_id'] . $url); + } else { + $approve = ''; + } + + $data['comments'][] = array( + 'article' => $result['article'], + 'article_edit' => $this->url->link('cms/article.edit', 'user_token=' . $this->session->data['user_token'] . '&article_id=' . $result['article_id']), + 'customer' => $result['customer'], + 'customer_edit' => $this->url->link('customer/customer.edit', 'user_token=' . $this->session->data['user_token'] . '&customer_id=' . $result['customer_id']), + 'comment' => nl2br($result['comment']), + 'date_added' => date('d/m/Y', strtotime($result['date_added'])), + 'approve' => $approve, + 'spam' => $this->url->link('cms/comment.spam', 'user_token=' . $this->session->data['user_token'] . '&comment_id=' . $result['comment_id'] . $url), + 'delete' => $this->url->link('cms/comment.delete', 'user_token=' . $this->session->data['user_token'] . '&comment_id=' . $result['comment_id'] . $url) + ); + } + + $url = ''; + + if (isset($this->request->get['filter_keyword'])) { + $url .= '&filter_keyword=' . urlencode(html_entity_decode($this->request->get['filter_keyword'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_title'])) { + $url .= '&filter_title=' . urlencode(html_entity_decode($this->request->get['filter_title'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['filter_date_added'])) { + $url .= '&filter_date_added=' . $this->request->get['filter_date_added']; + } + + $data['pagination'] = $this->load->controller('common/pagination', array( + 'total' => $comment_total, + 'page' => $page, + 'limit' => 10, + 'url' => $this->url->link('cms/comment.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + )); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($comment_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($comment_total - $this->config->get('config_pagination_admin'))) ? $comment_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $comment_total, ceil($comment_total / $this->config->get('config_pagination_admin'))); + + return $this->load->view('cms/comment_list', $data); + } + + public function approve() { + $this->load->language('cms/comment'); + + $json = array(); + + if (isset($this->request->get['article_comment_id'])) { + $article_comment_id = $this->request->get['article_comment_id']; + } else { + $article_comment_id = 0; + } + + if (!$this->user->hasPermission('modify', 'cms/comment')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('cms/article'); + + $comment_info = $this->model_cms_article->getComment($article_comment_id); + + if (!$comment_info) { + $json['error'] = $this->language->get('error_comment'); + } + + if (!$json) { + // Approve Commentor + $this->load->model('customer/customer'); + + $this->model_customer_customer->editCommentor($comment_info['customer_id'], 1); + + // Approve all past comments + $filter_data = array( + 'filter_customer_id' => $comment_info['customer_id'], + 'filter_status' => 0 + ); + + $results = $this->model_cms_comment->getComments($filter_data); + + foreach ($results as $result) { + $this->model_cms_comment->editStatus($result['customer_id'], 1); + } + + $json['success'] = $this->language->get('text_success'); + + $url = ''; + + if (isset($this->request->get['filter_keyword'])) { + $url .= '&filter_keyword=' . urlencode(html_entity_decode($this->request->get['filter_keyword'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_title'])) { + $url .= '&filter_title=' . urlencode(html_entity_decode($this->request->get['filter_title'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['filter_date_added'])) { + $url .= '&filter_date_added=' . $this->request->get['filter_date_added']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $json['redirect'] = $this->url->link('cms/comment.comment', 'user_token=' . $this->session->data['user_token'] . $url, true); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + public function spam() { + $this->load->language('cms/comment'); + + $json = array(); + + if (isset($this->request->get['comment_id'])) { + $comment_id = $this->request->get['comment_id']; + } else { + $comment_id = 0; + } + + if (!$this->user->hasPermission('modify', 'cms/comment')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('cms/article'); + + $comment_info = $this->model_cms_article->getComment($comment_id); + + if (!$comment_info) { + $json['error'] = $this->language->get('error_comment'); + } + + if (!$json) { + $this->load->model('customer/customer'); + + $this->model_customer_customer->editCommentor($comment_info['customer_id'], 0); + $this->model_customer_customer->editStatus($comment_info['customer_id'], 0); + $this->model_customer_customer->addHistory($comment_info['customer_id'], 'SPAMMER!!!'); + + // Delete all customer comments + $results = $this->model_cms_comment->getComments(array('filter_customer_id' => $comment_info['customer_id'])); + + foreach ($results as $result) { + $this->model_cms_comment->deleteCommentsByCustomerId($result['comment_id']); + } + + $json['success'] = $this->language->get('text_success'); + + $url = ''; + + if (isset($this->request->get['filter_keyword'])) { + $url .= '&filter_keyword=' . urlencode(html_entity_decode($this->request->get['filter_keyword'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_title'])) { + $url .= '&filter_title=' . urlencode(html_entity_decode($this->request->get['filter_title'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['filter_date_added'])) { + $url .= '&filter_date_added=' . $this->request->get['filter_date_added']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $json['redirect'] = $this->url->link('cms/comment/comment', 'user_token=' . $this->session->data['user_token'] . $url, true); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + public function delete() { + $this->load->language('cms/comment'); + + $json = array(); + + if (isset($this->request->get['comment_id'])) { + $comment_id = $this->request->get['comment_id']; + } else { + $comment_id = 0; + } + + if (!$this->user->hasPermission('modify', 'cms/comment')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('cms/article'); + + $comment_info = $this->model_cms_article->getComment($comment_id); + + if (!$comment_info) { + $json['error'] = $this->language->get('error_comment'); + } + + if (!$json) { + $this->model_cms_article->deleteComment($comment_id); + + $json['success'] = $this->language->get('error_success'); + + $url = ''; + + if (isset($this->request->get['filter_keyword'])) { + $url .= '&filter_keyword=' . urlencode(html_entity_decode($this->request->get['filter_keyword'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_title'])) { + $url .= '&filter_title=' . urlencode(html_entity_decode($this->request->get['filter_title'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['filter_date_added'])) { + $url .= '&filter_date_added=' . $this->request->get['filter_date_added']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $json['redirect'] = $this->url->link('cms/comment.comment', 'user_token=' . $this->session->data['user_token'] . $url, true); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/cms/topic.php b/admininistrator/controller/cms/topic.php new file mode 100644 index 0000000..e5623be --- /dev/null +++ b/admininistrator/controller/cms/topic.php @@ -0,0 +1,389 @@ +load->language('cms/topic'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('cms/topic', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('cms/topic.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('cms/topic.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('cms/topic', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('cms/topic'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 't.sort_order'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('cms/topic.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['topics'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('cms/topic'); + + $topic_total = $this->model_cms_topic->getTotalTopics(); + + $results = $this->model_cms_topic->getTopics($filter_data); + + foreach ($results as $result) { + $data['topics'][] = [ + 'topic_id' => $result['topic_id'], + 'name' => $result['name'], + 'status' => $result['status'], + 'sort_order' => $result['sort_order'], + 'edit' => $this->url->link('cms/topic.form', 'user_token=' . $this->session->data['user_token'] . '&topic_id=' . $result['topic_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('cms/topic.list', 'user_token=' . $this->session->data['user_token'] . '&sort=bcd.name' . $url); + $data['sort_sort_order'] = $this->url->link('cms/topic.list', 'user_token=' . $this->session->data['user_token'] . '&sort=bc.sort_order' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $topic_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('cms/topic.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($topic_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($topic_total - $this->config->get('config_pagination_admin'))) ? $topic_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $topic_total, ceil($topic_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('cms/topic_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('cms/topic'); + + $this->document->setTitle($this->language->get('heading_title')); + + $this->document->addScript('view/javascript/ckeditor/ckeditor.js'); + $this->document->addScript('view/javascript/ckeditor/adapters/jquery.js'); + + $data['text_form'] = !isset($this->request->get['topic_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('cms/topic', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('cms/topic.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('cms/topic', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['topic_id'])) { + $this->load->model('cms/topic'); + + $topic_info = $this->model_cms_topic->getTopic($this->request->get['topic_id']); + } + + if (isset($this->request->get['topic_id'])) { + $data['topic_id'] = (int)$this->request->get['topic_id']; + } else { + $data['topic_id'] = 0; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + $this->load->model('tool/image'); + + $data['placeholder'] = $this->model_tool_image->resize('no_image.png', 100, 100); + + $data['topic_description'] = []; + + if (isset($this->request->get['topic_id'])) { + $results = $this->model_cms_topic->getDescriptions($this->request->get['topic_id']); + + foreach ($results as $key => $result) { + $data['topic_description'][$key] = $result; + + if (is_file(DIR_IMAGE . html_entity_decode($result['image'], ENT_QUOTES, 'UTF-8'))) { + $data['topic_description'][$key]['thumb'] = $this->model_tool_image->resize(html_entity_decode($result['image'], ENT_QUOTES, 'UTF-8'), 100, 100); + } else { + $data['topic_description'][$key]['thumb'] = $data['placeholder']; + } + } + } + + $data['stores'] = []; + + $data['stores'][] = [ + 'store_id' => 0, + 'name' => $this->language->get('text_default') + ]; + + $this->load->model('setting/store'); + + $stores = $this->model_setting_store->getStores(); + + foreach ($stores as $store) { + $data['stores'][] = [ + 'store_id' => $store['store_id'], + 'name' => $store['name'] + ]; + } + + if (isset($this->request->get['topic_id'])) { + $data['topic_store'] = $this->model_cms_topic->getStores($this->request->get['topic_id']); + } else { + $data['topic_store'] = [0]; + } + + if (!empty($topic_info)) { + $data['sort_order'] = $topic_info['sort_order']; + } else { + $data['sort_order'] = 0; + } + + if (!empty($topic_info)) { + $data['status'] = $topic_info['status']; + } else { + $data['status'] = true; + } + + if (isset($this->request->get['topic_id'])) { + $data['topic_seo_url'] = $this->model_cms_topic->getSeoUrls($this->request->get['topic_id']); + } else { + $data['topic_seo_url'] = []; + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('cms/topic_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('cms/topic'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'cms/topic')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + foreach ($this->request->post['topic_description'] as $language_id => $value) { + if ((oc_strlen(trim($value['name'])) < 1) || (oc_strlen($value['name']) > 255)) { + $json['error']['name_' . $language_id] = $this->language->get('error_name'); + } + + if ((oc_strlen(trim($value['meta_title'])) < 1) || (oc_strlen($value['meta_title']) > 255)) { + $json['error']['meta_title_' . $language_id] = $this->language->get('error_meta_title'); + } + } + + if ($this->request->post['topic_seo_url']) { + $this->load->model('design/seo_url'); + + foreach ($this->request->post['topic_seo_url'] as $store_id => $language) { + foreach ($language as $language_id => $keyword) { + if ((oc_strlen(trim($keyword)) < 1) || (oc_strlen($keyword) > 64)) { + $json['error']['keyword_' . $store_id . '_' . $language_id] = $this->language->get('error_keyword'); + } + + if (preg_match('/[^a-zA-Z0-9\/_-]|[\p{Cyrillic}]+/u', $keyword)) { + $json['error']['keyword_' . $store_id . '_' . $language_id] = $this->language->get('error_keyword_character'); + } + + $seo_url_info = $this->model_design_seo_url->getSeoUrlByKeyword($keyword, $store_id); + + if ($seo_url_info && (!isset($this->request->post['topic_id']) || $seo_url_info['key'] != 'topic_id' || $seo_url_info['value'] != (int)$this->request->post['topic_id'])) { + $json['error']['keyword_' . $store_id . '_' . $language_id] = $this->language->get('error_keyword_exists'); + } + } + } + } + + if (isset($json['error']) && !isset($json['error']['warning'])) { + $json['error']['warning'] = $this->language->get('error_warning'); + } + + if (!$json) { + $this->load->model('cms/topic'); + + if (!$this->request->post['topic_id']) { + $json['topic_id'] = $this->model_cms_topic->addTopic($this->request->post); + } else { + $this->model_cms_topic->editTopic($this->request->post['topic_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('cms/topic'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'cms/topic')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('cms/topic'); + + foreach ($selected as $topic_id) { + $this->model_cms_topic->deleteTopic($topic_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/common/authorize.php b/admininistrator/controller/common/authorize.php new file mode 100644 index 0000000..ed60f5f --- /dev/null +++ b/admininistrator/controller/common/authorize.php @@ -0,0 +1,243 @@ +load->language('common/authorize'); + + $this->document->setTitle($this->language->get('heading_title')); + + if (isset($this->request->cookie['authorize'])) { + $token = $this->request->cookie['authorize']; + } else { + $token = ''; + } + + // Check to see if user is using incorrect token + if (isset($this->session->data['error'])) { + $data['error_warning'] = $this->session->data['error']; + + unset($this->session->data['error']); + } else { + $data['error_warning'] = ''; + } + + if (isset($this->session->data['success'])) { + $data['success'] = $this->session->data['success']; + + unset($this->session->data['success']); + } else { + $data['success'] = ''; + } + + $this->load->model('user/user'); + + $login_info = $this->model_user_user->getAuthorizeByToken($this->user->getId(), $token); + + if (!$login_info) { + // Create a token that can be stored as a cookie and will be used to identify device is safe. + $token = oc_token(32); + + $authorize_data = [ + 'token' => $token, + 'ip' => $this->request->server['REMOTE_ADDR'], + 'user_agent' => $this->request->server['HTTP_USER_AGENT'] + ]; + + $this->load->model('user/user'); + + $this->model_user_user->addAuthorize($this->user->getId(), $authorize_data); + + setcookie('authorize', $token, time() + 60 * 60 * 24 * 365 * 10); + } + + $data['action'] = $this->url->link('common/authorize.validate', 'user_token=' . $this->session->data['user_token']); + + // Set the code to be emailed + $this->session->data['code'] = oc_token(4); + + if (isset($this->request->get['route']) && $this->request->get['route'] != 'common/login' && $this->request->get['route'] != 'common/authorize') { + $args = $this->request->get; + + $route = $args['route']; + + unset($args['route']); + unset($args['user_token']); + + $url = ''; + + if ($args) { + $url .= http_build_query($args); + } + + $data['redirect'] = $this->url->link($route, $url); + } else { + $data['redirect'] = $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token'], true); + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('common/authorize', $data)); + } + + /** + * @return void + */ + public function send() { + $this->load->language('common/authorize'); + + $json = []; + + $json['success'] = $this->language->get('text_resend'); + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function validate(): void { + $this->load->language('common/authorize'); + + $json = []; + + if (isset($this->request->cookie['authorize'])) { + $token = $this->request->cookie['authorize']; + } else { + $token = ''; + } + + $this->load->model('user/user'); + + $authorize_info = $this->model_user_user->getAuthorizeByToken($this->user->getId(), $token); + + if ($authorize_info) { + if (($authorize_info['attempts'] <= 2) && (!isset($this->request->post['code']) || !isset($this->session->data['code']) || ($this->request->post['code'] != $this->session->data['code']))) { + $json['error'] = $this->language->get('error_code'); + + $this->model_user_user->editAuthorizeTotal($authorize_info['user_authorize_id'], $authorize_info['total'] + 1); + } + + if ($authorize_info['attempts'] >= 2) { + $json['redirect'] = $this->url->link('common/authorize.unlock', 'user_token=' . $this->session->data['user_token'], true); + } + } else { + $json['error'] = $this->language->get('error_code'); + } + + if (!$json) { + $this->model_user_user->editAuthorizeStatus($authorize_info['user_authorize_id'], 1); + $this->model_user_user->editAuthorizeTotal($authorize_info['user_authorize_id'], 0); + + // Register the cookie for security. + if (isset($this->request->post['redirect']) && (strpos($this->request->post['redirect'], HTTP_SERVER) === 0)) { + $json['redirect'] = str_replace('&', '&', $this->request->post['redirect'] . '&user_token=' . $this->session->data['user_token']); + } else { + $json['redirect'] = $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token'], true); + } + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function unlock() { + $this->load->language('common/authorize'); + + if (isset($this->request->cookie['authorize'])) { + $token = $this->request->cookie['authorize']; + } else { + $token = ''; + } + + $this->load->model('user/user'); + + $authorize_info = $this->model_user_user->getAuthorizeByToken($this->user->getId(), $token); + + if ($authorize_info && $authorize_info['status']) { + // Redirect if already have a valid token. + $this->response->redirect($this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token'], true)); + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('common/authorize_unlock', $data)); + } + + /** + * @return void + */ + public function confirm() { + $this->load->language('common/authorize'); + + $json = []; + + $json['success'] = $this->language->get('text_link'); + + // Create reset code + $this->load->model('user/user'); + + $this->model_user_user->editCode($this->user->getEmail(), oc_token(32)); + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function reset() { + $this->load->language('common/authorize'); + + if (isset($this->request->get['email'])) { + $email = (string)$this->request->get['email']; + } else { + $email = ''; + } + + if (isset($this->request->get['code'])) { + $code = (string)$this->request->get['code']; + } else { + $code = ''; + } + + $this->load->model('user/user'); + + $user_info = $this->model_user_user->getUserByEmail($email); + + if ($user_info && $user_info['code'] && $code && $user_info['code'] === $code) { + $this->model_user_user->resetAuthorizes($user_info['user_id']); + + $this->model_user_user->editCode($email, ''); + + $this->session->data['success'] = $this->language->get('text_unlocked'); + + $this->response->redirect($this->url->link('common/authorize', 'user_token=' . $this->session->data['user_token'], true)); + } else { + $this->user->logout(); + + $this->model_user_user->editCode($email, ''); + + $this->session->data['error'] = $this->language->get('error_reset'); + + $this->response->redirect($this->url->link('common/login', '', true)); + } + } +} diff --git a/admininistrator/controller/common/column_left.php b/admininistrator/controller/common/column_left.php new file mode 100644 index 0000000..19c95c3 --- /dev/null +++ b/admininistrator/controller/common/column_left.php @@ -0,0 +1,808 @@ +request->get['user_token']) && isset($this->session->data['user_token']) && ((string)$this->request->get['user_token'] == $this->session->data['user_token'])) { + $this->load->language('common/column_left'); + + // Create a 3 level menu array + // Level 2 cannot have children + + // Menu + $data['menus'][] = [ + 'id' => 'menu-dashboard', + 'icon' => 'fas fa-home', + 'name' => $this->language->get('text_dashboard'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + + // Catalog + $catalog = []; + + if ($this->user->hasPermission('access', 'catalog/category')) { + $catalog[] = [ + 'name' => $this->language->get('text_category'), + 'href' => $this->url->link('catalog/category', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'catalog/product')) { + $catalog[] = [ + 'name' => $this->language->get('text_product'), + 'href' => $this->url->link('catalog/product', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'catalog/subscription_plan')) { + $catalog[] = [ + 'name' => $this->language->get('text_subscription_plan'), + 'href' => $this->url->link('catalog/subscription_plan', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'catalog/filter')) { + $catalog[] = [ + 'name' => $this->language->get('text_filter'), + 'href' => $this->url->link('catalog/filter', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + // Attributes + $attribute = []; + + if ($this->user->hasPermission('access', 'catalog/attribute')) { + $attribute[] = [ + 'name' => $this->language->get('text_attribute'), + 'href' => $this->url->link('catalog/attribute', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'catalog/attribute_group')) { + $attribute[] = [ + 'name' => $this->language->get('text_attribute_group'), + 'href' => $this->url->link('catalog/attribute_group', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($attribute) { + $catalog[] = [ + 'name' => $this->language->get('text_attribute'), + 'href' => '', + 'children' => $attribute + ]; + } + + if ($this->user->hasPermission('access', 'catalog/option')) { + $catalog[] = [ + 'name' => $this->language->get('text_option'), + 'href' => $this->url->link('catalog/option', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'catalog/manufacturer')) { + $catalog[] = [ + 'name' => $this->language->get('text_manufacturer'), + 'href' => $this->url->link('catalog/manufacturer', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'catalog/download')) { + $catalog[] = [ + 'name' => $this->language->get('text_download'), + 'href' => $this->url->link('catalog/download', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'catalog/review')) { + $catalog[] = [ + 'name' => $this->language->get('text_review'), + 'href' => $this->url->link('catalog/review', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'catalog/information')) { + $catalog[] = [ + 'name' => $this->language->get('text_information'), + 'href' => $this->url->link('catalog/information', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($catalog) { + $data['menus'][] = [ + 'id' => 'menu-catalog', + 'icon' => 'fa-solid fa-tag', + 'name' => $this->language->get('text_catalog'), + 'href' => '', + 'children' => $catalog + ]; + } + + $cms = []; + + if ($this->user->hasPermission('access', 'cms/topic')) { + $cms[] = [ + 'name' => $this->language->get('text_topic'), + 'href' => $this->url->link('cms/topic', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'cms/article')) { + $cms[] = [ + 'name' => $this->language->get('text_article'), + 'href' => $this->url->link('cms/article', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'cms/comment')) { + $cms[] = [ + 'name' => $this->language->get('text_comment'), + 'href' => $this->url->link('cms/comment', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'cms/antispam')) { + $cms[] = [ + 'name' => $this->language->get('text_antispam'), + 'href' => $this->url->link('cms/antispam', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + // Still in development + //if ($cms) { + // $data['menus'][] = [ + // 'id' => 'menu-cms', + // 'icon' => 'fa-regular fa-newspaper', + // 'name' => $this->language->get('text_cms'), + // 'href' => '', + // 'children' => $cms + // ]; + //} + + // Extension + $marketplace = []; + + if ($this->user->hasPermission('access', 'marketplace/marketplace')) { + $marketplace[] = [ + 'name' => $this->language->get('text_marketplace'), + 'href' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'marketplace/installer')) { + $marketplace[] = [ + 'name' => $this->language->get('text_installer'), + 'href' => $this->url->link('marketplace/installer', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'marketplace/extension')) { + $marketplace[] = [ + 'name' => $this->language->get('text_extension'), + 'href' => $this->url->link('marketplace/extension', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'marketplace/startup')) { + $marketplace[] = [ + 'name' => $this->language->get('text_startup'), + 'href' => $this->url->link('marketplace/startup', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'marketplace/event')) { + $marketplace[] = [ + 'name' => $this->language->get('text_event'), + 'href' => $this->url->link('marketplace/event', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'marketplace/cron')) { + $marketplace[] = [ + 'name' => $this->language->get('text_cron'), + 'href' => $this->url->link('marketplace/cron', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($marketplace) { + $data['menus'][] = [ + 'id' => 'menu-extension', + 'icon' => 'fas fa-puzzle-piece', + 'name' => $this->language->get('text_extension'), + 'href' => '', + 'children' => $marketplace + ]; + } + + // Design + $design = []; + + if ($this->user->hasPermission('access', 'design/layout')) { + $design[] = [ + 'name' => $this->language->get('text_layout'), + 'href' => $this->url->link('design/layout', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'design/theme')) { + $design[] = [ + 'name' => $this->language->get('text_theme'), + 'href' => $this->url->link('design/theme', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'design/translation')) { + $design[] = [ + 'name' => $this->language->get('text_language_editor'), + 'href' => $this->url->link('design/translation', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'design/banner')) { + $design[] = [ + 'name' => $this->language->get('text_banner'), + 'href' => $this->url->link('design/banner', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + $seo = []; + + if ($this->user->hasPermission('access', 'design/seo_url')) { + $design[] = [ + 'name' => $this->language->get('text_seo_url'), + 'href' => $this->url->link('design/seo_url', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($design) { + $data['menus'][] = [ + 'id' => 'menu-design', + 'icon' => 'fas fa-desktop', + 'name' => $this->language->get('text_design'), + 'href' => '', + 'children' => $design + ]; + } + + // Sales + $sale = []; + + if ($this->user->hasPermission('access', 'sale/order')) { + $sale[] = [ + 'name' => $this->language->get('text_order'), + 'href' => $this->url->link('sale/order', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'sale/subscription')) { + $sale[] = [ + 'name' => $this->language->get('text_subscription'), + 'href' => $this->url->link('sale/subscription', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'sale/returns')) { + $sale[] = [ + 'name' => $this->language->get('text_return'), + 'href' => $this->url->link('sale/returns', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + // Voucher + $voucher = []; + + if ($this->user->hasPermission('access', 'sale/voucher')) { + $voucher[] = [ + 'name' => $this->language->get('text_voucher'), + 'href' => $this->url->link('sale/voucher', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'sale/voucher_theme')) { + $voucher[] = [ + 'name' => $this->language->get('text_voucher_theme'), + 'href' => $this->url->link('sale/voucher_theme', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($voucher) { + $sale[] = [ + 'name' => $this->language->get('text_voucher'), + 'href' => '', + 'children' => $voucher + ]; + } + + if ($sale) { + $data['menus'][] = [ + 'id' => 'menu-sale', + 'icon' => 'fas fa-shopping-cart', + 'name' => $this->language->get('text_sale'), + 'href' => '', + 'children' => $sale + ]; + } + + // Customer + $customer = []; + + if ($this->user->hasPermission('access', 'customer/customer')) { + $customer[] = [ + 'name' => $this->language->get('text_customer'), + 'href' => $this->url->link('customer/customer', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'customer/customer_group')) { + $customer[] = [ + 'name' => $this->language->get('text_customer_group'), + 'href' => $this->url->link('customer/customer_group', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'customer/customer_approval')) { + $customer[] = [ + 'name' => $this->language->get('text_customer_approval'), + 'href' => $this->url->link('customer/customer_approval', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'customer/gdpr')) { + $customer[] = [ + 'name' => $this->language->get('text_gdpr'), + 'href' => $this->url->link('customer/gdpr', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'customer/custom_field')) { + $customer[] = [ + 'name' => $this->language->get('text_custom_field'), + 'href' => $this->url->link('customer/custom_field', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($customer) { + $data['menus'][] = [ + 'id' => 'menu-customer', + 'icon' => 'fas fa-user', + 'name' => $this->language->get('text_customer'), + 'href' => '', + 'children' => $customer + ]; + } + + // Marketing + $marketing = []; + + if ($this->user->hasPermission('access', 'marketing/affiliate')) { + $marketing[] = [ + 'name' => $this->language->get('text_affiliate'), + 'href' => $this->url->link('marketing/affiliate', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'marketing/marketing')) { + $marketing[] = [ + 'name' => $this->language->get('text_marketing'), + 'href' => $this->url->link('marketing/marketing', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'marketing/coupon')) { + $marketing[] = [ + 'name' => $this->language->get('text_coupon'), + 'href' => $this->url->link('marketing/coupon', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'marketing/contact')) { + $marketing[] = [ + 'name' => $this->language->get('text_contact'), + 'href' => $this->url->link('marketing/contact', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($marketing) { + $data['menus'][] = [ + 'id' => 'menu-marketing', + 'icon' => 'fas fa-share-alt', + 'name' => $this->language->get('text_marketing'), + 'href' => '', + 'children' => $marketing + ]; + } + + // System + $system = []; + + if ($this->user->hasPermission('access', 'setting/setting')) { + $system[] = [ + 'name' => $this->language->get('text_setting'), + 'href' => $this->url->link('setting/store', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + // Users + $user = []; + + if ($this->user->hasPermission('access', 'user/user')) { + $user[] = [ + 'name' => $this->language->get('text_users'), + 'href' => $this->url->link('user/user', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'user/user_permission')) { + $user[] = [ + 'name' => $this->language->get('text_user_group'), + 'href' => $this->url->link('user/user_permission', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'user/api')) { + $user[] = [ + 'name' => $this->language->get('text_api'), + 'href' => $this->url->link('user/api', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($user) { + $system[] = [ + 'name' => $this->language->get('text_users'), + 'href' => '', + 'children' => $user + ]; + } + + // Localisation + $localisation = []; + + if ($this->user->hasPermission('access', 'localisation/location')) { + $localisation[] = [ + 'name' => $this->language->get('text_location'), + 'href' => $this->url->link('localisation/location', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'localisation/language')) { + $localisation[] = [ + 'name' => $this->language->get('text_language'), + 'href' => $this->url->link('localisation/language', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'localisation/currency')) { + $localisation[] = [ + 'name' => $this->language->get('text_currency'), + 'href' => $this->url->link('localisation/currency', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'localisation/stock_status')) { + $localisation[] = [ + 'name' => $this->language->get('text_stock_status'), + 'href' => $this->url->link('localisation/stock_status', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'localisation/order_status')) { + $localisation[] = [ + 'name' => $this->language->get('text_order_status'), + 'href' => $this->url->link('localisation/order_status', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'localisation/subscription_status')) { + $localisation[] = [ + 'name' => $this->language->get('text_subscription_status'), + 'href' => $this->url->link('localisation/subscription_status', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + // Returns + $returns = []; + + if ($this->user->hasPermission('access', 'localisation/return_status')) { + $returns[] = [ + 'name' => $this->language->get('text_return_status'), + 'href' => $this->url->link('localisation/return_status', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'localisation/return_action')) { + $returns[] = [ + 'name' => $this->language->get('text_return_action'), + 'href' => $this->url->link('localisation/return_action', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'localisation/return_reason')) { + $returns[] = [ + 'name' => $this->language->get('text_return_reason'), + 'href' => $this->url->link('localisation/return_reason', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($returns) { + $localisation[] = [ + 'name' => $this->language->get('text_return'), + 'href' => '', + 'children' => $returns + ]; + } + + if ($this->user->hasPermission('access', 'localisation/country')) { + $localisation[] = [ + 'name' => $this->language->get('text_country'), + 'href' => $this->url->link('localisation/country', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'localisation/zone')) { + $localisation[] = [ + 'name' => $this->language->get('text_zone'), + 'href' => $this->url->link('localisation/zone', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'localisation/geo_zone')) { + $localisation[] = [ + 'name' => $this->language->get('text_geo_zone'), + 'href' => $this->url->link('localisation/geo_zone', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + // Tax + $tax = []; + + if ($this->user->hasPermission('access', 'localisation/tax_class')) { + $tax[] = [ + 'name' => $this->language->get('text_tax_class'), + 'href' => $this->url->link('localisation/tax_class', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'localisation/tax_rate')) { + $tax[] = [ + 'name' => $this->language->get('text_tax_rate'), + 'href' => $this->url->link('localisation/tax_rate', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($tax) { + $localisation[] = [ + 'name' => $this->language->get('text_tax'), + 'href' => '', + 'children' => $tax + ]; + } + + if ($this->user->hasPermission('access', 'localisation/length_class')) { + $localisation[] = [ + 'name' => $this->language->get('text_length_class'), + 'href' => $this->url->link('localisation/length_class', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'localisation/weight_class')) { + $localisation[] = [ + 'name' => $this->language->get('text_weight_class'), + 'href' => $this->url->link('localisation/weight_class', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'localisation/address_format')) { + $localisation[] = [ + 'name' => $this->language->get('text_address_format'), + 'href' => $this->url->link('localisation/address_format', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($localisation) { + $system[] = [ + 'name' => $this->language->get('text_localisation'), + 'href' => '', + 'children' => $localisation + ]; + } + + // Tools + $maintenance = []; + + if ($this->user->hasPermission('access', 'tool/upgrade')) { + $maintenance[] = [ + 'name' => $this->language->get('text_upgrade'), + 'href' => $this->url->link('tool/upgrade', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'tool/backup')) { + $maintenance[] = [ + 'name' => $this->language->get('text_backup'), + 'href' => $this->url->link('tool/backup', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'tool/upload')) { + $maintenance[] = [ + 'name' => $this->language->get('text_upload'), + 'href' => $this->url->link('tool/upload', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'tool/log')) { + $maintenance[] = [ + 'name' => $this->language->get('text_log'), + 'href' => $this->url->link('tool/log', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($maintenance) { + $system[] = [ + 'name' => $this->language->get('text_maintenance'), + 'href' => '', + 'children' => $maintenance + ]; + } + + if ($system) { + $data['menus'][] = [ + 'id' => 'menu-system', + 'icon' => 'fas fa-cog', + 'name' => $this->language->get('text_system'), + 'href' => '', + 'children' => $system + ]; + } + + $report = []; + + if ($this->user->hasPermission('access', 'report/report')) { + $report[] = [ + 'name' => $this->language->get('text_reports'), + 'href' => $this->url->link('report/report', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'report/online')) { + $report[] = [ + 'name' => $this->language->get('text_online'), + 'href' => $this->url->link('report/online', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($this->user->hasPermission('access', 'report/statistics')) { + $report[] = [ + 'name' => $this->language->get('text_statistics'), + 'href' => $this->url->link('report/statistics', 'user_token=' . $this->session->data['user_token']), + 'children' => [] + ]; + } + + if ($report) { + $data['menus'][] = [ + 'id' => 'menu-report', + 'icon' => 'fas fa-chart-bar', + 'name' => $this->language->get('text_reports'), + 'href' => '', + 'children' => $report + ]; + } + + // Stats + if ($this->user->hasPermission('access', 'report/statistics')) { + $this->load->model('sale/order'); + + $order_total = (float)$this->model_sale_order->getTotalOrders(); + + $this->load->model('report/statistics'); + + $complete_total = (float)$this->model_report_statistics->getValue('order_complete'); + + if ($complete_total && $order_total) { + $data['complete_status'] = round(($complete_total / $order_total) * 100); + } else { + $data['complete_status'] = 0; + } + + $processing_total = (float)$this->model_report_statistics->getValue('order_processing'); + + if ($processing_total && $order_total) { + $data['processing_status'] = round(($processing_total / $order_total) * 100); + } else { + $data['processing_status'] = 0; + } + + $other_total = (float)$this->model_report_statistics->getValue('order_other'); + + if ($other_total && $order_total) { + $data['other_status'] = round(($other_total / $order_total) * 100); + } else { + $data['other_status'] = 0; + } + + $data['statistics_status'] = true; + } else { + $data['statistics_status'] = false; + } + + return $this->load->view('common/column_left', $data); + } else { + return ''; + } + } +} diff --git a/admininistrator/controller/common/dashboard.php b/admininistrator/controller/common/dashboard.php new file mode 100644 index 0000000..573a3e2 --- /dev/null +++ b/admininistrator/controller/common/dashboard.php @@ -0,0 +1,100 @@ +load->language('common/dashboard'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + // Dashboard Extensions + $dashboards = []; + + $this->load->model('setting/extension'); + + // Get a list of installed modules + $extensions = $this->model_setting_extension->getExtensionsByType('dashboard'); + + // Add all the modules which have multiple settings for each module + foreach ($extensions as $extension) { + if ($this->config->get('dashboard_' . $extension['code'] . '_status') && $this->user->hasPermission('access', 'extension/' . $extension['extension'] . '/dashboard/' . $extension['code'])) { + $output = $this->load->controller('extension/' . $extension['extension'] . '/dashboard/' . $extension['code'] . '.dashboard'); + + //if (!$output instanceof \Exception) { + if ($output) { + $dashboards[] = [ + 'code' => $extension['code'], + 'width' => $this->config->get('dashboard_' . $extension['code'] . '_width'), + 'sort_order' => $this->config->get('dashboard_' . $extension['code'] . '_sort_order'), + 'output' => $output + ]; + } + } + } + + $sort_order = []; + + foreach ($dashboards as $key => $value) { + $sort_order[$key] = $value['sort_order']; + } + + array_multisort($sort_order, SORT_ASC, $dashboards); + + // Split the array so the columns width is not more than 12 on each row. + $width = 0; + $column = []; + $data['rows'] = []; + + foreach ($dashboards as $dashboard) { + $column[] = $dashboard; + + $width = ($width + $dashboard['width']); + + if ($width >= 12) { + $data['rows'][] = $column; + + $width = 0; + $column = []; + } + } + + if (!empty($column)) { + $data['rows'][] = $column; + } + + if ($this->user->hasPermission('access', 'common/developer')) { + $data['developer_status'] = true; + } else { + $data['developer_status'] = false; + } + + $data['security'] = $this->load->controller('common/security'); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('common/dashboard', $data)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/common/developer.php b/admininistrator/controller/common/developer.php new file mode 100644 index 0000000..97401d7 --- /dev/null +++ b/admininistrator/controller/common/developer.php @@ -0,0 +1,130 @@ +load->language('common/developer'); + + $data['developer_sass'] = $this->config->get('developer_sass'); + + $data['user_token'] = $this->session->data['user_token']; + + $this->response->setOutput($this->load->view('common/developer', $data)); + } + + /** + * @return void + */ + public function edit(): void { + $this->load->language('common/developer'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'common/developer')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/setting'); + + $this->model_setting_setting->editSetting('developer', $this->request->post, 0); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function theme(): void { + $this->load->language('common/developer'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'common/developer')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $directories = glob(DIR_CACHE . 'template/*', GLOB_ONLYDIR); + + if ($directories) { + foreach ($directories as $directory) { + $files = glob($directory . '/*'); + + foreach ($files as $file) { + if (is_file($file)) { + unlink($file); + } + } + + if (is_dir($directory)) { + rmdir($directory); + } + } + } + + $json['success'] = sprintf($this->language->get('text_cache'), $this->language->get('text_theme')); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function sass(): void { + $this->load->language('common/developer'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'common/developer')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + // Before we delete we need to make sure there is a sass file to regenerate the css + $file = DIR_APPLICATION . 'view/stylesheet/bootstrap.css'; + + if (is_file($file) && is_file(DIR_APPLICATION . 'view/stylesheet/scss/bootstrap.scss')) { + unlink($file); + } + + $files = glob(DIR_CATALOG . 'view/theme/*/stylesheet/scss/bootstrap.scss'); + + foreach ($files as $file) { + $file = substr($file, 0, -20) . '/bootstrap.css'; + + if (is_file($file)) { + unlink($file); + } + } + + $files = glob(DIR_CATALOG . 'view/theme/*/stylesheet/stylesheet.scss'); + + foreach ($files as $file) { + $file = substr($file, 0, -16) . '/stylesheet.css'; + + if (is_file($file)) { + unlink($file); + } + } + + $json['success'] = sprintf($this->language->get('text_cache'), $this->language->get('text_sass')); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/common/filemanager.php b/admininistrator/controller/common/filemanager.php new file mode 100644 index 0000000..c12e465 --- /dev/null +++ b/admininistrator/controller/common/filemanager.php @@ -0,0 +1,485 @@ +load->language('common/filemanager'); + + $data['error_upload_size'] = sprintf($this->language->get('error_upload_size'), $this->config->get('config_file_max_size')); + + $data['config_file_max_size'] = ((int)$this->config->get('config_file_max_size') * 1024 * 1024); + + // Return the target ID for the file manager to set the value + if (isset($this->request->get['target'])) { + $data['target'] = $this->request->get['target']; + } else { + $data['target'] = ''; + } + + // Return the thumbnail for the file manager to show a thumbnail + if (isset($this->request->get['thumb'])) { + $data['thumb'] = $this->request->get['thumb']; + } else { + $data['thumb'] = ''; + } + + if (isset($this->request->get['ckeditor'])) { + $data['ckeditor'] = $this->request->get['ckeditor']; + } else { + $data['ckeditor'] = ''; + } + + $data['user_token'] = $this->session->data['user_token']; + + $this->response->setOutput($this->load->view('common/filemanager', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('common/filemanager'); + + $base = DIR_IMAGE . 'catalog/'; + + // Make sure we have the correct directory + if (isset($this->request->get['directory'])) { + $directory = $base . html_entity_decode($this->request->get['directory'], ENT_QUOTES, 'UTF-8') . '/'; + } else { + $directory = $base; + } + + if (isset($this->request->get['filter_name'])) { + $filter_name = basename(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } else { + $filter_name = ''; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $allowed = [ + '.ico', + '.jpg', + '.jpeg', + '.png', + '.gif', + '.webp', + '.JPG', + '.JPEG', + '.PNG', + '.GIF' + ]; + + $data['directories'] = []; + $data['images'] = []; + + $this->load->model('tool/image'); + + // Get directories and files + $paths = array_merge( + glob($directory . $filter_name . '*', GLOB_ONLYDIR), + glob($directory . $filter_name . '*{' . implode(',', $allowed) . '}', GLOB_BRACE) + ); + + $total = count($paths); + $limit = 16; + $start = ($page - 1) * $limit; + + if ($paths) { + // Split the array based on current page number and max number of items per page of 10 + foreach (array_slice($paths, $start, $limit) as $path) { + $path = str_replace('\\', '/', realpath($path)); + + if (substr($path, 0, strlen($path)) == $path) { + $name = basename($path); + + $url = ''; + + if (isset($this->request->get['target'])) { + $url .= '&target=' . $this->request->get['target']; + } + + if (isset($this->request->get['thumb'])) { + $url .= '&thumb=' . $this->request->get['thumb']; + } + + if (isset($this->request->get['ckeditor'])) { + $url .= '&ckeditor=' . $this->request->get['ckeditor']; + } + + if (is_dir($path)) { + $data['directories'][] = [ + 'name' => $name, + 'path' => oc_substr($path, oc_strlen($base)) . '/', + 'href' => $this->url->link('common/filemanager.list', 'user_token=' . $this->session->data['user_token'] . '&directory=' . urlencode(oc_substr($path, oc_strlen($base))) . $url) + ]; + } + + if (is_file($path) && in_array(substr($path, strrpos($path, '.')), $allowed)) { + $data['images'][] = [ + 'name' => $name, + 'path' => oc_substr($path, oc_strlen($base)), + 'href' => HTTP_CATALOG . 'image/catalog/' . oc_substr($path, oc_strlen($base)), + 'thumb' => $this->model_tool_image->resize(oc_substr($path, oc_strlen(DIR_IMAGE)), 136, 136) + ]; + } + } + } + } + + if (isset($this->request->get['directory'])) { + $data['directory'] = urldecode($this->request->get['directory']); + } else { + $data['directory'] = ''; + } + + if (isset($this->request->get['filter_name'])) { + $data['filter_name'] = $this->request->get['filter_name']; + } else { + $data['filter_name'] = ''; + } + + // Parent + $url = ''; + + if (isset($this->request->get['directory'])) { + $pos = strrpos($this->request->get['directory'], '/'); + + if ($pos) { + $url .= '&directory=' . urlencode(substr($this->request->get['directory'], 0, $pos)); + } + } + + if (isset($this->request->get['target'])) { + $url .= '&target=' . $this->request->get['target']; + } + + if (isset($this->request->get['thumb'])) { + $url .= '&thumb=' . $this->request->get['thumb']; + } + + if (isset($this->request->get['ckeditor'])) { + $url .= '&ckeditor=' . $this->request->get['ckeditor']; + } + + $data['parent'] = $this->url->link('common/filemanager.list', 'user_token=' . $this->session->data['user_token'] . $url); + + // Refresh + $url = ''; + + if (isset($this->request->get['directory'])) { + $url .= '&directory=' . urlencode(html_entity_decode($this->request->get['directory'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['target'])) { + $url .= '&target=' . $this->request->get['target']; + } + + if (isset($this->request->get['thumb'])) { + $url .= '&thumb=' . $this->request->get['thumb']; + } + + if (isset($this->request->get['ckeditor'])) { + $url .= '&ckeditor=' . $this->request->get['ckeditor']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['refresh'] = $this->url->link('common/filemanager.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $url = ''; + + if (isset($this->request->get['directory'])) { + $url .= '&directory=' . urlencode(html_entity_decode($this->request->get['directory'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['target'])) { + $url .= '&target=' . $this->request->get['target']; + } + + if (isset($this->request->get['thumb'])) { + $url .= '&thumb=' . $this->request->get['thumb']; + } + + if (isset($this->request->get['ckeditor'])) { + $url .= '&ckeditor=' . $this->request->get['ckeditor']; + } + + // Get total number of files and directories + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $total, + 'page' => $page, + 'limit' => $limit, + 'url' => $this->url->link('common/filemanager.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $this->response->setOutput($this->load->view('common/filemanager_list', $data)); + } + + /** + * @return void + */ + public function upload(): void { + $this->load->language('common/filemanager'); + + $json = []; + + $base = DIR_IMAGE . 'catalog/'; + + // Check user has permission + if (!$this->user->hasPermission('modify', 'common/filemanager')) { + $json['error'] = $this->language->get('error_permission'); + } + + // Make sure we have the correct directory + if (isset($this->request->get['directory'])) { + $directory = $base . html_entity_decode($this->request->get['directory'], ENT_QUOTES, 'UTF-8') . '/'; + } else { + $directory = $base; + } + + // Check it's a directory + if (!is_dir($directory) || substr(str_replace('\\', '/', realpath($directory)) . '/', 0, strlen($base)) != $base) { + $json['error'] = $this->language->get('error_directory'); + } + + if (!$json) { + // Check if multiple files are uploaded or just one + $files = []; + + if (!empty($this->request->files['file']['name']) && is_array($this->request->files['file']['name'])) { + foreach (array_keys($this->request->files['file']['name']) as $key) { + $files[] = [ + 'name' => $this->request->files['file']['name'][$key], + 'type' => $this->request->files['file']['type'][$key], + 'tmp_name' => $this->request->files['file']['tmp_name'][$key], + 'error' => $this->request->files['file']['error'][$key], + 'size' => $this->request->files['file']['size'][$key] + ]; + } + } + + foreach ($files as $file) { + if (is_file($file['tmp_name'])) { + // Sanitize the filename + $filename = preg_replace('[/\\?%*:|"<>]', '', basename(html_entity_decode($file['name'], ENT_QUOTES, 'UTF-8'))); + + // Validate the filename length + if ((oc_strlen($filename) < 4) || (oc_strlen($filename) > 255)) { + $json['error'] = $this->language->get('error_filename'); + } + + // Allowed file extension types + $allowed = [ + 'ico', + 'jpg', + 'jpeg', + 'png', + 'gif', + 'webp', + 'JPG', + 'JPEG', + 'PNG', + 'GIF' + ]; + + if (!in_array(substr($filename, strrpos($filename, '.') + 1), $allowed)) { + $json['error'] = $this->language->get('error_file_type'); + } + + // Allowed file mime types + $allowed = [ + 'image/x-icon', + 'image/jpeg', + 'image/pjpeg', + 'image/png', + 'image/x-png', + 'image/gif', + 'image/webp' + ]; + + if (!in_array($file['type'], $allowed)) { + $json['error'] = $this->language->get('error_file_type'); + } + + // Return any upload error + if ($file['error'] != UPLOAD_ERR_OK) { + $json['error'] = $this->language->get('error_upload_' . $file['error']); + } + } else { + $json['error'] = $this->language->get('error_upload'); + } + + if (!$json) { + move_uploaded_file($file['tmp_name'], $directory . $filename); + } + } + } + + if (!$json) { + $json['success'] = $this->language->get('text_uploaded'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function folder(): void { + $this->load->language('common/filemanager'); + + $json = []; + + $base = DIR_IMAGE . 'catalog/'; + + // Check user has permission + if (!$this->user->hasPermission('modify', 'common/filemanager')) { + $json['error'] = $this->language->get('error_permission'); + } + + // Make sure we have the correct directory + if (isset($this->request->get['directory'])) { + $directory = $base . html_entity_decode($this->request->get['directory'], ENT_QUOTES, 'UTF-8') . '/'; + } else { + $directory = $base; + } + + // Check its a directory + if (!is_dir($directory) || substr(str_replace('\\', '/', realpath($directory)) . '/', 0, strlen($base)) != $base) { + $json['error'] = $this->language->get('error_directory'); + } + + if ($this->request->server['REQUEST_METHOD'] == 'POST') { + // Sanitize the folder name + $folder = preg_replace('[/\\?%*&:|"<>]', '', basename(html_entity_decode($this->request->post['folder'], ENT_QUOTES, 'UTF-8'))); + + // Validate the filename length + if ((oc_strlen($folder) < 3) || (oc_strlen($folder) > 128)) { + $json['error'] = $this->language->get('error_folder'); + } + + // Check if directory already exists or not + if (is_dir($directory . $folder)) { + $json['error'] = $this->language->get('error_exists'); + } + } + + if (!$json) { + mkdir($directory . '/' . $folder, 0777); + + chmod($directory . '/' . $folder, 0777); + + @touch($directory . '/' . $folder . '/' . 'index.html'); + + $json['success'] = $this->language->get('text_directory'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('common/filemanager'); + + $json = []; + + $base = DIR_IMAGE . 'catalog/'; + + // Check user has permission + if (!$this->user->hasPermission('modify', 'common/filemanager')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (isset($this->request->post['path'])) { + $paths = $this->request->post['path']; + } else { + $paths = []; + } + + // Loop through each path to run validations + foreach ($paths as $path) { + // Convert any html encoded characters. + $path = html_entity_decode($path, ENT_QUOTES, 'UTF-8'); + + // Check path exists + if (($path == $base) || (substr(str_replace('\\', '/', realpath($base . $path)) . '/', 0, strlen($base)) != $base)) { + $json['error'] = $this->language->get('error_delete'); + + break; + } + } + + if (!$json) { + // Loop through each path + foreach ($paths as $path) { + $path = rtrim($base . html_entity_decode($path, ENT_QUOTES, 'UTF-8'), '/'); + + $files = []; + + // Make path into an array + $directory = [$path]; + + // While the path array is still populated keep looping through + while (count($directory) != 0) { + $next = array_shift($directory); + + if (is_dir($next)) { + foreach (glob(trim($next, '/') . '/{*,.[!.]*,..?*}', GLOB_BRACE) as $file) { + // If directory add to path array + $directory[] = $file; + } + } + + // Add the file to the files to be deleted array + $files[] = $next; + } + + // Reverse sort the file array + rsort($files); + + foreach ($files as $file) { + // If file just delete + if (is_file($file)) { + unlink($file); + } + + // If directory use the remove directory function + if (is_dir($file)) { + rmdir($file); + } + } + } + + $json['success'] = $this->language->get('text_delete'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/common/footer.php b/admininistrator/controller/common/footer.php new file mode 100644 index 0000000..6d6a00d --- /dev/null +++ b/admininistrator/controller/common/footer.php @@ -0,0 +1,25 @@ +load->language('common/footer'); + + if ($this->user->isLogged() && isset($this->request->get['user_token']) && ($this->request->get['user_token'] == $this->session->data['user_token'])) { + $data['text_version'] = sprintf($this->language->get('text_version'), VERSION); + } else { + $data['text_version'] = ''; + } + + $data['bootstrap'] = 'view/javascript/bootstrap/js/bootstrap.bundle.min.js'; + + return $this->load->view('common/footer', $data); + } +} \ No newline at end of file diff --git a/admininistrator/controller/common/forgotten.php b/admininistrator/controller/common/forgotten.php new file mode 100644 index 0000000..86f65a8 --- /dev/null +++ b/admininistrator/controller/common/forgotten.php @@ -0,0 +1,214 @@ +load->language('common/forgotten'); + + if ($this->user->isLogged() || !$this->config->get('config_mail_engine')) { + $this->response->redirect($this->url->link('common/login', '', true)); + } + + $this->document->setTitle($this->language->get('heading_title')); + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard') + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('common/forgotten') + ]; + + $data['confirm'] = $this->url->link('common/forgotten.confirm'); + $data['back'] = $this->url->link('common/login'); + + $data['header'] = $this->load->controller('common/header'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('common/forgotten', $data)); + } + + /** + * @return void + */ + public function confirm(): void { + $this->load->language('common/forgotten'); + + $json = []; + + // Stop any undefined index messages. + if ($this->user->isLogged() || !$this->config->get('config_mail_engine')) { + $json['redirect'] = $this->url->link('common/login', '', true); + } + + $keys = ['email']; + + foreach ($keys as $key) { + if (!isset($this->request->post[$key])) { + $this->request->post[$key] = ''; + } + } + + $this->load->model('user/user'); + + $user_info = $this->model_user_user->getUserByEmail($this->request->post['email']); + + if (!$user_info) { + $json['error'] = $this->language->get('error_email'); + } + + if (!$json) { + $this->model_user_user->editCode($this->request->post['email'], oc_token(40)); + + $this->session->data['success'] = $this->language->get('text_success'); + + $json['redirect'] = $this->url->link('common/login', '', true); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function reset(): void { + $this->load->language('common/forgotten'); + + if (isset($this->request->get['email'])) { + $email = (string)$this->request->get['email']; + } else { + $email = ''; + } + + if (isset($this->request->get['code'])) { + $code = (string)$this->request->get['code']; + } else { + $code = ''; + } + + if ($this->user->isLogged() || !$this->config->get('config_mail_engine')) { + $this->response->redirect($this->url->link('common/login', '', true)); + } + + $this->load->model('user/user'); + + $user_info = $this->model_user_user->getUserByEmail($email); + + if (!$user_info || !$user_info['code'] || $user_info['code'] !== $code) { + $this->model_user_user->editCode($email, ''); + + $this->session->data['error'] = $this->language->get('error_code'); + + $this->response->redirect($this->url->link('common/login', '', true)); + } + + $this->document->setTitle($this->language->get('heading_reset')); + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard') + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('common/forgotten.reset') + ]; + + $this->session->data['reset_token'] = substr(bin2hex(openssl_random_pseudo_bytes(26)), 0, 26); + + $data['reset'] = $this->url->link('common/forgotten.password', 'email=' . urlencode($email) . '&code=' . $code . '&reset_token=' . $this->session->data['reset_token']); + $data['back'] = $this->url->link('common/login'); + + $data['header'] = $this->load->controller('common/header'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('common/forgotten_reset', $data)); + } + + /** + * @return void + */ + public function password(): void { + $this->load->language('common/forgotten'); + + $json = []; + + if (isset($this->request->get['email'])) { + $email = (string)$this->request->get['email']; + } else { + $email = ''; + } + + if (isset($this->request->get['code'])) { + $code = (string)$this->request->get['code']; + } else { + $code = ''; + } + + $keys = [ + 'password', + 'confirm' + ]; + + foreach ($keys as $key) { + if (!isset($this->request->post[$key])) { + $this->request->post[$key] = ''; + } + } + + if (!isset($this->request->get['reset_token']) || !isset($this->session->data['reset_token']) || ($this->session->data['reset_token'] != $this->request->get['reset_token'])) { + $this->session->data['error'] = $this->language->get('error_session'); + + $json['redirect'] = $this->url->link('account/forgotten', true); + } + + $this->load->model('user/user'); + + $user_info = $this->model_user_user->getUserByEmail($email); + + if (!$user_info || !$user_info['code'] || $user_info['code'] !== $code) { + $this->model_user_user->editCode($email, ''); + + $this->session->data['error'] = $this->language->get('error_code'); + + $json['redirect'] = $this->url->link('common/login', '', true); + } + + if (!$json) { + if ((oc_strlen(html_entity_decode($this->request->post['password'], ENT_QUOTES, 'UTF-8')) < 4) || (oc_strlen(html_entity_decode($this->request->post['password'], ENT_QUOTES, 'UTF-8')) > 40)) { + $json['error']['password'] = $this->language->get('error_password'); + } + + if ($this->request->post['confirm'] != $this->request->post['password']) { + $json['error']['confirm'] = $this->language->get('error_confirm'); + } + } + + if (!$json) { + $this->model_user_user->editPassword($user_info['user_id'], $this->request->post['password']); + + $this->session->data['success'] = $this->language->get('text_reset'); + + unset($this->session->data['reset_token']); + + $json['redirect'] = $this->url->link('common/login', '', true); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/common/header.php b/admininistrator/controller/common/header.php new file mode 100644 index 0000000..51f8214 --- /dev/null +++ b/admininistrator/controller/common/header.php @@ -0,0 +1,117 @@ +language->get('code'); + $data['direction'] = $this->language->get('direction'); + + $data['title'] = $this->document->getTitle(); + $data['base'] = HTTP_SERVER; + $data['description'] = $this->document->getDescription(); + $data['keywords'] = $this->document->getKeywords(); + + // Hard coding css so they can be replaced via the event's system. + $data['bootstrap'] = 'view/stylesheet/bootstrap.css'; + $data['icons'] = 'view/stylesheet/fonts/fontawesome/css/all.min.css'; + $data['stylesheet'] = 'view/stylesheet/stylesheet.css'; + + // Hard coding scripts so they can be replaced via the event's system. + $data['jquery'] = 'view/javascript/jquery/jquery-3.7.1.min.js'; + + $data['links'] = $this->document->getLinks(); + $data['styles'] = $this->document->getStyles(); + $data['scripts'] = $this->document->getScripts(); + + $this->load->language('common/header'); + + if (!isset($this->request->get['user_token']) || !isset($this->session->data['user_token']) || ($this->request->get['user_token'] != $this->session->data['user_token'])) { + $data['logged'] = false; + + $data['home'] = $this->url->link('common/login'); + } else { + $data['logged'] = true; + + $data['home'] = $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']); + + $data['language'] = $this->load->controller('common/language'); + + // Notifications + $filter_data = [ + 'start' => 0, + 'limit' => 5 + ]; + + $data['notifications'] = []; + + $this->load->model('tool/notification'); + + $results = $this->model_tool_notification->getNotifications($filter_data); + + foreach ($results as $result) { + $data['notifications'][] = [ + 'title' => $result['title'], + 'href' => $this->url->link('tool/notification.info', 'user_token=' . $this->session->data['user_token'] . '¬ification_id=' . $result['notification_id']) + ]; + } + + $data['notification_all'] = $this->url->link('tool/notification', 'user_token=' . $this->session->data['user_token']); + $data['notification_total'] = $this->model_tool_notification->getTotalNotifications(['filter_status' => 0]); + + $data['profile'] = $this->url->link('user/profile', 'user_token=' . $this->session->data['user_token']); + + $this->load->model('tool/image'); + + $data['image'] = $this->model_tool_image->resize('profile.png', 45, 45); + + $this->load->model('user/user'); + + $user_info = $this->model_user_user->getUser($this->user->getId()); + + if ($user_info) { + $data['firstname'] = $user_info['firstname']; + $data['lastname'] = $user_info['lastname']; + $data['username'] = $user_info['username']; + $data['user_group'] = $user_info['user_group']; + + if (is_file(DIR_IMAGE . html_entity_decode($user_info['image'], ENT_QUOTES, 'UTF-8'))) { + $data['image'] = $this->model_tool_image->resize(html_entity_decode($user_info['image'], ENT_QUOTES, 'UTF-8'), 45, 45); + } + } else { + $data['firstname'] = ''; + $data['lastname'] = ''; + $data['user_group'] = ''; + } + + // Stores + $data['stores'] = []; + + $data['stores'][] = [ + 'name' => $this->config->get('config_name'), + 'href' => HTTP_CATALOG + ]; + + $this->load->model('setting/store'); + + $results = $this->model_setting_store->getStores(); + + foreach ($results as $result) { + $data['stores'][] = [ + 'name' => $result['name'], + 'href' => $result['url'] + ]; + } + + $data['logout'] = $this->url->link('common/logout', 'user_token=' . $this->session->data['user_token']); + } + + return $this->load->view('common/header', $data); + } +} diff --git a/admininistrator/controller/common/language.php b/admininistrator/controller/common/language.php new file mode 100644 index 0000000..437e8f3 --- /dev/null +++ b/admininistrator/controller/common/language.php @@ -0,0 +1,98 @@ +load->model('localisation/language'); + + $results = $this->model_localisation_language->getLanguages(); + + foreach ($results as $result) { + $data['languages'][] = [ + 'name' => $result['name'], + 'code' => $result['code'], + 'image' => $result['image'] + ]; + } + + if (isset($this->request->cookie['language'])) { + $data['code'] = $this->request->cookie['language']; + } else { + $data['code'] = $this->config->get('config_language'); + } + + // Redirect + $url_data = $this->request->get; + + if (isset($url_data['route'])) { + $route = $url_data['route']; + } else { + $route = 'common/dashboard'; + } + + unset($url_data['route']); + + $url = ''; + + if ($url_data) { + $url .= '&' . urldecode(http_build_query($url_data)); + } + + $data['redirect'] = $this->url->link($route, $url); + + $data['user_token'] = $this->session->data['user_token']; + + return $this->load->view('common/language', $data); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('common/language'); + + $json = []; + + if (isset($this->request->post['code'])) { + $code = $this->request->post['code']; + } else { + $code = ''; + } + + if (isset($this->request->post['redirect'])) { + $redirect = htmlspecialchars_decode($this->request->post['redirect'], ENT_COMPAT); + } else { + $redirect = ''; + } + + $this->load->model('localisation/language'); + + $language_info = $this->model_localisation_language->getLanguageByCode($code); + + if (!$language_info) { + $json['error'] = $this->language->get('error_language'); + } + + if (!$json) { + setcookie('language', $code, time() + 60 * 60 * 24 * 365 * 10); + + if ($redirect && substr($redirect, 0, strlen($this->config->get('config_url'))) == $this->config->get('config_url')) { + $json['redirect'] = $redirect; + } else { + $json['redirect'] = $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token'], true); + } + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/common/login.php b/admininistrator/controller/common/login.php new file mode 100644 index 0000000..8f99599 --- /dev/null +++ b/admininistrator/controller/common/login.php @@ -0,0 +1,137 @@ +load->language('common/login'); + + $this->document->setTitle($this->language->get('heading_title')); + + // Check to see if user is already logged + if ($this->user->isLogged() && isset($this->request->get['user_token']) && isset($this->session->data['user_token']) && ($this->request->get['user_token'] == $this->session->data['user_token'])) { + $this->response->redirect($this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token'], true)); + } + + // Check to see if user is using incorrect token + if (isset($this->request->get['user_token']) && (!isset($this->session->data['user_token']) || ($this->request->get['user_token'] != $this->session->data['user_token']))) { + $data['error_warning'] = $this->language->get('error_token'); + } elseif (isset($this->session->data['error'])) { + $data['error_warning'] = $this->session->data['error']; + + unset($this->session->data['error']); + } else { + $data['error_warning'] = ''; + } + + if (isset($this->session->data['success'])) { + $data['success'] = $this->session->data['success']; + + unset($this->session->data['success']); + } else { + $data['success'] = ''; + } + + // Create a login token to prevent brute force attacks + $this->session->data['login_token'] = oc_token(32); + + $data['login'] = $this->url->link('common/login.login', 'login_token=' . $this->session->data['login_token'], true); + + if ($this->config->get('config_mail_engine')) { + $data['forgotten'] = $this->url->link('common/forgotten'); + } else { + $data['forgotten'] = ''; + } + + if (isset($this->request->get['route']) && $this->request->get['route'] != 'common/login') { + $args = $this->request->get; + + $route = $args['route']; + + unset($args['route']); + unset($args['user_token']); + + $url = ''; + + if ($this->request->get) { + $url .= http_build_query($args); + } + + $data['redirect'] = $this->url->link($route, $url); + } else { + $data['redirect'] = ''; + } + + $data['header'] = $this->load->controller('common/header'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('common/login', $data)); + } + + /** + * @return void + */ + public function login(): void { + $this->load->language('common/login'); + + $json = []; + + // Stop any undefined index messages. + $keys = [ + 'username', + 'password', + 'redirect' + ]; + + foreach ($keys as $key) { + if (!isset($this->request->post[$key])) { + $this->request->post[$key] = ''; + } + } + + if ($this->user->isLogged() && isset($this->request->get['user_token']) && isset($this->session->data['user_token']) && ($this->request->get['user_token'] == $this->session->data['user_token'])) { + $json['redirect'] = $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token'], true); + } + + if (!isset($this->request->get['login_token']) || !isset($this->session->data['login_token']) || $this->request->get['login_token'] != $this->session->data['login_token']) { + $this->session->data['error'] = $this->language->get('error_login'); + + $json['redirect'] = $this->url->link('common/login', '', true); + } + + if (!$json && !$this->user->login($this->request->post['username'], html_entity_decode($this->request->post['password'], ENT_QUOTES, 'UTF-8'))) { + $json['error'] = $this->language->get('error_login'); + } + + if (!$json) { + $this->session->data['user_token'] = oc_token(32); + + // Remove login token so it cannot be used again. + unset($this->session->data['login_token']); + + $login_data = [ + 'ip' => $this->request->server['REMOTE_ADDR'], + 'user_agent' => $this->request->server['HTTP_USER_AGENT'] + ]; + + $this->load->model('user/user'); + + $this->model_user_user->addLogin($this->user->getId(), $login_data); + + if ($this->request->post['redirect'] && (strpos($this->request->post['redirect'], HTTP_SERVER) === 0)) { + $json['redirect'] = str_replace('&', '&', $this->request->post['redirect'] . '&user_token=' . $this->session->data['user_token']); + } else { + $json['redirect'] = $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token'], true); + } + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/common/logout.php b/admininistrator/controller/common/logout.php new file mode 100644 index 0000000..b191ce2 --- /dev/null +++ b/admininistrator/controller/common/logout.php @@ -0,0 +1,19 @@ +user->logout(); + + unset($this->session->data['user_token']); + + $this->response->redirect($this->url->link('common/login', '', true)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/common/pagination.php b/admininistrator/controller/common/pagination.php new file mode 100644 index 0000000..950c5a8 --- /dev/null +++ b/admininistrator/controller/common/pagination.php @@ -0,0 +1,106 @@ + 0) { + $page = (int)$setting['page']; + } else { + $page = 1; + } + + if (isset($setting['limit']) && (int)$setting['limit']) { + $limit = (int)$setting['limit']; + } else { + $limit = 10; + } + + if (isset($setting['url'])) { + $url = str_replace('%7Bpage%7D', '{page}', (string)$setting['url']); + } else { + $url = ''; + } + + $num_links = 8; + $num_pages = ceil($total / $limit); + + if ($url && $page > 1 && $num_pages < $page) { + $back = true; + } else { + $back = false; + } + + $data['page'] = $page; + + if ($page > 1) { + $data['first'] = str_replace(['&page={page}', '?page={page}', '&page={page}'], '', $url); + + if ($page - 1 === 1) { + $data['prev'] = str_replace(['&page={page}', '?page={page}', '&page={page}'], '', $url); + } else { + $data['prev'] = str_replace('{page}', $page - 1, $url); + } + } else { + $data['first'] = ''; + $data['prev'] = ''; + } + + $data['links'] = []; + + if ($num_pages > 1) { + if ($num_pages <= $num_links) { + $start = 1; + $end = $num_pages; + } else { + $start = $page - floor($num_links / 2); + $end = $page + floor($num_links / 2); + + if ($start < 1) { + $end += abs($start) + 1; + $start = 1; + } + + if ($end > $num_pages) { + $start -= ($end - $num_pages); + $end = $num_pages; + } + } + + for ($i = $start; $i <= $end; $i++) { + $data['links'][] = [ + 'page' => $i, + 'href' => str_replace('{page}', $i, $url) + ]; + } + } + + if ($num_pages > $page) { + $data['next'] = str_replace('{page}', $page + 1, $url); + $data['last'] = str_replace('{page}', $num_pages, $url); + } else { + $data['next'] = ''; + $data['last'] = ''; + } + + if ($num_pages > 1 || $back) { + return $this->load->view('common/pagination', $data); + } else { + return ''; + } + } +} diff --git a/admininistrator/controller/common/security.php b/admininistrator/controller/common/security.php new file mode 100644 index 0000000..c8ae0bb --- /dev/null +++ b/admininistrator/controller/common/security.php @@ -0,0 +1,455 @@ +load->language('common/security'); + + // Check install directory exists + if (is_dir(DIR_OPENCART . 'install/')) { + $data['install'] = DIR_OPENCART . 'install/'; + } else { + $data['install'] = ''; + } + + // Check storage directory exists + if (DIR_STORAGE == DIR_SYSTEM . 'storage/') { + // Check install directory exists + $data['storage'] = DIR_STORAGE; + + $data['document_root'] = str_replace('\\', '/', realpath($this->request->server['DOCUMENT_ROOT'] . '/../')) . '/'; + + $path = ''; + + $data['paths'] = []; + + $parts = explode('/', rtrim($data['document_root'], '/')); + + foreach ($parts as $part) { + $path .= $part . '/'; + + $data['paths'][] = $path; + } + + rsort($data['paths']); + } else { + $data['storage'] = ''; + } + + // Check admin directory ia renamed + if (DIR_APPLICATION == DIR_OPENCART . 'admin/') { + $data['admin'] = 'admin'; + } else { + $data['admin'] = ''; + } + + $data['user_token'] = $this->session->data['user_token']; + + if ($data['install'] || $data['storage'] || $data['admin']) { + return $this->load->view('common/security', $data); + } else { + return ''; + } + } + + /** + * @return void + */ + public function install(): void { + $this->load->language('common/security'); + + $json = []; + + if ($this->user->hasPermission('modify', 'common/security')) { + if (!is_dir(DIR_OPENCART . 'install/')) { + $json['error'] = $this->language->get('error_install'); + } + } else { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $files = []; + + $path = DIR_OPENCART . 'install/'; + + // Make path into an array + $directory = [$path]; + + // While the path array is still populated keep looping through + while (count($directory) != 0) { + $next = array_shift($directory); + + if (is_dir($next)) { + foreach (glob(rtrim($next, '/') . '/{*,.[!.]*,..?*}', GLOB_BRACE) as $file) { + // If directory add to path array + if (is_dir($file)) { + $directory[] = $file; + } + + // Add the file to the files to be deleted array + $files[] = $file; + } + } + } + + rsort($files); + + foreach ($files as $file) { + if (is_file($file)) { + unlink($file); + } elseif (is_dir($file)) { + rmdir($file); + } + } + + rmdir($path); + + $json['success'] = $this->language->get('text_install_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function storage(): void { + $this->load->language('common/security'); + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + if (isset($this->request->get['name'])) { + $name = preg_replace('[^a-zA-z0-9_]', '', basename(html_entity_decode(trim($this->request->get['name']), ENT_QUOTES, 'UTF-8'))); + } else { + $name = ''; + } + + if (isset($this->request->get['path'])) { + $path = preg_replace('[^a-zA-z0-9_\:\/]', '', html_entity_decode(trim($this->request->get['path']), ENT_QUOTES, 'UTF-8')); + } else { + $path = ''; + } + + $json = []; + + if ($this->user->hasPermission('modify', 'common/security')) { + $base_old = DIR_STORAGE; + $base_new = $path . $name . '/'; + + if (!is_dir($base_old)) { + $json['error'] = $this->language->get('error_storage'); + } + + $root = str_replace('\\', '/', realpath($this->request->server['DOCUMENT_ROOT'] . '/../')); + + if ((substr($base_new, 0, strlen($root)) != $root) || ($root == $base_new)) { + $json['error'] = $this->language->get('error_storage'); + } + + if (is_dir($base_new) && $page < 2) { + $json['error'] = $this->language->get('error_storage_exists'); + } + + if (!is_writable(DIR_OPENCART . 'config.php') || !is_writable(DIR_APPLICATION . 'config.php')) { + $json['error'] = $this->language->get('error_writable'); + } + } else { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $files = []; + + // Make path into an array + $directory = [$base_old]; + + // While the path array is still populated keep looping through + while (count($directory) != 0) { + $next = array_shift($directory); + + foreach (glob(rtrim($next, '/') . '/{*,.[!.]*,..?*}', GLOB_BRACE) as $file) { + // If directory add to path array + if (is_dir($file)) { + $directory[] = $file; + } + + // Add the file to the files to be deleted array + $files[] = $file; + } + } + + // Create the new storage folder + if (!is_dir($base_new)) { + mkdir($base_new, 0777); + } + + // Copy the + $total = count($files); + $limit = 200; + + $start = ($page - 1) * $limit; + $end = $start > ($total - $limit) ? $total : ($start + $limit); + + for ($i = $start; $i < $end; $i++) { + $destination = substr($files[$i], strlen($base_old)); + + if (is_dir($base_old . $destination) && !is_dir($base_new . $destination)) { + mkdir($base_new . $destination, 0777); + } + + if (is_file($base_old . $destination) && !is_file($base_new . $destination)) { + copy($base_old . $destination, $base_new . $destination); + } + } + + if ($end < $total) { + $json['next'] = $this->url->link('common/security.storage', '&user_token=' . $this->session->data['user_token'] . '&name=' . $name . '&path=' . $path . '&page=' . ($page + 1), true); + } else { + // Start deleting old storage location files. + rsort($files); + + foreach ($files as $file) { + // If file just delete + if (is_file($file)) { + unlink($file); + } + + // If directory use the remove directory function + if (is_dir($file)) { + rmdir($file); + } + } + + rmdir($base_old); + + // Modify the config files + $files = [ + DIR_APPLICATION . 'config.php', + DIR_OPENCART . 'config.php' + ]; + + foreach ($files as $file) { + $output = ''; + + $lines = file($file); + + foreach ($lines as $line_id => $line) { + if (strpos($line, 'define(\'DIR_STORAGE') !== false) { + $output .= 'define(\'DIR_STORAGE\', \'' . $base_new . '\');' . "\n"; + } else { + $output .= $line; + } + } + + $file = fopen($file, 'w'); + + fwrite($file, $output); + + fclose($file); + } + + $json['success'] = $this->language->get('text_storage_success'); + } + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function admin(): void { + $this->load->language('common/security'); + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + if (isset($this->request->get['name'])) { + $name = preg_replace('[^a-zA-z0-9]', '', basename(html_entity_decode(trim((string)$this->request->get['name']), ENT_QUOTES, 'UTF-8'))); + } else { + $name = 'admin'; + } + + $json = []; + + if ($this->user->hasPermission('modify', 'common/security')) { + $base_old = DIR_OPENCART . 'admin/'; + $base_new = DIR_OPENCART . $name . '/'; + + if (!is_dir($base_old)) { + $json['error'] = $this->language->get('error_admin'); + } + + if (is_dir($base_new) && $page < 2) { + $json['error'] = $this->language->get('error_admin_exists'); + } + + if ($name == 'admin') { + $json['error'] = $this->language->get('error_admin_name'); + } + + if (!is_writable(DIR_OPENCART . 'config.php') || !is_writable(DIR_APPLICATION . 'config.php')) { + $json['error'] = $this->language->get('error_writable'); + } + } else { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + // 1. // 1. We need to copy the files, as rename cannot be used on any directory, the executing script is running under + $files = []; + + // Make path into an array + $directory = [$base_old]; + + // While the path array is still populated keep looping through + while (count($directory) != 0) { + $next = array_shift($directory); + + foreach (glob(rtrim($next, '/') . '/{*,.[!.]*,..?*}', GLOB_BRACE) as $file) { + // If directory add to path array + if (is_dir($file)) { + $directory[] = $file; + } + + // Add the file to the files to be deleted array + $files[] = $file; + } + } + + // 2. Create the new admin folder name + if (!is_dir($base_new)) { + mkdir($base_new, 0777); + } + + // 3. split the file copies into chunks. + $total = count($files); + $limit = 200; + + $start = ($page - 1) * $limit; + $end = $start > ($total - $limit) ? $total : ($start + $limit); + + // 4. Copy the files across + foreach (array_slice($files, $start, $end) as $file) { + $destination = substr($file, strlen($base_old)); + + if (is_dir($base_old . $destination) && !is_dir($base_new . $destination)) { + mkdir($base_new . $destination, 0777); + } + + if (is_file($base_old . $destination) && !is_file($base_new . $destination)) { + copy($base_old . $destination, $base_new . $destination); + } + } + + if (($page * $limit) <= $total) { + $json['next'] = $this->url->link('common/security.admin', '&user_token=' . $this->session->data['user_token'] . '&name=' . $name . '&page=' . ($page + 1), true); + } else { + // Update the old config files + $file = $base_new . 'config.php'; + + $output = ''; + + $lines = file($file); + + foreach ($lines as $line_id => $line) { + $status = true; + + if (strpos($line, 'define(\'HTTP_SERVER') !== false) { + $output .= 'define(\'HTTP_SERVER\', \'' . substr(HTTP_SERVER, 0, strrpos(HTTP_SERVER, '/admin/')) . '/' . $name . '/\');' . "\n"; + + $status = false; + } + + if (strpos($line, 'define(\'DIR_APPLICATION') !== false) { + $output .= 'define(\'DIR_APPLICATION\', DIR_OPENCART . \'' . $name . '/\');' . "\n"; + + $status = false; + } + + if ($status) { + $output .= $line; + } + } + + $file = fopen($file, 'w'); + + fwrite($file, $output); + + fclose($file); + + // 6. redirect to the new admin + $json['redirect'] = str_replace('&', '&', substr(HTTP_SERVER, 0, -6) . $name . '/index.php?route=common/login'); + } + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * + */ + public function __destruct() { + // Remove old admin if exists + $path = DIR_OPENCART . 'admin/'; + + if (is_dir($path) && DIR_APPLICATION != $path) { + // 1. We need to copy the files, as rename cannot be used on any directory, the executing script is running under + $files = []; + + // Make path into an array + $directory = [$path]; + + // While the path array is still populated keep looping through + while (count($directory) != 0) { + $next = array_shift($directory); + + foreach (glob(rtrim($next, '/') . '/{*,.[!.]*,..?*}', GLOB_BRACE) as $file) { + // If directory add to path array + if (is_dir($file)) { + $directory[] = $file; + } + + // Add the file to the files to be deleted array + $files[] = $file; + } + } + + // 4. reverse file order + rsort($files); + + // 5. Delete the old admin directory + foreach ($files as $file) { + // If file just delete + if (is_file($file)) { + unlink($file); + } + + // If directory use the remove directory function + if (is_dir($file)) { + rmdir($file); + } + } + + rmdir($path); + } + } +} diff --git a/admininistrator/controller/customer/custom_field.php b/admininistrator/controller/customer/custom_field.php new file mode 100644 index 0000000..4d62ab2 --- /dev/null +++ b/admininistrator/controller/customer/custom_field.php @@ -0,0 +1,438 @@ +load->language('customer/custom_field'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('customer/custom_field', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('customer/custom_field.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('customer/custom_field.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('customer/custom_field', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('customer/custom_field'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'cfd.name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('customer/custom_field.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['custom_fields'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('customer/custom_field'); + + $custom_field_total = $this->model_customer_custom_field->getTotalCustomFields(); + + $results = $this->model_customer_custom_field->getCustomFields($filter_data); + + foreach ($results as $result) { + $type = ''; + + switch ($result['type']) { + case 'select': + $type = $this->language->get('text_select'); + break; + case 'radio': + $type = $this->language->get('text_radio'); + break; + case 'checkbox': + $type = $this->language->get('text_checkbox'); + break; + case 'input': + $type = $this->language->get('text_input'); + break; + case 'text': + $type = $this->language->get('text_text'); + break; + case 'textarea': + $type = $this->language->get('text_textarea'); + break; + case 'file': + $type = $this->language->get('text_file'); + break; + case 'date': + $type = $this->language->get('text_date'); + break; + case 'datetime': + $type = $this->language->get('text_datetime'); + break; + case 'time': + $type = $this->language->get('text_time'); + break; + } + + $data['custom_fields'][] = [ + 'custom_field_id' => $result['custom_field_id'], + 'name' => $result['name'], + 'location' => $this->language->get('text_' . $result['location']), + 'type' => $type, + 'status' => $result['status'], + 'sort_order' => $result['sort_order'], + 'edit' => $this->url->link('customer/custom_field.form', 'user_token=' . $this->session->data['user_token'] . '&custom_field_id=' . $result['custom_field_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('customer/custom_field.list', 'user_token=' . $this->session->data['user_token'] . '&sort=cfd.name' . $url); + $data['sort_location'] = $this->url->link('customer/custom_field.list', 'user_token=' . $this->session->data['user_token'] . '&sort=cf.location' . $url); + $data['sort_type'] = $this->url->link('customer/custom_field.list', 'user_token=' . $this->session->data['user_token'] . '&sort=cf.type' . $url); + $data['sort_status'] = $this->url->link('customer/custom_field.list', 'user_token=' . $this->session->data['user_token'] . '&sort=cf.status' . $url); + $data['sort_sort_order'] = $this->url->link('customer/custom_field.list', 'user_token=' . $this->session->data['user_token'] . '&sort=cf.sort_order' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $custom_field_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('customer/custom_field.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($custom_field_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($custom_field_total - $this->config->get('config_pagination_admin'))) ? $custom_field_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $custom_field_total, ceil($custom_field_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('customer/custom_field_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('customer/custom_field'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['custom_field_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('customer/custom_field', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('customer/custom_field.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('customer/custom_field', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['custom_field_id'])) { + $this->load->model('customer/custom_field'); + + $custom_field_info = $this->model_customer_custom_field->getCustomField($this->request->get['custom_field_id']); + } + + if (isset($this->request->get['custom_field_id'])) { + $data['custom_field_id'] = (int)$this->request->get['custom_field_id']; + } else { + $data['custom_field_id'] = 0; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (isset($this->request->get['custom_field_id'])) { + $data['custom_field_description'] = $this->model_customer_custom_field->getDescriptions($this->request->get['custom_field_id']); + } else { + $data['custom_field_description'] = []; + } + + if (!empty($custom_field_info)) { + $data['location'] = $custom_field_info['location']; + } else { + $data['location'] = ''; + } + + if (!empty($custom_field_info)) { + $data['type'] = $custom_field_info['type']; + } else { + $data['type'] = ''; + } + + if (!empty($custom_field_info)) { + $data['value'] = $custom_field_info['value']; + } else { + $data['value'] = ''; + } + + if (!empty($custom_field_info)) { + $data['validation'] = $custom_field_info['validation']; + } else { + $data['validation'] = ''; + } + + if (!empty($custom_field_info)) { + $data['status'] = $custom_field_info['status']; + } else { + $data['status'] = ''; + } + + if (!empty($custom_field_info)) { + $data['sort_order'] = $custom_field_info['sort_order']; + } else { + $data['sort_order'] = ''; + } + + if (isset($this->request->get['custom_field_id'])) { + $custom_field_values = $this->model_customer_custom_field->getValueDescriptions($this->request->get['custom_field_id']); + } else { + $custom_field_values = []; + } + + $data['custom_field_values'] = []; + + foreach ($custom_field_values as $custom_field_value) { + $data['custom_field_values'][] = [ + 'custom_field_value_id' => $custom_field_value['custom_field_value_id'], + 'custom_field_value_description' => $custom_field_value['custom_field_value_description'], + 'sort_order' => $custom_field_value['sort_order'] + ]; + } + + if (isset($this->request->get['custom_field_id'])) { + $custom_field_customer_groups = $this->model_customer_custom_field->getCustomerGroups($this->request->get['custom_field_id']); + } else { + $custom_field_customer_groups = []; + } + + $data['custom_field_customer_group'] = []; + + foreach ($custom_field_customer_groups as $custom_field_customer_group) { + if (isset($custom_field_customer_group['customer_group_id'])) { + $data['custom_field_customer_group'][] = $custom_field_customer_group['customer_group_id']; + } + } + + $this->load->model('customer/customer_group'); + + $data['customer_groups'] = $this->model_customer_customer_group->getCustomerGroups(); + + $data['custom_field_required'] = []; + + foreach ($custom_field_customer_groups as $custom_field_customer_group) { + if (isset($custom_field_customer_group['required']) && $custom_field_customer_group['required'] && isset($custom_field_customer_group['customer_group_id'])) { + $data['custom_field_required'][] = $custom_field_customer_group['customer_group_id']; + } + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('customer/custom_field_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('customer/custom_field'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'customer/custom_field')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + foreach ($this->request->post['custom_field_description'] as $language_id => $value) { + if ((oc_strlen($value['name']) < 1) || (oc_strlen($value['name']) > 128)) { + $json['error']['name_' . $language_id] = $this->language->get('error_name'); + } + } + + if (($this->request->post['type'] == 'select' || $this->request->post['type'] == 'radio' || $this->request->post['type'] == 'checkbox')) { + if (!isset($this->request->post['custom_field_value'])) { + $json['error']['warning'] = $this->language->get('error_type'); + } + + if (isset($this->request->post['custom_field_value'])) { + foreach ($this->request->post['custom_field_value'] as $custom_field_value_id => $custom_field_value) { + foreach ($custom_field_value['custom_field_value_description'] as $language_id => $custom_field_value_description) { + if ((oc_strlen($custom_field_value_description['name']) < 1) || (oc_strlen($custom_field_value_description['name']) > 128)) { + $json['error']['custom_field_value_' . $custom_field_value_id . '_' . $language_id] = $this->language->get('error_custom_value'); + } + } + } + } + } + + if ($this->request->post['type'] == 'text' && $this->request->post['validation'] && @preg_match(html_entity_decode($this->request->post['validation'], ENT_QUOTES, 'UTF-8'), null) === false) { + $json['error']['validation'] = $this->language->get('error_validation'); + } + + if (!$json) { + $this->load->model('customer/custom_field'); + + if (!$this->request->post['custom_field_id']) { + $json['custom_field_id'] = $this->model_customer_custom_field->addCustomField($this->request->post); + } else { + $this->model_customer_custom_field->editCustomField($this->request->post['custom_field_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('customer/custom_field'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'customer/custom_field')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('customer/custom_field'); + + foreach ($selected as $custom_field_id) { + $this->model_customer_custom_field->deleteCustomField($custom_field_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/customer/customer.php b/admininistrator/controller/customer/customer.php new file mode 100644 index 0000000..3dd096b --- /dev/null +++ b/admininistrator/controller/customer/customer.php @@ -0,0 +1,1429 @@ +load->language('customer/customer'); + + $this->document->setTitle($this->language->get('heading_title')); + + if (isset($this->request->get['filter_name'])) { + $filter_name = $this->request->get['filter_name']; + } else { + $filter_name = ''; + } + + if (isset($this->request->get['filter_email'])) { + $filter_email = $this->request->get['filter_email']; + } else { + $filter_email = ''; + } + + if (isset($this->request->get['filter_customer_group_id'])) { + $filter_customer_group_id = (int)$this->request->get['filter_customer_group_id']; + } else { + $filter_customer_group_id = ''; + } + + if (isset($this->request->get['filter_status'])) { + $filter_status = $this->request->get['filter_status']; + } else { + $filter_status = ''; + } + + if (isset($this->request->get['filter_ip'])) { + $filter_ip = $this->request->get['filter_ip']; + } else { + $filter_ip = ''; + } + + if (isset($this->request->get['filter_date_from'])) { + $filter_date_from = $this->request->get['filter_date_from']; + } else { + $filter_date_from = ''; + } + + if (isset($this->request->get['filter_date_to'])) { + $filter_date_to = $this->request->get['filter_date_to']; + } else { + $filter_date_to = ''; + } + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_email'])) { + $url .= '&filter_email=' . urlencode(html_entity_decode($this->request->get['filter_email'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_customer_group_id'])) { + $url .= '&filter_customer_group_id=' . $this->request->get['filter_customer_group_id']; + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['filter_ip'])) { + $url .= '&filter_ip=' . $this->request->get['filter_ip']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('customer/customer', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('customer/customer.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('customer/customer.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $this->load->model('customer/customer_group'); + + $data['customer_groups'] = $this->model_customer_customer_group->getCustomerGroups(); + + $data['filter_name'] = $filter_name; + $data['filter_email'] = $filter_email; + $data['filter_customer_group_id'] = $filter_customer_group_id; + $data['filter_status'] = $filter_status; + $data['filter_ip'] = $filter_ip; + $data['filter_date_from'] = $filter_date_from; + $data['filter_date_to'] = $filter_date_to; + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('customer/customer', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('customer/customer'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['filter_name'])) { + $filter_name = $this->request->get['filter_name']; + } else { + $filter_name = ''; + } + + if (isset($this->request->get['filter_email'])) { + $filter_email = $this->request->get['filter_email']; + } else { + $filter_email = ''; + } + + if (isset($this->request->get['filter_customer_group_id'])) { + $filter_customer_group_id = (int)$this->request->get['filter_customer_group_id']; + } else { + $filter_customer_group_id = ''; + } + + if (isset($this->request->get['filter_status'])) { + $filter_status = (bool)$this->request->get['filter_status']; + } else { + $filter_status = ''; + } + + if (isset($this->request->get['filter_ip'])) { + $filter_ip = (string)$this->request->get['filter_ip']; + } else { + $filter_ip = ''; + } + + if (isset($this->request->get['filter_date_from'])) { + $filter_date_from = (string)$this->request->get['filter_date_from']; + } else { + $filter_date_from = ''; + } + + if (isset($this->request->get['filter_date_to'])) { + $filter_date_to = (string)$this->request->get['filter_date_to']; + } else { + $filter_date_to = ''; + } + + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_email'])) { + $url .= '&filter_email=' . urlencode(html_entity_decode($this->request->get['filter_email'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_customer_group_id'])) { + $url .= '&filter_customer_group_id=' . $this->request->get['filter_customer_group_id']; + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['filter_ip'])) { + $url .= '&filter_ip=' . $this->request->get['filter_ip']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('customer/customer.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $this->load->model('setting/store'); + + $stores = $this->model_setting_store->getStores(); + + $data['customers'] = []; + + $filter_data = [ + 'filter_name' => $filter_name, + 'filter_email' => $filter_email, + 'filter_customer_group_id' => $filter_customer_group_id, + 'filter_status' => $filter_status, + 'filter_ip' => $filter_ip, + 'filter_date_from' => $filter_date_from, + 'filter_date_to' => $filter_date_to, + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('customer/customer'); + + $customer_total = $this->model_customer_customer->getTotalCustomers($filter_data); + + $results = $this->model_customer_customer->getCustomers($filter_data); + + foreach ($results as $result) { + $login_info = $this->model_customer_customer->getTotalLoginAttempts($result['email']); + + if ($login_info && $login_info['total'] >= $this->config->get('config_login_attempts')) { + $unlock = $this->url->link('customer/customer.unlock', 'user_token=' . $this->session->data['user_token'] . '&email=' . $result['email'] . $url); + } else { + $unlock = ''; + } + + $store_data = []; + + $store_data[] = [ + 'store_id' => 0, + 'name' => $this->config->get('config_name'), + 'href' => $this->url->link('customer/customer.login', 'user_token=' . $this->session->data['user_token'] . '&customer_id=' . $result['customer_id'] . '&store_id=0') + ]; + + foreach ($stores as $store) { + $store_data[] = [ + 'store_id' => $store['store_id'], + 'name' => $store['name'], + 'href' => $this->url->link('customer/customer.login', 'user_token=' . $this->session->data['user_token'] . '&customer_id=' . $result['customer_id'] . '&store_id=' . $store['store_id']) + ]; + } + + $data['customers'][] = [ + 'customer_id' => $result['customer_id'], + 'name' => $result['name'], + 'email' => $result['email'], + 'store_id' => $result['store_id'], + 'customer_group' => $result['customer_group'], + 'status' => $result['status'], + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])), + 'unlock' => $unlock, + 'store' => $store_data, + 'edit' => $this->url->link('customer/customer.form', 'user_token=' . $this->session->data['user_token'] . '&customer_id=' . $result['customer_id'] . $url) + ]; + } + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_email'])) { + $url .= '&filter_email=' . urlencode(html_entity_decode($this->request->get['filter_email'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_customer_group_id'])) { + $url .= '&filter_customer_group_id=' . $this->request->get['filter_customer_group_id']; + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['filter_ip'])) { + $url .= '&filter_ip=' . $this->request->get['filter_ip']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('customer/customer.list', 'user_token=' . $this->session->data['user_token'] . '&sort=name' . $url); + $data['sort_email'] = $this->url->link('customer/customer.list', 'user_token=' . $this->session->data['user_token'] . '&sort=c.email' . $url); + $data['sort_customer_group'] = $this->url->link('customer/customer.list', 'user_token=' . $this->session->data['user_token'] . '&sort=customer_group' . $url); + $data['sort_status'] = $this->url->link('customer/customer.list', 'user_token=' . $this->session->data['user_token'] . '&sort=c.status' . $url); + $data['sort_date_added'] = $this->url->link('customer/customer.list', 'user_token=' . $this->session->data['user_token'] . '&sort=c.date_added' . $url); + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_email'])) { + $url .= '&filter_email=' . urlencode(html_entity_decode($this->request->get['filter_email'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_customer_group_id'])) { + $url .= '&filter_customer_group_id=' . $this->request->get['filter_customer_group_id']; + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['filter_ip'])) { + $url .= '&filter_ip=' . $this->request->get['filter_ip']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $customer_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('customer/customer.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($customer_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($customer_total - $this->config->get('config_pagination_admin'))) ? $customer_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $customer_total, ceil($customer_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('customer/customer_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('customer/customer'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['customer_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $data['error_upload_size'] = sprintf($this->language->get('error_upload_size'), $this->config->get('config_file_max_size')); + + $data['config_file_max_size'] = ((int)$this->config->get('config_file_max_size') * 1024 * 1024); + $data['config_telephone_required'] = $this->config->get('config_telephone_required'); + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_email'])) { + $url .= '&filter_email=' . urlencode(html_entity_decode($this->request->get['filter_email'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_customer_group_id'])) { + $url .= '&filter_customer_group_id=' . $this->request->get['filter_customer_group_id']; + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['filter_ip'])) { + $url .= '&filter_ip=' . $this->request->get['filter_ip']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('customer/customer', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('customer/customer.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('customer/customer', 'user_token=' . $this->session->data['user_token'] . $url); + $data['upload'] = $this->url->link('tool/upload.upload', 'user_token=' . $this->session->data['user_token']); + + if (isset($this->request->get['customer_id'])) { + $data['orders'] = $this->url->link('sale/order', 'user_token=' . $this->session->data['user_token'] . '&filter_customer_id=' . $this->request->get['customer_id']); + } else { + $data['orders'] = ''; + } + + if (isset($this->request->get['customer_id'])) { + $this->load->model('customer/customer'); + + $customer_info = $this->model_customer_customer->getCustomer((int)$this->request->get['customer_id']); + } + + if (isset($this->request->get['customer_id'])) { + $data['customer_id'] = (int)$this->request->get['customer_id']; + } else { + $data['customer_id'] = 0; + } + + $data['stores'] = []; + + $data['stores'][] = [ + 'store_id' => 0, + 'name' => $this->language->get('text_default') + ]; + + $this->load->model('setting/store'); + + $stores = $this->model_setting_store->getStores(); + + foreach ($stores as $store) { + $data['stores'][] = [ + 'store_id' => $store['store_id'], + 'name' => $store['name'] + ]; + } + + if (!empty($customer_info)) { + $data['store_id'] = $customer_info['store_id']; + } else { + $data['store_id'] = [0]; + } + + $this->load->model('customer/customer_group'); + + $data['customer_groups'] = $this->model_customer_customer_group->getCustomerGroups(); + + if (!empty($customer_info)) { + $data['customer_group_id'] = $customer_info['customer_group_id']; + } else { + $data['customer_group_id'] = $this->config->get('config_customer_group_id'); + } + + if (!empty($customer_info)) { + $data['firstname'] = $customer_info['firstname']; + } else { + $data['firstname'] = ''; + } + + if (!empty($customer_info)) { + $data['lastname'] = $customer_info['lastname']; + } else { + $data['lastname'] = ''; + } + + if (!empty($customer_info)) { + $data['email'] = $customer_info['email']; + } else { + $data['email'] = ''; + } + + if (!empty($customer_info)) { + $data['telephone'] = $customer_info['telephone']; + } else { + $data['telephone'] = ''; + } + + // Custom Fields + $this->load->model('customer/custom_field'); + + $data['custom_fields'] = []; + + $filter_data = [ + 'sort' => 'cf.sort_order', + 'order' => 'ASC' + ]; + + $custom_fields = $this->model_customer_custom_field->getCustomFields($filter_data); + + foreach ($custom_fields as $custom_field) { + if ($custom_field['status']) { + $data['custom_fields'][] = [ + 'custom_field_id' => $custom_field['custom_field_id'], + 'custom_field_value' => $this->model_customer_custom_field->getValues($custom_field['custom_field_id']), + 'name' => $custom_field['name'], + 'value' => $custom_field['value'], + 'type' => $custom_field['type'], + 'location' => $custom_field['location'], + 'sort_order' => $custom_field['sort_order'] + ]; + } + } + + if (!empty($customer_info)) { + $data['account_custom_field'] = json_decode($customer_info['custom_field'], true); + } else { + $data['account_custom_field'] = []; + } + + $data['password'] = ''; + $data['confirm'] = ''; + + if (!empty($customer_info)) { + $data['newsletter'] = $customer_info['newsletter']; + } else { + $data['newsletter'] = 0; + } + + if (!empty($customer_info)) { + $data['status'] = $customer_info['status']; + } else { + $data['status'] = 1; + } + + if (!empty($customer_info)) { + $data['safe'] = $customer_info['safe']; + } else { + $data['safe'] = 0; + } + + $this->load->model('localisation/country'); + + $data['countries'] = $this->model_localisation_country->getCountries(); + + if (isset($this->request->get['customer_id'])) { + $data['addresses'] = $this->model_customer_customer->getAddresses((int)$this->request->get['customer_id']); + } else { + $data['addresses'] = []; + } + + $data['history'] = $this->getHistory(); + $data['transaction'] = $this->getTransaction(); + $data['reward'] = $this->getReward(); + $data['ip'] = $this->getIp(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('customer/customer_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('customer/customer'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'customer/customer')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if ((oc_strlen($this->request->post['firstname']) < 1) || (oc_strlen($this->request->post['firstname']) > 32)) { + $json['error']['firstname'] = $this->language->get('error_firstname'); + } + + if ((oc_strlen($this->request->post['lastname']) < 1) || (oc_strlen($this->request->post['lastname']) > 32)) { + $json['error']['lastname'] = $this->language->get('error_lastname'); + } + + if ((oc_strlen($this->request->post['email']) > 96) || !filter_var($this->request->post['email'], FILTER_VALIDATE_EMAIL)) { + $json['error']['email'] = $this->language->get('error_email'); + } + + $this->load->model('customer/customer'); + + $customer_info = $this->model_customer_customer->getCustomerByEmail($this->request->post['email']); + + if (!$this->request->post['customer_id']) { + if ($customer_info) { + $json['error']['warning'] = $this->language->get('error_exists'); + } + } else { + if ($customer_info && ($this->request->post['customer_id'] != $customer_info['customer_id'])) { + $json['error']['warning'] = $this->language->get('error_exists'); + } + } + + if ($this->config->get('config_telephone_required') && (oc_strlen($this->request->post['telephone']) < 3) || (oc_strlen($this->request->post['telephone']) > 32)) { + $json['error']['telephone'] = $this->language->get('error_telephone'); + } + + // Custom field validation + $this->load->model('customer/custom_field'); + + $custom_fields = $this->model_customer_custom_field->getCustomFields(['filter_customer_group_id' => $this->request->post['customer_group_id']]); + + foreach ($custom_fields as $custom_field) { + if ($custom_field['status']) { + if (($custom_field['location'] == 'account') && $custom_field['required'] && empty($this->request->post['custom_field'][$custom_field['custom_field_id']])) { + $json['error']['custom_field_' . $custom_field['custom_field_id']] = sprintf($this->language->get('error_custom_field'), $custom_field['name']); + } elseif (($custom_field['location'] == 'account') && ($custom_field['type'] == 'text') && !empty($custom_field['validation']) && !preg_match(html_entity_decode($custom_field['validation'], ENT_QUOTES, 'UTF-8'), $this->request->post['custom_field'][$custom_field['custom_field_id']])) { + $json['error']['custom_field_' . $custom_field['custom_field_id']] = sprintf($this->language->get('error_regex'), $custom_field['name']); + } + } + } + + if ($this->request->post['password'] || (!isset($this->request->post['customer_id']))) { + if ((oc_strlen(html_entity_decode($this->request->post['password'], ENT_QUOTES, 'UTF-8')) < 4) || (oc_strlen(html_entity_decode($this->request->post['password'], ENT_QUOTES, 'UTF-8')) > 40)) { + $json['error']['password'] = $this->language->get('error_password'); + } + + if ($this->request->post['password'] != $this->request->post['confirm']) { + $json['error']['confirm'] = $this->language->get('error_confirm'); + } + } + + if (isset($this->request->post['address'])) { + foreach ($this->request->post['address'] as $key => $value) { + if ((oc_strlen($value['firstname']) < 1) || (oc_strlen($value['firstname']) > 32)) { + $json['error']['address_' . $key . '_firstname'] = $this->language->get('error_firstname'); + } + + if ((oc_strlen($value['lastname']) < 1) || (oc_strlen($value['lastname']) > 32)) { + $json['error']['address_' . $key . '_lastname'] = $this->language->get('error_lastname'); + } + + if ((oc_strlen($value['address_1']) < 3) || (oc_strlen($value['address_1']) > 128)) { + $json['error']['address_' . $key . '_address_1'] = $this->language->get('error_address_1'); + } + + if ((oc_strlen($value['city']) < 2) || (oc_strlen($value['city']) > 128)) { + $json['error']['address_' . $key . '_city'] = $this->language->get('error_city'); + } + + if (!isset($value['country_id']) || $value['country_id'] == '') { + $json['error']['address_' . $key . '_country'] = $this->language->get('error_country'); + } else { + + $this->load->model('localisation/country'); + + $country_info = $this->model_localisation_country->getCountry($value['country_id']); + + if ($country_info && $country_info['postcode_required'] && (oc_strlen($value['postcode']) < 2 || oc_strlen($value['postcode']) > 10)) { + $json['error']['address_' . $key . '_postcode'] = $this->language->get('error_postcode'); + } + } + + if (!isset($value['zone_id']) || $value['zone_id'] == '') { + $json['error']['address_' . $key . '_zone'] = $this->language->get('error_zone'); + } + + foreach ($custom_fields as $custom_field) { + if ($custom_field['status']) { + if (($custom_field['location'] == 'address') && $custom_field['required'] && empty($value['custom_field'][$custom_field['custom_field_id']])) { + $json['error']['address_' . $key . '_custom_field_' . $custom_field['custom_field_id']] = sprintf($this->language->get('error_custom_field'), $custom_field['name']); + } elseif (($custom_field['location'] == 'address') && ($custom_field['type'] == 'text') && !empty($custom_field['validation']) && !preg_match(html_entity_decode($custom_field['validation'], ENT_QUOTES, 'UTF-8'), $value['custom_field'][$custom_field['custom_field_id']])) { + $json['error']['address_' . $key . '_custom_field_' . $custom_field['custom_field_id']] = sprintf($this->language->get('error_regex'), $custom_field['name']); + } + } + } + } + } + + if (isset($json['error']) && !isset($json['error']['warning'])) { + $json['error']['warning'] = $this->language->get('error_warning'); + } + + if (!$json) { + if (!$this->request->post['customer_id']) { + $json['customer_id'] = $this->model_customer_customer->addCustomer($this->request->post); + } else { + $this->model_customer_customer->editCustomer($this->request->post['customer_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function unlock(): void { + $this->load->language('customer/customer'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'customer/customer')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (empty($this->request->get['email'])) { + $json['error'] = $this->language->get('error_email'); + } + + if (!$json) { + $this->load->model('customer/customer'); + + $this->model_customer_customer->deleteAuthorizeAttempts($this->request->get['email']); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('customer/customer'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'customer/customer')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('customer/customer'); + + foreach ($selected as $customer_id) { + $this->model_customer_customer->deleteCustomer($customer_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return object|\Opencart\System\Engine\Action|null + */ + public function login(): object|null { + if (isset($this->request->get['customer_id'])) { + $customer_id = (int)$this->request->get['customer_id']; + } else { + $customer_id = 0; + } + + $this->load->model('customer/customer'); + + $customer_info = $this->model_customer_customer->getCustomer($customer_id); + + if ($customer_info) { + // Create token to login with + $token = oc_token(64); + + $this->model_customer_customer->editToken($customer_id, $token); + + if (isset($this->request->get['store_id'])) { + $store_id = (int)$this->request->get['store_id']; + } else { + $store_id = 0; + } + + $this->load->model('setting/store'); + + $store_info = $this->model_setting_store->getStore($store_id); + + if ($store_info) { + $this->response->redirect($store_info['url'] . 'index.php?route=account/login.token&email=' . urlencode($customer_info['email']). '&login_token=' . $token); + } else { + $this->response->redirect(HTTP_CATALOG . 'index.php?route=account/login.token&email=' . urlencode($customer_info['email']) . '&login_token=' . $token); + } + + return null; + } else { + return new \Opencart\System\Engine\Action('error/not_found'); + } + } + + /** + * @return void + */ + public function payment(): void { + $this->load->language('customer/customer'); + + //$this->response->setOutput($this->getPayment()); + } + + /** + * @return string + */ + private function getPayment(): string { + if (isset($this->request->get['customer_id'])) { + $customer_id = (int)$this->request->get['customer_id']; + } else { + $customer_id = 0; + } + + if (isset($this->request->get['page']) && $this->request->get['route'] == 'customer/customer.payment') { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $limit = 10; + + $data['payment_methods'] = []; + + $this->load->model('customer/customer'); + + $results = $this->model_customer_customer->getPaymentMethods($customer_id, ($page - 1) * $limit, $limit); + + foreach ($results as $result) { + if (isset($result['image'])) { + $image = DIR_IMAGE . 'payment/' . $result['image']; + } else { + $image = ''; + } + + $data['payment_methods'][] = [ + 'customer_payment_id' => $result['customer_payment_id'], + 'name' => $result['name'], + 'image' => $image, + 'type' => $result['type'], + 'status' => $result['status'], + 'date_expire' => date($this->language->get('date_format_short'), strtotime($result['date_expire'])), + 'delete' => $this->url->link('customer/customer.deletePayment', 'user_token=' . $this->session->data['user_token'] . '&customer_payment_id=' . $result['customer_payment_id']) + ]; + } + + $payment_total = $this->model_customer_customer->getTotalPaymentMethods($customer_id); + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $payment_total, + 'page' => $page, + 'limit' => $limit, + 'url' => $this->url->link('customer/customer.payment', 'user_token=' . $this->session->data['user_token'] . '&customer_id=' . $customer_id . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($payment_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($payment_total - $limit)) ? $payment_total : ((($page - 1) * $limit) + $limit), $payment_total, ceil($payment_total / $limit)); + + return $this->load->view('customer/customer_payment', $data); + } + + /** + * @return void + */ + public function deletePayment(): void { + $this->load->language('customer/customer'); + + $json = []; + + if (isset($this->request->get['customer_payment_id'])) { + $customer_payment_id = (int)$this->request->get['customer_payment_id']; + } else { + $customer_payment_id = 0; + } + + if (!$this->user->hasPermission('modify', 'customer/customer')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('customer/customer'); + + $this->model_customer_customer->deletePaymentMethod($customer_payment_id); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function history(): void { + $this->load->language('customer/customer'); + + $this->response->setOutput($this->getHistory()); + } + + /** + * @return string + */ + public function getHistory(): string { + if (isset($this->request->get['customer_id'])) { + $customer_id = (int)$this->request->get['customer_id']; + } else { + $customer_id = 0; + } + + if (isset($this->request->get['page']) && $this->request->get['route'] == 'customer/customer.history') { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $limit = 10; + + $data['histories'] = []; + + $this->load->model('customer/customer'); + + $results = $this->model_customer_customer->getHistories($customer_id, ($page - 1) * $limit, $limit); + + foreach ($results as $result) { + $data['histories'][] = [ + 'comment' => nl2br($result['comment']), + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])) + ]; + } + + $history_total = $this->model_customer_customer->getTotalHistories($customer_id); + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $history_total, + 'page' => $page, + 'limit' => $limit, + 'url' => $this->url->link('customer/customer.history', 'user_token=' . $this->session->data['user_token'] . '&customer_id=' . $customer_id . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($history_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($history_total - $limit)) ? $history_total : ((($page - 1) * $limit) + $limit), $history_total, ceil($history_total / $limit)); + + return $this->load->view('customer/customer_history', $data); + } + + /** + * @return void + */ + public function addHistory(): void { + $this->load->language('customer/customer'); + + $json = []; + + if (isset($this->request->get['customer_id'])) { + $customer_id = (int)$this->request->get['customer_id']; + } else { + $customer_id = 0; + } + + if (!$this->user->hasPermission('modify', 'customer/customer')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('customer/customer'); + + $this->model_customer_customer->addHistory($customer_id, $this->request->post['comment']); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function transaction(): void { + $this->load->language('customer/customer'); + + $this->response->setOutput($this->getTransaction()); + } + + /** + * @return string + */ + public function getTransaction(): string { + if (isset($this->request->get['customer_id'])) { + $customer_id = (int)$this->request->get['customer_id']; + } else { + $customer_id = 0; + } + + if (isset($this->request->get['page']) && $this->request->get['route'] == 'customer/customer.transaction') { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $limit = 10; + + $data['transactions'] = []; + + $this->load->model('customer/customer'); + + $results = $this->model_customer_customer->getTransactions($customer_id, ($page - 1) * $limit, $limit); + + foreach ($results as $result) { + $data['transactions'][] = [ + 'amount' => $this->currency->format($result['amount'], $this->config->get('config_currency')), + 'description' => $result['description'], + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])) + ]; + } + + $data['balance'] = $this->currency->format($this->model_customer_customer->getTransactionTotal($customer_id), $this->config->get('config_currency')); + + $transaction_total = $this->model_customer_customer->getTotalTransactions($customer_id); + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $transaction_total, + 'page' => $page, + 'limit' => $limit, + 'url' => $this->url->link('customer/customer.transaction', 'user_token=' . $this->session->data['user_token'] . '&customer_id=' . $customer_id . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($transaction_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($transaction_total - $limit)) ? $transaction_total : ((($page - 1) * $limit) + $limit), $transaction_total, ceil($transaction_total / $limit)); + + return $this->load->view('customer/customer_transaction', $data); + } + + /** + * @return void + */ + public function addTransaction(): void { + $this->load->language('customer/customer'); + + $json = []; + + if (isset($this->request->get['customer_id'])) { + $customer_id = (int)$this->request->get['customer_id']; + } else { + $customer_id = 0; + } + + if (!$this->user->hasPermission('modify', 'customer/customer')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('customer/customer'); + + $customer_info = $this->model_customer_customer->getCustomer($customer_id); + + if (!$customer_info) { + $json['error'] = $this->language->get('error_customer'); + } + + if (!$json) { + $this->load->model('customer/customer'); + + $this->model_customer_customer->addTransaction($customer_id, (string)$this->request->post['description'], (float)$this->request->post['amount']); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function reward(): void { + $this->load->language('customer/customer'); + + $this->response->setOutput($this->getReward()); + } + + /** + * @return string + */ + public function getReward(): string { + if (isset($this->request->get['customer_id'])) { + $customer_id = (int)$this->request->get['customer_id']; + } else { + $customer_id = 0; + } + + if (isset($this->request->get['page']) && $this->request->get['route'] == 'customer/customer.reward') { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $limit = 10; + + $data['rewards'] = []; + + $this->load->model('customer/customer'); + + $results = $this->model_customer_customer->getRewards($customer_id, ($page - 1) * $limit, $limit); + + foreach ($results as $result) { + $data['rewards'][] = [ + 'points' => $result['points'], + 'description' => $result['description'], + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])) + ]; + } + + $data['balance'] = $this->model_customer_customer->getRewardTotal($customer_id); + + $reward_total = $this->model_customer_customer->getTotalRewards($customer_id); + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $reward_total, + 'page' => $page, + 'limit' => $limit, + 'url' => $this->url->link('customer/customer.reward', 'user_token=' . $this->session->data['user_token'] . '&customer_id=' . $customer_id . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($reward_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($reward_total - $limit)) ? $reward_total : ((($page - 1) * $limit) + $limit), $reward_total, ceil($reward_total / $limit)); + + return $this->load->view('customer/customer_reward', $data); + } + + /** + * @return void + */ + public function addReward(): void { + $this->load->language('customer/customer'); + + $json = []; + + if (isset($this->request->get['customer_id'])) { + $customer_id = (int)$this->request->get['customer_id']; + } else { + $customer_id = 0; + } + + if (!$this->user->hasPermission('modify', 'customer/customer')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('customer/customer'); + + $customer_info = $this->model_customer_customer->getCustomer($customer_id); + + if (!$customer_info) { + $json['error'] = $this->language->get('error_customer'); + } + + if (!$json) { + $this->load->model('customer/customer'); + + $this->model_customer_customer->addReward($customer_id, (string)$this->request->post['description'], (int)$this->request->post['points']); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function ip(): void { + $this->load->language('customer/customer'); + + $this->response->setOutput($this->getIp()); + } + + /** + * @return string + */ + public function getIp(): string { + if (isset($this->request->get['customer_id'])) { + $customer_id = (int)$this->request->get['customer_id']; + } else { + $customer_id = 0; + } + + if (isset($this->request->get['page']) && $this->request->get['route'] == 'customer/customer.ip') { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $limit = 10; + + $data['ips'] = []; + + $this->load->model('customer/customer'); + $this->load->model('setting/store'); + + $results = $this->model_customer_customer->getIps($customer_id, ($page - 1) * $limit, $limit); + + foreach ($results as $result) { + $store_info = $this->model_setting_store->getStore($result['store_id']); + + if ($store_info) { + $store = $store_info['name']; + } elseif (!$result['store_id']) { + $store = $this->config->get('config_name'); + } else { + $store = ''; + } + + $data['ips'][] = [ + 'ip' => $result['ip'], + 'account' => $this->model_customer_customer->getTotalCustomersByIp($result['ip']), + 'store' => $store, + 'country' => $result['country'], + 'date_added' => date($this->language->get('datetime_format'), strtotime($result['date_added'])), + 'filter_ip' => $this->url->link('customer/customer', 'user_token=' . $this->session->data['user_token'] . '&filter_ip=' . $result['ip']) + ]; + } + + $ip_total = $this->model_customer_customer->getTotalIps($customer_id); + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $ip_total, + 'page' => $page, + 'limit' => $limit, + 'url' => $this->url->link('customer/customer.ip', 'user_token=' . $this->session->data['user_token'] . '&customer_id=' . $customer_id . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($ip_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($ip_total - $limit)) ? $ip_total : ((($page - 1) * $limit) + $limit), $ip_total, ceil($ip_total / $limit)); + + return $this->load->view('customer/customer_ip', $data); + } + + /** + * @return void + */ + public function autocomplete(): void { + $json = []; + + if (isset($this->request->get['filter_name']) || isset($this->request->get['filter_email'])) { + if (isset($this->request->get['filter_name'])) { + $filter_name = $this->request->get['filter_name']; + } else { + $filter_name = ''; + } + + if (isset($this->request->get['filter_email'])) { + $filter_email = $this->request->get['filter_email']; + } else { + $filter_email = ''; + } + + $filter_data = [ + 'filter_name' => $filter_name, + 'filter_email' => $filter_email, + 'start' => 0, + 'limit' => 5 + ]; + + $this->load->model('customer/customer'); + + $results = $this->model_customer_customer->getCustomers($filter_data); + + foreach ($results as $result) { + $json[] = [ + 'customer_id' => $result['customer_id'], + 'customer_group_id' => $result['customer_group_id'], + 'name' => strip_tags(html_entity_decode($result['name'], ENT_QUOTES, 'UTF-8')), + 'customer_group' => $result['customer_group'], + 'firstname' => $result['firstname'], + 'lastname' => $result['lastname'], + 'email' => $result['email'], + 'telephone' => $result['telephone'], + 'custom_field' => json_decode($result['custom_field'], true), + 'address' => $this->model_customer_customer->getAddresses($result['customer_id']) + ]; + } + } + + $sort_order = []; + + foreach ($json as $key => $value) { + $sort_order[$key] = $value['name']; + } + + array_multisort($sort_order, SORT_ASC, $json); + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function address(): void { + $this->load->language('customer/customer'); + + $json = []; + + if (isset($this->request->get['address_id'])) { + $address_id = (int)$this->request->get['address_id']; + } else { + $address_id = 0; + } + + $this->load->model('customer/customer'); + + $address_info = $this->model_customer_customer->getAddress($address_id); + + if (!$address_info) { + $json['error'] = $this->language->get('error_address'); + } + + if (!$json) { + $json = $address_info; + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function customfield(): void { + $json = []; + + // Customer Group + if (isset($this->request->get['customer_group_id'])) { + $customer_group_id = (int)$this->request->get['customer_group_id']; + } else { + $customer_group_id = $this->config->get('config_customer_group_id'); + } + + $this->load->model('customer/custom_field'); + + $custom_fields = $this->model_customer_custom_field->getCustomFields(['filter_customer_group_id' => $customer_group_id]); + + foreach ($custom_fields as $custom_field) { + $json[] = [ + 'custom_field_id' => $custom_field['custom_field_id'], + 'required' => empty($custom_field['required']) || $custom_field['required'] == 0 ? false : true + ]; + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/customer/customer_approval.php b/admininistrator/controller/customer/customer_approval.php new file mode 100644 index 0000000..e97f813 --- /dev/null +++ b/admininistrator/controller/customer/customer_approval.php @@ -0,0 +1,297 @@ +load->language('customer/customer_approval'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('customer/customer_approval', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['approve'] = $this->url->link('customer/customer_approval.approve', 'user_token=' . $this->session->data['user_token'], true); + $data['deny'] = $this->url->link('customer/customer_approval.deny', 'user_token=' . $this->session->data['user_token'], true); + + $this->load->model('customer/customer_group'); + + $data['customer_groups'] = $this->model_customer_customer_group->getCustomerGroups(); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('customer/customer_approval', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('customer/customer_approval'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + if (isset($this->request->get['filter_customer'])) { + $filter_customer = $this->request->get['filter_customer']; + } else { + $filter_customer = ''; + } + + if (isset($this->request->get['filter_email'])) { + $filter_email = $this->request->get['filter_email']; + } else { + $filter_email = ''; + } + + if (isset($this->request->get['filter_customer_group_id'])) { + $filter_customer_group_id = (int)$this->request->get['filter_customer_group_id']; + } else { + $filter_customer_group_id = ''; + } + + if (isset($this->request->get['filter_type'])) { + $filter_type = $this->request->get['filter_type']; + } else { + $filter_type = ''; + } + + if (isset($this->request->get['filter_date_from'])) { + $filter_date_from = $this->request->get['filter_date_from']; + } else { + $filter_date_from = ''; + } + + if (isset($this->request->get['filter_date_to'])) { + $filter_date_to = $this->request->get['filter_date_to']; + } else { + $filter_date_to = ''; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_email'])) { + $url .= '&filter_email=' . urlencode(html_entity_decode($this->request->get['filter_email'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_customer_group_id'])) { + $url .= '&filter_customer_group_id=' . $this->request->get['filter_customer_group_id']; + } + + if (isset($this->request->get['filter_type'])) { + $url .= '&filter_type=' . $this->request->get['filter_type']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('customer/customer_approval.list', 'user_token=' . $this->session->data['user_token'] . $url, true); + + $data['customer_approvals'] = []; + + $filter_data = [ + 'filter_customer' => $filter_customer, + 'filter_email' => $filter_email, + 'filter_customer_group_id' => $filter_customer_group_id, + 'filter_type' => $filter_type, + 'filter_date_from' => $filter_date_from, + 'filter_date_to' => $filter_date_to, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('customer/customer_approval'); + + $customer_approval_total = $this->model_customer_customer_approval->getTotalCustomerApprovals($filter_data); + + $results = $this->model_customer_customer_approval->getCustomerApprovals($filter_data); + + foreach ($results as $result) { + $data['customer_approvals'][] = [ + 'customer_approval_id' => $result['customer_approval_id'], + 'customer_id' => $result['customer_id'], + 'customer' => $result['customer'], + 'email' => $result['email'], + 'customer_group' => $result['customer_group'], + 'type' => $this->language->get('text_' . $result['type']), + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])), + 'approve' => $this->url->link('customer/customer_approval.approve', 'user_token=' . $this->session->data['user_token'] . '&customer_approval_id=' . $result['customer_approval_id'], true), + 'deny' => $this->url->link('customer/customer_approval.deny', 'user_token=' . $this->session->data['user_token'] . '&customer_approval_id=' . $result['customer_approval_id'], true), + 'edit' => $this->url->link('customer/customer.form', 'user_token=' . $this->session->data['user_token'] . '&customer_id=' . $result['customer_id'], true) + ]; + } + + $url = ''; + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_email'])) { + $url .= '&filter_email=' . urlencode(html_entity_decode($this->request->get['filter_email'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_customer_group_id'])) { + $url .= '&filter_customer_group_id=' . $this->request->get['filter_customer_group_id']; + } + + if (isset($this->request->get['filter_type'])) { + $url .= '&filter_type=' . $this->request->get['filter_type']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $customer_approval_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('customer/customer_approval.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($customer_approval_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($customer_approval_total - $this->config->get('config_pagination_admin'))) ? $customer_approval_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $customer_approval_total, ceil($customer_approval_total / $this->config->get('config_pagination_admin'))); + + return $this->load->view('customer/customer_approval_list', $data); + } + + /** + * @return void + */ + public function approve(): void { + $this->load->language('customer/customer_approval'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'customer/customer_approval')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('customer/customer_approval'); + + $approvals = []; + + if (isset($this->request->post['selected'])) { + $approvals = $this->request->post['selected']; + } + + if (isset($this->request->get['customer_approval_id'])) { + $approvals[] = (int)$this->request->get['customer_approval_id']; + } + + foreach ($approvals as $customer_approval_id) { + $customer_approval_info = $this->model_customer_customer_approval->getCustomerApproval($customer_approval_id); + + if ($customer_approval_info) { + if ($customer_approval_info['type'] == 'customer') { + $this->model_customer_customer_approval->approveCustomer($customer_approval_info['customer_id']); + } + + if ($customer_approval_info['type'] == 'affiliate') { + $this->model_customer_customer_approval->approveAffiliate($customer_approval_info['customer_id']); + } + } + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function deny(): void { + $this->load->language('customer/customer_approval'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'customer/customer_approval')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('customer/customer_approval'); + + $denials = []; + + if (isset($this->request->post['selected'])) { + $denials = $this->request->post['selected']; + } + + if (isset($this->request->get['customer_approval_id'])) { + $denials[] = (int)$this->request->get['customer_approval_id']; + } + + foreach ($denials as $customer_approval_id) { + $customer_approval_info = $this->model_customer_customer_approval->getCustomerApproval($customer_approval_id); + + if ($customer_approval_info) { + if ($customer_approval_info['type'] == 'customer') { + $this->model_customer_customer_approval->denyCustomer($customer_approval_info['customer_id']); + } + + if ($customer_approval_info['type'] == 'affiliate') { + $this->model_customer_customer_approval->denyAffiliate($customer_approval_info['customer_id']); + } + } + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/customer/customer_group.php b/admininistrator/controller/customer/customer_group.php new file mode 100644 index 0000000..ee3ef6e --- /dev/null +++ b/admininistrator/controller/customer/customer_group.php @@ -0,0 +1,330 @@ +load->language('customer/customer_group'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('customer/customer_group', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('customer/customer_group.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('customer/customer_group.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('customer/customer_group', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('customer/customer_group'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'cgd.name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('customer/customer_group.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['customer_groups'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('customer/customer_group'); + + $customer_group_total = $this->model_customer_customer_group->getTotalCustomerGroups(); + + $results = $this->model_customer_customer_group->getCustomerGroups($filter_data); + + foreach ($results as $result) { + $data['customer_groups'][] = [ + 'customer_group_id' => $result['customer_group_id'], + 'name' => $result['name'] . (($result['customer_group_id'] == $this->config->get('config_customer_group_id')) ? $this->language->get('text_default') : ''), + 'sort_order' => $result['sort_order'], + 'edit' => $this->url->link('customer/customer_group.form', 'user_token=' . $this->session->data['user_token'] . '&customer_group_id=' . $result['customer_group_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('customer/customer_group.list', 'user_token=' . $this->session->data['user_token'] . '&sort=cgd.name' . $url); + $data['sort_sort_order'] = $this->url->link('customer/customer_group.list', 'user_token=' . $this->session->data['user_token'] . '&sort=cg.sort_order' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $customer_group_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('customer/customer_group.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($customer_group_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($customer_group_total - $this->config->get('config_pagination_admin'))) ? $customer_group_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $customer_group_total, ceil($customer_group_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('customer/customer_group_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('customer/customer_group'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['customer_group_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('customer/customer_group', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('customer/customer_group.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('customer/customer_group', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['customer_group_id'])) { + $this->load->model('customer/customer_group'); + + $customer_group_info = $this->model_customer_customer_group->getCustomerGroup($this->request->get['customer_group_id']); + } + + if (isset($this->request->get['customer_group_id'])) { + $data['customer_group_id'] = (int)$this->request->get['customer_group_id']; + } else { + $data['customer_group_id'] = 0; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (isset($this->request->get['customer_group_id'])) { + $data['customer_group_description'] = $this->model_customer_customer_group->getDescriptions($this->request->get['customer_group_id']); + } else { + $data['customer_group_description'] = []; + } + + if (!empty($customer_group_info)) { + $data['approval'] = $customer_group_info['approval']; + } else { + $data['approval'] = ''; + } + + if (!empty($customer_group_info)) { + $data['sort_order'] = $customer_group_info['sort_order']; + } else { + $data['sort_order'] = ''; + } + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('customer/customer_group_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('customer/customer_group'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'customer/customer_group')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + foreach ($this->request->post['customer_group_description'] as $language_id => $value) { + if ((oc_strlen($value['name']) < 3) || (oc_strlen($value['name']) > 32)) { + $json['error']['name_' . $language_id] = $this->language->get('error_name'); + } + } + + if (!$json) { + $this->load->model('customer/customer_group'); + + if (!$this->request->post['customer_group_id']) { + $json['customer_group_id'] = $this->model_customer_customer_group->addCustomerGroup($this->request->post); + } else { + $this->model_customer_customer_group->editCustomerGroup($this->request->post['customer_group_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('customer/customer_group'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'customer/customer_group')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('setting/store'); + $this->load->model('customer/customer'); + + foreach ($selected as $customer_group_id) { + if ($this->config->get('config_customer_group_id') == $customer_group_id) { + $json['error'] = $this->language->get('error_default'); + } + + $store_total = $this->model_setting_store->getTotalStoresByCustomerGroupId($customer_group_id); + + if ($store_total) { + $json['error'] = sprintf($this->language->get('error_store'), $store_total); + } + + $customer_total = $this->model_customer_customer->getTotalCustomersByCustomerGroupId($customer_group_id); + + if ($customer_total) { + $json['error'] = sprintf($this->language->get('error_customer'), $customer_total); + } + } + + if (!$json) { + $this->load->model('customer/customer_group'); + + foreach ($selected as $customer_group_id) { + $this->model_customer_customer_group->deleteCustomerGroup($customer_group_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/customer/gdpr.php b/admininistrator/controller/customer/gdpr.php new file mode 100644 index 0000000..b57b3ee --- /dev/null +++ b/admininistrator/controller/customer/gdpr.php @@ -0,0 +1,336 @@ +load->language('customer/gdpr'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('customer/gdpr', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['text_info'] = sprintf($this->language->get('text_info'), $this->config->get('config_gdpr_limit')); + + $data['approve'] = $this->url->link('customer/gdpr.approve', 'user_token=' . $this->session->data['user_token'], true); + $data['deny'] = $this->url->link('customer/gdpr.deny', 'user_token=' . $this->session->data['user_token'], true); + $data['delete'] = $this->url->link('customer/gdpr.delete', 'user_token=' . $this->session->data['user_token'], true); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('customer/gdpr', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('customer/gdpr'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + $this->load->language('customer/gdpr'); + + if (isset($this->request->get['filter_email'])) { + $filter_email = $this->request->get['filter_email']; + } else { + $filter_email = ''; + } + + if (isset($this->request->get['filter_action'])) { + $filter_action = $this->request->get['filter_action']; + } else { + $filter_action = ''; + } + + if (isset($this->request->get['filter_status'])) { + $filter_status = $this->request->get['filter_status']; + } else { + $filter_status = ''; + } + + if (isset($this->request->get['filter_date_from'])) { + $filter_date_from = $this->request->get['filter_date_from']; + } else { + $filter_date_from = ''; + } + + if (isset($this->request->get['filter_date_to'])) { + $filter_date_to = $this->request->get['filter_date_to']; + } else { + $filter_date_to = ''; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['filter_email'])) { + $url .= '&filter_email=' . urlencode(html_entity_decode($this->request->get['filter_email'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_action'])) { + $url .= '&filter_action=' . $this->request->get['filter_action']; + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + $data['action'] = $this->url->link('customer/gdpr.list', 'user_token=' . $this->session->data['user_token'] . $url, true); + + $data['gdprs'] = []; + + $filter_data = [ + 'filter_email' => $filter_email, + 'filter_action' => $filter_action, + 'filter_status' => $filter_status, + 'filter_date_from' => $filter_date_from, + 'filter_date_to' => $filter_date_to, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('customer/gdpr'); + $this->load->model('customer/customer'); + + $gdpr_total = $this->model_customer_gdpr->getTotalGdprs($filter_data); + + $results = $this->model_customer_gdpr->getGdprs($filter_data); + + foreach ($results as $result) { + $customer_info = $this->model_customer_customer->getCustomerByEmail($result['email']); + + if ($customer_info) { + $edit = $this->url->link('customer/customer.form', 'user_token=' . $this->session->data['user_token'] . '&customer_id=' . $customer_info['customer_id'], true); + } else { + $edit = ''; + } + + $data['gdprs'][] = [ + 'gdpr_id' => $result['gdpr_id'], + 'email' => $result['email'], + 'action' => $this->language->get('text_' . $result['action']), + 'status' => $result['status'], + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])), + 'approve' => $this->url->link('customer/gdpr.approve', 'user_token=' . $this->session->data['user_token'] . '&gdpr_id=' . $result['gdpr_id'], true), + 'deny' => $this->url->link('customer/gdpr.deny', 'user_token=' . $this->session->data['user_token'] . '&gdpr_id=' . $result['gdpr_id'], true), + 'edit' => $edit, + 'delete' => $this->url->link('customer/gdpr.delete', 'user_token=' . $this->session->data['user_token'] . '&gdpr_id=' . $result['gdpr_id'], true) + ]; + } + + $url = ''; + + if (isset($this->request->get['filter_email'])) { + $url .= '&filter_email=' . urlencode(html_entity_decode($this->request->get['filter_email'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_action'])) { + $url .= '&filter_action=' . $this->request->get['filter_action']; + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $gdpr_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('customer/gdpr.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($gdpr_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($gdpr_total - $this->config->get('config_pagination_admin'))) ? $gdpr_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $gdpr_total, ceil($gdpr_total / $this->config->get('config_pagination_admin'))); + + return $this->load->view('customer/gdpr_list', $data); + } + + /* + * Action Statuses + * + * EXPORT + * + * unverified = 0 + * pending = 1 + * complete = 3 + * + * REMOVE + * + * unverified = 0 + * pending = 1 + * processing = 2 + * delete = 3 + * + * DENY + * + * unverified = 0 + * pending = 1 + * processing = 2 + * denied = -1 + */ + /** + * @return void + */ + public function approve(): void { + $this->load->language('customer/gdpr'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'customer/gdpr')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $gdprs = []; + + if (isset($this->request->post['selected'])) { + $gdprs = $this->request->post['selected']; + } + + if (isset($this->request->get['gdpr_id'])) { + $gdprs[] = (int)$this->request->get['gdpr_id']; + } + + $this->load->model('customer/gdpr'); + + foreach ($gdprs as $gdpr_id) { + $gdpr_info = $this->model_customer_gdpr->getGdpr($gdpr_id); + + if ($gdpr_info) { + // If we remove we want to change the status to processing + // to give time for store owners to process orders and refunds. + if ($gdpr_info['action'] == 'export') { + $this->model_customer_gdpr->editStatus($gdpr_id, 3); + } else { + $this->model_customer_gdpr->editStatus($gdpr_id, 2); + } + } + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function deny(): void { + $this->load->language('customer/gdpr'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'customer/gdpr')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $gdprs = []; + + if (isset($this->request->post['selected'])) { + $gdprs = $this->request->post['selected']; + } + + if (isset($this->request->get['gdpr_id'])) { + $gdprs[] = (int)$this->request->get['gdpr_id']; + } + + $this->load->model('customer/gdpr'); + + foreach ($gdprs as $gdpr_id) { + $this->model_customer_gdpr->editStatus($gdpr_id, -1); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('customer/gdpr'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'customer/gdpr')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $gdprs = []; + + if (isset($this->request->post['selected'])) { + $gdprs = $this->request->post['selected']; + } + + if (isset($this->request->get['gdpr_id'])) { + $gdprs[] = (int)$this->request->get['gdpr_id']; + } + + $this->load->model('customer/gdpr'); + + foreach ($gdprs as $gdpr_id) { + $this->model_customer_gdpr->deleteGdpr($gdpr_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/design/banner.php b/admininistrator/controller/design/banner.php new file mode 100644 index 0000000..85b9998 --- /dev/null +++ b/admininistrator/controller/design/banner.php @@ -0,0 +1,344 @@ +load->language('design/banner'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('design/banner', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('design/banner.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('design/banner.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('design/banner', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('design/banner'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('design/banner.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['banners'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('design/banner'); + + $banner_total = $this->model_design_banner->getTotalBanners(); + + $results = $this->model_design_banner->getBanners($filter_data); + + foreach ($results as $result) { + $data['banners'][] = [ + 'banner_id' => $result['banner_id'], + 'name' => $result['name'], + 'status' => $result['status'], + 'edit' => $this->url->link('design/banner.form', 'user_token=' . $this->session->data['user_token'] . '&banner_id=' . $result['banner_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('design/banner.list', 'user_token=' . $this->session->data['user_token'] . '&sort=name' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $banner_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('design/banner.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($banner_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($banner_total - $this->config->get('config_pagination_admin'))) ? $banner_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $banner_total, ceil($banner_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('design/banner_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('design/banner'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['banner_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('design/banner', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('design/banner.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('design/banner', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['banner_id'])) { + $this->load->model('design/banner'); + + $banner_info = $this->model_design_banner->getBanner($this->request->get['banner_id']); + } + + if (isset($this->request->get['banner_id'])) { + $data['banner_id'] = (int)$this->request->get['banner_id']; + } else { + $data['banner_id'] = 0; + } + + if (!empty($banner_info)) { + $data['name'] = $banner_info['name']; + } else { + $data['name'] = ''; + } + + if (!empty($banner_info)) { + $data['status'] = $banner_info['status']; + } else { + $data['status'] = true; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + $this->load->model('tool/image'); + + if (!empty($banner_info)) { + $banner_images = $this->model_design_banner->getImages($this->request->get['banner_id']); + } else { + $banner_images = []; + } + + $data['banner_images'] = []; + + foreach ($banner_images as $language_id => $banner_image) { + foreach ($banner_image as $value) { + if (is_file(DIR_IMAGE . html_entity_decode($value['image'], ENT_QUOTES, 'UTF-8'))) { + $image = $value['image']; + $thumb = $value['image']; + } else { + $image = ''; + $thumb = 'no_image.png'; + } + + $data['banner_images'][$language_id][] = [ + 'title' => $value['title'], + 'link' => $value['link'], + 'image' => $image, + 'thumb' => $this->model_tool_image->resize(html_entity_decode($thumb, ENT_QUOTES, 'UTF-8'), 100, 100), + 'sort_order' => $value['sort_order'] + ]; + } + } + + $data['placeholder'] = $this->model_tool_image->resize('no_image.png', 100, 100); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('design/banner_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('design/banner'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'design/banner')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if ((oc_strlen($this->request->post['name']) < 3) || (oc_strlen($this->request->post['name']) > 64)) { + $json['error']['name'] = $this->language->get('error_name'); + } + + if (isset($this->request->post['banner_image'])) { + foreach ($this->request->post['banner_image'] as $language_id => $banner_image) { + foreach ($banner_image as $key => $value) { + if ((oc_strlen(trim($value['title'])) < 2) || (oc_strlen($value['title']) > 64)) { + $json['error']['image_' . $language_id . '_' . $key . '_title'] = $this->language->get('error_title'); + } + } + } + } + + if (!$json) { + $this->load->model('design/banner'); + + if (!$this->request->post['banner_id']) { + $json['banner_id'] = $this->model_design_banner->addBanner($this->request->post); + } else { + $this->model_design_banner->editBanner($this->request->post['banner_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('design/banner'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'design/banner')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('design/banner'); + + foreach ($selected as $banner_id) { + $this->model_design_banner->deleteBanner($banner_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/design/layout.php b/admininistrator/controller/design/layout.php new file mode 100644 index 0000000..e534687 --- /dev/null +++ b/admininistrator/controller/design/layout.php @@ -0,0 +1,410 @@ +load->language('design/layout'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('design/layout', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('design/layout.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('design/layout.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('design/layout', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('design/layout'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('design/layout.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['layouts'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('design/layout'); + + $layout_total = $this->model_design_layout->getTotalLayouts(); + + $results = $this->model_design_layout->getLayouts($filter_data); + + foreach ($results as $result) { + $data['layouts'][] = [ + 'layout_id' => $result['layout_id'], + 'name' => $result['name'], + 'edit' => $this->url->link('design/layout.form', 'user_token=' . $this->session->data['user_token'] . '&layout_id=' . $result['layout_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('design/layout.list', 'user_token=' . $this->session->data['user_token'] . '&sort=name' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $layout_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('design/layout.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($layout_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($layout_total - $this->config->get('config_pagination_admin'))) ? $layout_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $layout_total, ceil($layout_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('design/layout_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('design/layout'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['layout_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('design/layout', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('design/layout.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('design/layout', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['layout_id'])) { + $this->load->model('design/layout'); + + $layout_info = $this->model_design_layout->getLayout($this->request->get['layout_id']); + } + + if (isset($this->request->get['layout_id'])) { + $data['layout_id'] = (int)$this->request->get['layout_id']; + } else { + $data['layout_id'] = 0; + } + + if (!empty($layout_info)) { + $data['name'] = $layout_info['name']; + } else { + $data['name'] = ''; + } + + $this->load->model('setting/store'); + + $data['stores'] = $this->model_setting_store->getStores(); + + if (isset($this->request->get['layout_id'])) { + $data['layout_routes'] = $this->model_design_layout->getRoutes($this->request->get['layout_id']); + } else { + $data['layout_routes'] = []; + } + + $this->load->model('setting/extension'); + + $this->load->model('setting/module'); + + $data['extensions'] = []; + + // Get a list of installed modules + $extensions = $this->model_setting_extension->getExtensionsByType('module'); + + // Add all the modules which have multiple settings for each module + foreach ($extensions as $extension) { + $this->load->language('extension/' . $extension['extension'] . '/module/' . $extension['code'], $extension['code']); + + $module_data = []; + + $modules = $this->model_setting_module->getModulesByCode($extension['extension'] .'.' . $extension['code']); + + foreach ($modules as $module) { + $module_data[] = [ + 'name' => strip_tags($module['name']), + 'code' => $extension['extension'] . '.' . $extension['code'] . '.' . $module['module_id'] + ]; + } + + if ($this->config->has('module_' . $extension['code'] . '_status') || $module_data) { + $data['extensions'][] = [ + 'name' => strip_tags($this->language->get($extension['code'] . '_heading_title')), + 'code' => $extension['extension'] . '.' . $extension['code'], + 'module' => $module_data + ]; + } + } + + // Modules layout + if (!empty($layout_info)) { + $layout_modules = $this->model_design_layout->getModules($this->request->get['layout_id']); + } else { + $layout_modules = []; + } + + $data['layout_modules'] = []; + + // Add all the modules which have multiple settings for each module + foreach ($layout_modules as $layout_module) { + $part = explode('.', $layout_module['code']); + + if (!isset($part[2])) { + $data['layout_modules'][] = [ + 'code' => $layout_module['code'], + 'position' => $layout_module['position'], + 'sort_order' => $layout_module['sort_order'], + 'edit' => $this->url->link('extension/' . $part[0] . '/module/' . $part[1], 'user_token=' . $this->session->data['user_token']) + ]; + } else { + $module_info = $this->model_setting_module->getModule($part[2]); + + if ($module_info) { + $data['layout_modules'][] = [ + 'code' => $layout_module['code'], + 'position' => $layout_module['position'], + 'sort_order' => $layout_module['sort_order'], + 'edit' => $this->url->link('extension/' . $part[0] . '/module/' . $part[1], 'user_token=' . $this->session->data['user_token'] . '&module_id=' . $part[2]) + ]; + } + } + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('design/layout_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('design/layout'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'design/layout')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if ((oc_strlen($this->request->post['name']) < 3) || (oc_strlen($this->request->post['name']) > 64)) { + $json['error']['name'] = $this->language->get('error_name'); + } + + if (!$json) { + $this->load->model('design/layout'); + + if (!$this->request->post['layout_id']) { + $json['layout_id'] = $this->model_design_layout->addLayout($this->request->post); + } else { + $this->model_design_layout->editLayout($this->request->post['layout_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('design/layout'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'design/layout')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('setting/store'); + $this->load->model('catalog/product'); + $this->load->model('catalog/category'); + $this->load->model('catalog/manufacturer'); + $this->load->model('catalog/information'); + + foreach ($selected as $layout_id) { + if ($this->config->get('config_layout_id') == $layout_id) { + $json['error'] = $this->language->get('error_default'); + } + + $store_total = $this->model_setting_store->getTotalStoresByLayoutId($layout_id); + + if ($store_total) { + $json['error'] = sprintf($this->language->get('error_store'), $store_total); + } + + $product_total = $this->model_catalog_product->getTotalProductsByLayoutId($layout_id); + + if ($product_total) { + $json['error'] = sprintf($this->language->get('error_product'), $product_total); + } + + $category_total = $this->model_catalog_category->getTotalCategoriesByLayoutId($layout_id); + + if ($category_total) { + $json['error'] = sprintf($this->language->get('error_category'), $category_total); + } + + $manufacturer_total = $this->model_catalog_manufacturer->getTotalManufacturersByLayoutId($layout_id); + + if ($manufacturer_total) { + $json['error'] = sprintf($this->language->get('error_manufacturer'), $manufacturer_total); + } + + $information_total = $this->model_catalog_information->getTotalInformationsByLayoutId($layout_id); + + if ($information_total) { + $json['error'] = sprintf($this->language->get('error_information'), $information_total); + } + } + + if (!$json) { + $this->load->model('design/layout'); + + foreach ($selected as $layout_id) { + $this->model_design_layout->deleteLayout($layout_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/design/seo_url.php b/admininistrator/controller/design/seo_url.php new file mode 100644 index 0000000..110217a --- /dev/null +++ b/admininistrator/controller/design/seo_url.php @@ -0,0 +1,573 @@ +load->language('design/seo_url'); + + $this->document->setTitle($this->language->get('heading_title')); + + if (isset($this->request->get['filter_keyword'])) { + $filter_keyword = (string)$this->request->get['filter_keyword']; + } else { + $filter_keyword = ''; + } + + if (isset($this->request->get['filter_key'])) { + $filter_key = (string)$this->request->get['filter_key']; + } else { + $filter_key = ''; + } + + if (isset($this->request->get['filter_value'])) { + $filter_value = (string)$this->request->get['filter_value']; + } else { + $filter_value = ''; + } + + if (isset($this->request->get['filter_store_id'])) { + $filter_store_id = (int)$this->request->get['filter_store_id']; + } else { + $filter_store_id = ''; + } + + if (isset($this->request->get['filter_language_id'])) { + $filter_language_id = (int)$this->request->get['filter_language_id']; + } else { + $filter_language_id = 0; + } + + $url = ''; + + if (isset($this->request->get['filter_keyword'])) { + $url .= '&filter_keyword=' . urlencode(html_entity_decode((string)$this->request->get['filter_keyword'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_key'])) { + $url .= '&filter_key=' . urlencode(html_entity_decode((string)$this->request->get['filter_key'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_value'])) { + $url .= '&filter_value=' . urlencode(html_entity_decode((string)$this->request->get['filter_value'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_store_id'])) { + $url .= '&filter_store_id=' . (int)$this->request->get['filter_store_id']; + } + + if (isset($this->request->get['filter_language_id'])) { + $url .= '&filter_language_id=' . (int)$this->request->get['filter_language_id']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . (string)$this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . (string)$this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . (int)$this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('design/seo_url', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('design/seo_url.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('design/seo_url.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $this->load->model('setting/store'); + + $data['stores'] = $this->model_setting_store->getStores(); + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + $data['filter_keyword'] = $filter_keyword; + $data['filter_key'] = $filter_key; + $data['filter_value'] = $filter_value; + $data['filter_store_id'] = $filter_store_id; + $data['filter_language_id'] = $filter_language_id; + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('design/seo_url', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('design/seo_url'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['filter_keyword'])) { + $filter_keyword = (string)$this->request->get['filter_keyword']; + } else { + $filter_keyword = ''; + } + + if (isset($this->request->get['filter_key'])) { + $filter_key = (string)$this->request->get['filter_key']; + } else { + $filter_key = ''; + } + + if (isset($this->request->get['filter_value'])) { + $filter_value = (string)$this->request->get['filter_value']; + } else { + $filter_value = ''; + } + + if (isset($this->request->get['filter_store_id'])) { + $filter_store_id = (int)$this->request->get['filter_store_id']; + } else { + $filter_store_id = ''; + } + + if (isset($this->request->get['filter_language_id'])) { + $filter_language_id = (int)$this->request->get['filter_language_id']; + } else { + $filter_language_id = 0; + } + + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'key'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['filter_keyword'])) { + $url .= '&filter_keyword=' . urlencode(html_entity_decode((string)$this->request->get['filter_keyword'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_key'])) { + $url .= '&filter_key=' . urlencode(html_entity_decode((string)$this->request->get['filter_key'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_value'])) { + $url .= '&filter_value=' . urlencode(html_entity_decode((string)$this->request->get['filter_value'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_store_id'])) { + $url .= '&filter_store_id=' . (int)$this->request->get['filter_store_id']; + } + + if (isset($this->request->get['filter_language_id'])) { + $url .= '&filter_language_id=' . (int)$this->request->get['filter_language_id']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . (string)$this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . (string)$this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . (int)$this->request->get['page']; + } + + $data['action'] = $this->url->link('design/seo_url.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['seo_urls'] = []; + + $filter_data = [ + 'filter_keyword' => $filter_keyword, + 'filter_key' => $filter_key, + 'filter_value' => $filter_value, + 'filter_store_id' => $filter_store_id, + 'filter_language_id' => $filter_language_id, + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('design/seo_url'); + $this->load->model('localisation/language'); + + $seo_url_total = $this->model_design_seo_url->getTotalSeoUrls($filter_data); + + $results = $this->model_design_seo_url->getSeoUrls($filter_data); + + foreach ($results as $result) { + $language_info = $this->model_localisation_language->getLanguage($result['language_id']); + + if ($language_info) { + $code = $language_info['code']; + $image = $language_info['image']; + } else { + $code = ''; + $image = ''; + } + + $data['seo_urls'][] = [ + 'seo_url_id' => $result['seo_url_id'], + 'keyword' => $result['keyword'], + 'image' => $image, + 'language' => $code, + 'key' => $result['key'], + 'value' => $result['value'], + 'sort_order' => $result['sort_order'], + 'store' => $result['store_id'] ? $result['store'] : $this->language->get('text_default'), + 'edit' => $this->url->link('design/seo_url.form', 'user_token=' . $this->session->data['user_token'] . '&seo_url_id=' . $result['seo_url_id'] . $url) + ]; + } + + $url = ''; + + if (isset($this->request->get['filter_keyword'])) { + $url .= '&filter_keyword=' . urlencode(html_entity_decode((string)$this->request->get['filter_keyword'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_key'])) { + $url .= '&filter_key=' . urlencode(html_entity_decode((string)$this->request->get['filter_key'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_value'])) { + $url .= '&filter_value=' . urlencode(html_entity_decode((string)$this->request->get['filter_value'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_store_id'])) { + $url .= '&filter_store_id=' . (int)$this->request->get['filter_store_id']; + } + + if (isset($this->request->get['filter_language_id'])) { + $url .= '&filter_language_id=' . (int)$this->request->get['filter_language_id']; + } + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_keyword'] = $this->url->link('design/seo_url.list', 'user_token=' . $this->session->data['user_token'] . '&sort=keyword' . $url); + $data['sort_key'] = $this->url->link('design/seo_url.list', 'user_token=' . $this->session->data['user_token'] . '&sort=key' . $url); + $data['sort_value'] = $this->url->link('design/seo_url.list', 'user_token=' . $this->session->data['user_token'] . '&sort=value' . $url); + $data['sort_sort_order'] = $this->url->link('design/seo_url.list', 'user_token=' . $this->session->data['user_token'] . '&sort=sort_order' . $url); + $data['sort_store'] = $this->url->link('design/seo_url.list', 'user_token=' . $this->session->data['user_token'] . '&sort=store' . $url); + $data['sort_language'] = $this->url->link('design/seo_url.list', 'user_token=' . $this->session->data['user_token'] . '&sort=language' . $url); + + $url = ''; + + if (isset($this->request->get['filter_keyword'])) { + $url .= '&filter_keyword=' . urlencode(html_entity_decode((string)$this->request->get['filter_keyword'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_key'])) { + $url .= '&filter_key=' . urlencode(html_entity_decode((string)$this->request->get['filter_key'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_value'])) { + $url .= '&filter_value=' . urlencode(html_entity_decode((string)$this->request->get['filter_value'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_store_id'])) { + $url .= '&filter_store_id=' . (int)$this->request->get['filter_store_id']; + } + + if (isset($this->request->get['filter_language_id'])) { + $url .= '&filter_language_id=' . (int)$this->request->get['filter_language_id']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . (string)$this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . (string)$this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $seo_url_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('design/seo_url.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($seo_url_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($seo_url_total - $this->config->get('config_pagination_admin'))) ? $seo_url_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $seo_url_total, ceil($seo_url_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('design/seo_url_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('design/seo_url'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['seo_url_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['filter_keyword'])) { + $url .= '&filter_keyword=' . urlencode(html_entity_decode((string)$this->request->get['filter_keyword'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_key'])) { + $url .= '&filter_key=' . urlencode(html_entity_decode((string)$this->request->get['filter_key'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_value'])) { + $url .= '&filter_value=' . urlencode(html_entity_decode((string)$this->request->get['filter_value'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_store_id'])) { + $url .= '&filter_store_id=' . (int)$this->request->get['filter_store_id']; + } + + if (isset($this->request->get['filter_language_id'])) { + $url .= '&filter_language_id=' . (int)$this->request->get['filter_language_id']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . (string)$this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . (string)$this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . (int)$this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('design/seo_url', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('design/seo_url.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('design/seo_url', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['seo_url_id'])) { + $this->load->model('design/seo_url'); + + $seo_url_info = $this->model_design_seo_url->getSeoUrl($this->request->get['seo_url_id']); + } + + if (isset($this->request->get['seo_url_id'])) { + $data['seo_url_id'] = (int)$this->request->get['seo_url_id']; + } else { + $data['seo_url_id'] = 0; + } + + $data['stores'] = []; + + $data['stores'][] = [ + 'store_id' => 0, + 'name' => $this->language->get('text_default') + ]; + + $this->load->model('setting/store'); + + $stores = $this->model_setting_store->getStores(); + + foreach ($stores as $store) { + $data['stores'][] = [ + 'store_id' => $store['store_id'], + 'name' => $store['name'] + ]; + } + + if (!empty($seo_url_info)) { + $data['store_id'] = $seo_url_info['store_id']; + } else { + $data['store_id'] = ''; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (!empty($seo_url_info)) { + $data['language_id'] = $seo_url_info['language_id']; + } else { + $data['language_id'] = ''; + } + + if (!empty($seo_url_info)) { + $data['key'] = $seo_url_info['key']; + } else { + $data['key'] = ''; + } + + if (!empty($seo_url_info)) { + $data['value'] = $seo_url_info['value']; + } else { + $data['value'] = ''; + } + + if (!empty($seo_url_info)) { + $data['keyword'] = $seo_url_info['keyword']; + } else { + $data['keyword'] = ''; + } + + if (!empty($seo_url_info)) { + $data['sort_order'] = $seo_url_info['sort_order']; + } else { + $data['sort_order'] = ''; + } + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('design/seo_url_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('design/seo_url'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'design/seo_url')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if ((oc_strlen($this->request->post['key']) < 1) || (oc_strlen($this->request->post['key']) > 64)) { + $json['error']['key'] = $this->language->get('error_key'); + } + + if ((oc_strlen($this->request->post['value']) < 1) || (oc_strlen($this->request->post['value']) > 255)) { + $json['error']['value'] = $this->language->get('error_value'); + } + + $this->load->model('design/seo_url'); + + // Check if there is already a key value pair on the same store using the same language + $seo_url_info = $this->model_design_seo_url->getSeoUrlByKeyValue($this->request->post['key'], $this->request->post['value'], $this->request->post['store_id'], $this->request->post['language_id']); + + if ($seo_url_info && (!isset($this->request->post['seo_url_id']) || $seo_url_info['seo_url_id'] != (int)$this->request->post['seo_url_id'])) { + $json['error']['value'] = $this->language->get('error_value_exists'); + } + + // Split keywords by / so we can validate each keyword + $keywords = explode('/', $this->request->post['keyword']); + + foreach ($keywords as $keyword) { + if ((oc_strlen(trim($keyword)) < 1) || (oc_strlen($keyword) > 64)) { + $json['error']['keyword'] = $this->language->get('error_keyword'); + } + + if (preg_match('/[^a-zA-Z0-9\/_-]|[\p{Cyrillic}]+/u', $keyword)) { + $json['error']['keyword'] = $this->language->get('error_keyword_character'); + } + } + + // Check if keyword already exists and on the same store as long as the keyword matches the key / value pair + $seo_url_info = $this->model_design_seo_url->getSeoUrlByKeyword($this->request->post['keyword'], $this->request->post['store_id']); + + if ($seo_url_info && (($seo_url_info['key'] != $this->request->post['key']) || ($seo_url_info['value'] != $this->request->post['value']))) { + $json['error']['keyword'] = $this->language->get('error_keyword_exists'); + } + + if (!$json) { + if (!$this->request->post['seo_url_id']) { + $json['seo_url_id'] = $this->model_design_seo_url->addSeoUrl($this->request->post); + } else { + $this->model_design_seo_url->editSeoUrl($this->request->post['seo_url_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('design/seo_url'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'design/seo_url')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('design/seo_url'); + + foreach ($selected as $seo_url_id) { + $this->model_design_seo_url->deleteSeoUrl($seo_url_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/design/theme.php b/admininistrator/controller/design/theme.php new file mode 100644 index 0000000..62b1b54 --- /dev/null +++ b/admininistrator/controller/design/theme.php @@ -0,0 +1,432 @@ +load->language('design/theme'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('design/theme', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['stores'] = []; + + $this->load->model('setting/store'); + + $results = $this->model_setting_store->getStores(); + + foreach ($results as $result) { + $data['stores'][] = [ + 'store_id' => $result['store_id'], + 'name' => $result['name'] + ]; + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('design/theme', $data)); + } + + /** + * @return void + */ + public function history(): void { + $this->load->language('design/theme'); + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $limit = 10; + + $data['histories'] = []; + + $this->load->model('design/theme'); + $this->load->model('setting/store'); + + $history_total = $this->model_design_theme->getTotalThemes(); + + $results = $this->model_design_theme->getThemes(($page - 1) * $limit, $limit); + + foreach ($results as $result) { + $store_info = $this->model_setting_store->getStore($result['store_id']); + + if ($store_info) { + $store = $store_info['name']; + } else { + $store = ''; + } + + $data['histories'][] = [ + 'store_id' => $result['store_id'], + 'store' => ($result['store_id'] ? $store : $this->language->get('text_default')), + 'route' => $result['route'], + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])), + 'edit' => $this->url->link('design/theme.template', 'user_token=' . $this->session->data['user_token']), + 'delete' => $this->url->link('design/theme.delete', 'user_token=' . $this->session->data['user_token'] . '&theme_id=' . $result['theme_id']) + ]; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $history_total, + 'page' => $page, + 'limit' => $limit, + 'url' => $this->url->link('design/theme.history', 'user_token=' . $this->session->data['user_token'] . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($history_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($history_total - $limit)) ? $history_total : ((($page - 1) * $limit) + $limit), $history_total, ceil($history_total / $limit)); + + $this->response->setOutput($this->load->view('design/theme_history', $data)); + } + + /** + * @return void + */ + public function path(): void { + $this->load->language('design/theme'); + + $json = []; + + if (isset($this->request->get['store_id'])) { + $store_id = (int)$this->request->get['store_id']; + } else { + $store_id = 0; + } + + if (isset($this->request->get['path'])) { + $path = $this->request->get['path']; + } else { + $path = ''; + } + + // Default templates + $json['directory'] = []; + $json['file'] = []; + + $directory = DIR_CATALOG . 'view/template'; + + if (substr(str_replace('\\', '/', realpath($directory . '/' . $path)), 0, strlen($directory)) == $directory) { + // We grab the files from the default template directory + $files = glob(rtrim(DIR_CATALOG . 'view/template/' . $path, '/') . '/*'); + + foreach ($files as $file) { + if (is_dir($file)) { + $json['directory'][] = [ + 'name' => basename($file), + 'path' => trim($path . '/' . basename($file), '/') + ]; + } + + if (is_file($file)) { + $json['file'][] = [ + 'name' => basename($file), + 'path' => trim($path . '/' . basename($file), '/') + ]; + } + } + } + + if (!$path) { + $json['directory'][] = [ + 'name' => $this->language->get('text_extension'), + 'path' => 'extension', + ]; + } + + // Extension templates + $json['extension'] = []; + + // List all the extensions + if ($path == 'extension') { + $directories = glob(DIR_EXTENSION . '*', GLOB_ONLYDIR); + + foreach ($directories as $directory) { + $json['extension']['directory'][] = [ + 'name' => basename($directory), + 'path' => 'extension/' . basename($directory) + ]; + } + } + + // List extension sub directories directories + if (substr($path, 0, 10) == 'extension/') { + $route = ''; + + $part = explode('/', $path); + + $extension = $part[1]; + + unset($part[0]); + unset($part[1]); + + if (isset($part[2])) { + $route = implode('/', $part); + } + + $safe = true; + + if (substr(str_replace('\\', '/', realpath(DIR_EXTENSION . $extension)), 0, strlen(DIR_EXTENSION)) != DIR_EXTENSION) { + $safe = false; + } + + $directory = DIR_EXTENSION . $extension . '/catalog/view/template'; + + if (substr(str_replace('\\', '/', realpath($directory . '/' . $route)), 0, strlen($directory)) != $directory) { + $safe = false; + } + + if ($safe) { + $files = glob(rtrim(DIR_EXTENSION . $extension . '/catalog/view/template/' . $route, '/') . '/*'); + + sort($files); + + foreach ($files as $file) { + if (is_dir($file)) { + $json['extension']['directory'][] = [ + 'name' => basename($file), + 'path' => $path . '/' . basename($file) + ]; + } + + if (is_file($file)) { + $json['extension']['file'][] = [ + 'name' => basename($file), + 'path' => $path . '/' . basename($file) + ]; + } + } + } + } + + if ($path) { + $json['back'] = [ + 'name' => $this->language->get('button_back'), + 'path' => urlencode(substr($path, 0, strrpos($path, '/'))), + ]; + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function template(): void { + $this->load->language('design/theme'); + + $json = []; + + if (isset($this->request->get['store_id'])) { + $store_id = (int)$this->request->get['store_id']; + } else { + $store_id = 0; + } + + if (isset($this->request->get['path'])) { + $path = $this->request->get['path']; + } else { + $path = ''; + } + + // Default template load + $directory = DIR_CATALOG . 'view/template'; + + if (is_file($directory . '/' . $path) && (substr(str_replace('\\', '/', realpath($directory . '/' . $path)), 0, strlen($directory)) == $directory)) { + $json['code'] = file_get_contents(DIR_CATALOG . 'view/template/' . $path); + } + + // Extension template load + if (substr($path, 0, 10) == 'extension/') { + $part = explode('/', $path); + + $extension = $part[1]; + + unset($part[0]); + unset($part[1]); + + $route = implode('/', $part); + + $safe = true; + + if (substr(str_replace('\\', '/', realpath(DIR_EXTENSION . $extension)), 0, strlen(DIR_EXTENSION)) != DIR_EXTENSION) { + $safe = false; + } + + $directory = DIR_EXTENSION . $extension . '/catalog/view/template'; + + if (substr(str_replace('\\', '/', realpath($directory . '/' . $route)), 0, strlen($directory)) != $directory) { + $safe = false; + } + + if ($safe && is_file($directory . '/' . $route)) { + $json['code'] = file_get_contents($directory . '/' . $route); + } + } + + // Custom template load + $this->load->model('design/theme'); + + $theme_info = $this->model_design_theme->getTheme($store_id, $path); + + if ($theme_info) { + $json['code'] = html_entity_decode($theme_info['code']); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('design/theme'); + + $json = []; + + if (isset($this->request->get['store_id'])) { + $store_id = (int)$this->request->get['store_id']; + } else { + $store_id = 0; + } + + if (isset($this->request->get['path'])) { + $path = $this->request->get['path']; + } else { + $path = ''; + } + + // Check user has permission + if (!$this->user->hasPermission('modify', 'design/theme')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (substr($path, -5) != '.twig') { + $json['error'] = $this->language->get('error_twig'); + } + + if (!$json) { + $this->load->model('design/theme'); + + $pos = strpos($path, '.'); + + $this->model_design_theme->editTheme($store_id, ($pos !== false) ? substr($path, 0, $pos) : $path, $this->request->post['code']); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function reset(): void { + $json = []; + + if (isset($this->request->get['store_id'])) { + $store_id = (int)$this->request->get['store_id']; + } else { + $store_id = 0; + } + + if (isset($this->request->get['path'])) { + $path = $this->request->get['path']; + } else { + $path = ''; + } + + $directory = DIR_CATALOG . 'view/template'; + + if (is_file($directory . '/' . $path) && (substr(str_replace('\\', '/', realpath($directory . '/' . $path)), 0, strlen($directory)) == $directory)) { + $json['code'] = file_get_contents(DIR_CATALOG . 'view/template/' . $path); + } + + // Extension template load + if (substr($path, 0, 10) == 'extension/') { + $part = explode('/', $path); + + $extension = $part[1]; + + unset($part[0]); + unset($part[1]); + + $route = implode('/', $part); + + $safe = true; + + if (substr(str_replace('\\', '/', realpath(DIR_EXTENSION . $extension)), 0, strlen(DIR_EXTENSION)) != DIR_EXTENSION) { + $safe = false; + } + + $directory = DIR_EXTENSION . $extension . '/catalog/view/template'; + + if (substr(str_replace('\\', '/', realpath($directory . '/' . $route)), 0, strlen($directory)) != $directory) { + $safe = false; + } + + if ($safe && is_file($directory . '/' . $route)) { + $json['code'] = file_get_contents($directory . '/' . $route); + } + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('design/theme'); + + $json = []; + + if (isset($this->request->get['theme_id'])) { + $theme_id = (int)$this->request->get['theme_id']; + } else { + $theme_id = 0; + } + + // Check user has permission + if (!$this->user->hasPermission('modify', 'design/theme')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('design/theme'); + + $this->model_design_theme->deleteTheme($theme_id); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/design/translation.php b/admininistrator/controller/design/translation.php new file mode 100644 index 0000000..c18ac9d --- /dev/null +++ b/admininistrator/controller/design/translation.php @@ -0,0 +1,459 @@ +load->language('design/translation'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('design/translation', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('design/translation.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('design/translation.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('design/translation', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('design/translation'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'store'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('design/translation.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $this->load->model('localisation/language'); + + $data['translations'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('design/translation'); + + $translation_total = $this->model_design_translation->getTotalTranslations(); + + $results = $this->model_design_translation->getTranslations($filter_data); + + foreach ($results as $result) { + $language_info = $this->model_localisation_language->getLanguage($result['language_id']); + + if ($language_info) { + $code = $language_info['code']; + $image = $language_info['image']; + } else { + $code = ''; + $image = ''; + } + + $data['translations'][] = [ + 'translation_id' => $result['translation_id'], + 'store' => ($result['store_id'] ? $result['store'] : $this->language->get('text_default')), + 'route' => $result['route'], + 'image' => $image, + 'language' => $code, + 'key' => $result['key'], + 'value' => $result['value'], + 'edit' => $this->url->link('design/translation.form', 'user_token=' . $this->session->data['user_token'] . '&translation_id=' . $result['translation_id']) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_store'] = $this->url->link('design/translation.list', 'user_token=' . $this->session->data['user_token'] . '&sort=store' . $url); + $data['sort_language'] = $this->url->link('design/translation.list', 'user_token=' . $this->session->data['user_token'] . '&sort=language' . $url); + $data['sort_route'] = $this->url->link('design/translation.list', 'user_token=' . $this->session->data['user_token'] . '&sort=route' . $url); + $data['sort_key'] = $this->url->link('design/translation.list', 'user_token=' . $this->session->data['user_token'] . '&sort=key' . $url); + $data['sort_value'] = $this->url->link('design/translation.list', 'user_token=' . $this->session->data['user_token'] . '&sort=value' . $url); + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $translation_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('design/translation.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($translation_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($translation_total - $this->config->get('config_pagination_admin'))) ? $translation_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $translation_total, ceil($translation_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('design/translation_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('design/translation'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['translation_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('design/translation', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('design/translation.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('design/translation', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['translation_id'])) { + $this->load->model('design/translation'); + + $translation_info = $this->model_design_translation->getTranslation($this->request->get['translation_id']); + } + + if (isset($this->request->get['translation_id'])) { + $data['translation_id'] = (int)$this->request->get['translation_id']; + } else { + $data['translation_id'] = 0; + } + + $this->load->model('setting/store'); + + $data['stores'] = $this->model_setting_store->getStores(); + + if (!empty($translation_info)) { + $data['store_id'] = $translation_info['store_id']; + } else { + $data['store_id'] = ''; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (!empty($translation_info)) { + $data['language_id'] = $translation_info['language_id']; + } else { + $data['language_id'] = ''; + } + + if (!empty($translation_info)) { + $data['route'] = $translation_info['route']; + } else { + $data['route'] = ''; + } + + if (!empty($translation_info)) { + $data['key'] = $translation_info['key']; + } else { + $data['key'] = ''; + } + + if (!empty($translation_info)) { + $data['value'] = $translation_info['value']; + } else { + $data['value'] = ''; + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('design/translation_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('design/translation'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'design/translation')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if ((oc_strlen($this->request->post['key']) < 3) || (oc_strlen($this->request->post['key']) > 64)) { + $json['error']['key'] = $this->language->get('error_key'); + } + + if (!$json) { + $this->load->model('design/translation'); + + if (!$this->request->post['translation_id']) { + $json['translation_id'] = $this->model_design_translation->addTranslation($this->request->post); + } else { + $this->model_design_translation->editTranslation($this->request->post['translation_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('design/translation'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'design/translation')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('design/translation'); + + foreach ($selected as $translation_id) { + $this->model_design_translation->deleteTranslation($translation_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function path(): void { + $this->load->language('design/translation'); + + $json = []; + + if (isset($this->request->get['language_id'])) { + $language_id = (int)$this->request->get['language_id']; + } else { + $language_id = 0; + } + + $this->load->model('localisation/language'); + + $language_info = $this->model_localisation_language->getLanguage($language_id); + + if (!empty($language_info)) { + $path = glob(DIR_CATALOG . 'language/' . $language_info['code'] . '/*'); + + while (count($path) != 0) { + $next = array_shift($path); + + foreach ((array)glob($next . '/*') as $file) { + if (is_dir($file)) { + $path[] = $file; + } + + if (substr($file, -4) == '.php') { + $json[] = substr(substr($file, strlen(DIR_CATALOG . 'language/' . $language_info['code'] . '/')), 0, -4); + } + } + } + + $path = glob(DIR_EXTENSION . '*/catalog/language/' . $language_info['code'] . '/*'); + + while (count($path) != 0) { + $next = array_shift($path); + + foreach ((array)glob($next . '/*') as $file) { + if (is_dir($file)) { + $path[] = $file; + } + + if (substr($file, -4) == '.php') { + $new_path = substr($file, strlen(DIR_EXTENSION)); + + $code = substr($new_path, 0, strpos($new_path, '/')); + + $length = strlen(DIR_EXTENSION . $code . '/catalog/language/' . $language_info['code'] . '/'); + + $route = substr(substr($file, $length), 0, -4); + + $json[] = 'extension/' . $code . '/' . $route; + } + } + } + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function translation(): void { + $this->load->language('design/translation'); + + $json = []; + + if (isset($this->request->get['store_id'])) { + $store_id = (int)$this->request->get['store_id']; + } else { + $store_id = 0; + } + + if (isset($this->request->get['language_id'])) { + $language_id = (int)$this->request->get['language_id']; + } else { + $language_id = 0; + } + + if (isset($this->request->get['path'])) { + $route = $this->request->get['path']; + } else { + $route = ''; + } + + $this->load->model('localisation/language'); + + $language_info = $this->model_localisation_language->getLanguage($language_id); + + $part = explode('/', $route); + + if ($part[0] != 'extension') { + $directory = DIR_CATALOG . 'language/'; + } else { + $directory = DIR_EXTENSION . $part[1] . '/catalog/language/'; + + array_shift($part); + // Don't remove. Required for extension route. + array_shift($part); + + $route = implode('/', $part); + } + + if ($language_info && is_file($directory . $language_info['code'] . '/' . $route . '.php') && substr(str_replace('\\', '/', realpath($directory . $language_info['code'] . '/' . $route . '.php')), 0, strlen($directory)) == str_replace('\\', '/', $directory)) { + $_ = []; + + include($directory . $language_info['code'] . '/' . $route . '.php'); + + foreach ($_ as $key => $value) { + $json[] = [ + 'key' => $key, + 'value' => $value + ]; + } + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/error/exception.php b/admininistrator/controller/error/exception.php new file mode 100644 index 0000000..3693b9f --- /dev/null +++ b/admininistrator/controller/error/exception.php @@ -0,0 +1,40 @@ +load->language('error/exception'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('error/exception', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('error/exception', $data)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/error/not_found.php b/admininistrator/controller/error/not_found.php new file mode 100644 index 0000000..983d1c5 --- /dev/null +++ b/admininistrator/controller/error/not_found.php @@ -0,0 +1,35 @@ +load->language('error/not_found'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', isset($this->session->data['user_token']) ? 'user_token=' . $this->session->data['user_token'] : '') + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('error/not_found', isset($this->session->data['user_token']) ? 'user_token=' . $this->session->data['user_token'] : '') + ]; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('error/not_found', $data)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/error/permission.php b/admininistrator/controller/error/permission.php new file mode 100644 index 0000000..07cda07 --- /dev/null +++ b/admininistrator/controller/error/permission.php @@ -0,0 +1,35 @@ +load->language('error/permission'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link($this->request->get['route'], 'user_token=' . $this->session->data['user_token']) + ]; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('error/permission', $data)); + } +} diff --git a/admininistrator/controller/event/currency.php b/admininistrator/controller/event/currency.php new file mode 100644 index 0000000..c53a4fd --- /dev/null +++ b/admininistrator/controller/event/currency.php @@ -0,0 +1,36 @@ +config->get('config_currency'); + } + + $this->load->model('setting/extension'); + + $extension_info = $this->model_setting_extension->getExtensionByCode('currency', $this->config->get('config_currency_engine')); + + if ($extension_info) { + $this->load->controller('extension/' . $extension_info['extension'] . '/currency/' . $extension_info['code'] . '.currency', $currency); + } + } +} diff --git a/admininistrator/controller/event/debug.php b/admininistrator/controller/event/debug.php new file mode 100644 index 0000000..573508d --- /dev/null +++ b/admininistrator/controller/event/debug.php @@ -0,0 +1,40 @@ +session->data['debug'][$route] = microtime(); + } + } + + /** + * @param string $route + * @param array $args + * @param mixed $output + * + * @return void + */ + public function after(string $route, array &$args, mixed &$output): void { + if ($route == 'common/home') { // add the route you want to test + if (isset($this->session->data['debug'][$route])) { + $log_data = [ + 'route' => $route, + 'time' => microtime() - $this->session->data['debug'][$route] + ]; + + $this->log->write($route); + } + } + } +} diff --git a/admininistrator/controller/event/language.php b/admininistrator/controller/event/language.php new file mode 100644 index 0000000..84e55ea --- /dev/null +++ b/admininistrator/controller/event/language.php @@ -0,0 +1,61 @@ +language->all() as $key => $value) { + if (!isset($args[$key])) { + $args[$key] = $value; + } + } + } + + // controller/*/before + // 1. Before controller load store all current loaded language data. + /** + * @param string $route + * @param array $args + * + * @return void + */ + public function before(string &$route, array &$args): void { + $data = $this->language->all(); + + if ($data) { + $this->language->set('backup', json_encode($data)); + } + } + + // controller/*/after + // 2. After controller load restore old language data. + /** + * @param string $route + * @param array $args + * @param mixed $output + * + * @return void + */ + public function after(string &$route, array &$args, mixed &$output): void { + $data = json_decode($this->language->get('backup'), true); + + if (is_array($data)) { + $this->language->clear(); + + foreach ($data as $key => $value) { + $this->language->set($key, $value); + } + } + } +} \ No newline at end of file diff --git a/admininistrator/controller/event/statistics.php b/admininistrator/controller/event/statistics.php new file mode 100644 index 0000000..afd8ee8 --- /dev/null +++ b/admininistrator/controller/event/statistics.php @@ -0,0 +1,67 @@ +load->model('report/statistics'); + + $this->model_report_statistics->addValue('review', 1); + } + + // admin/model/catalog/review/deleteReview/after + + /** + * @param string $route + * @param array $args + * @param mixed $output + * + * @return void + */ + public function deleteReview(string &$route, array &$args, mixed &$output): void { + $this->load->model('report/statistics'); + + $this->model_report_statistics->removeValue('review', 1); + } + + // admin/model/sale/returns/addReturn/after + + /** + * @param string $route + * @param array $args + * @param mixed $output + * + * @return void + */ + public function addReturn(string &$route, array &$args, mixed &$output): void { + $this->load->model('report/statistics'); + + $this->model_report_statistics->addValue('returns', 1); + } + + // admin/model/sale/returns/deleteReturn/after + + /** + * @param string $route + * @param array $args + * @param mixed $output + * + * @return void + */ + public function deleteReturn(string &$route, array &$args, mixed &$output): void { + $this->load->model('report/statistics'); + + $this->model_report_statistics->removeValue('returns', 1); + } +} diff --git a/admininistrator/controller/extension/analytics.php b/admininistrator/controller/extension/analytics.php new file mode 100644 index 0000000..ecaba0d --- /dev/null +++ b/admininistrator/controller/extension/analytics.php @@ -0,0 +1,184 @@ +response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + $this->load->language('extension/analytics'); + + // Promotion + $data['promotion'] = $this->load->controller('marketplace/promotion'); + + $available = []; + + $this->load->model('setting/extension'); + + $results = $this->model_setting_extension->getPaths('%/admin/controller/analytics/%.php'); + + foreach ($results as $result) { + $available[] = basename($result['path'], '.php'); + } + + $installed = []; + + $extensions = $this->model_setting_extension->getExtensionsByType('analytics'); + + foreach ($extensions as $extension) { + if (in_array($extension['code'], $available)) { + $installed[] = $extension['code']; + } else { + // Uninstall any missing extensions + $this->model_setting_extension->uninstall('analytics', $extension['code']); + } + } + + $this->load->model('setting/store'); + $this->load->model('setting/setting'); + + $stores = $this->model_setting_store->getStores(); + + $data['extensions'] = []; + + $this->load->model('setting/extension'); + + if ($results) { + foreach ($results as $result) { + $extension = substr($result['path'], 0, strpos($result['path'], '/')); + + $code = basename($result['path'], '.php'); + + $this->load->language('extension/' . $extension . '/analytics/' . $code, $code); + + $store_data = []; + + $store_data[] = [ + 'name' => $this->config->get('config_name'), + 'edit' => $this->url->link('extension/' . $extension . '/analytics/' . $code, 'user_token=' . $this->session->data['user_token'] . '&store_id=0'), + 'status' => $this->config->get('analytics_' . $code . '_status') ? $this->language->get('text_enabled') : $this->language->get('text_disabled') + ]; + + foreach ($stores as $store) { + $store_data[] = [ + 'name' => $store['name'], + 'edit' => $this->url->link('extension/' . $extension . '/analytics/' . $code, 'user_token=' . $this->session->data['user_token'] . '&store_id=' . $store['store_id']), + 'status' => $this->model_setting_setting->getValue('analytics_' . $code . '_status', $store['store_id']) ? $this->language->get('text_enabled') : $this->language->get('text_disabled') + ]; + } + + $data['extensions'][] = [ + 'name' => $this->language->get($code . '_heading_title'), + 'install' => $this->url->link('extension/analytics.install', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'uninstall' => $this->url->link('extension/analytics.uninstall', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'installed' => in_array($code, $installed), + 'store' => $store_data + ]; + } + } + + return $this->load->view('extension/analytics', $data); + } + + /** + * @return void + */ + public function install(): void { + $this->load->language('extension/analytics'); + + $json = []; + + if (isset($this->request->get['extension'])) { + $extension = basename($this->request->get['extension']); + } else { + $extension = ''; + } + + if (isset($this->request->get['code'])) { + $code = basename($this->request->get['code']); + } else { + $code = ''; + } + + if (!$this->user->hasPermission('modify', 'extension/analytics')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!is_file(DIR_EXTENSION . $extension . '/admin/controller/analytics/' . $code . '.php')) { + $json['error'] = $this->language->get('error_extension'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->install('analytics', $extension, $code); + + $this->load->model('user/user_group'); + + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'access', 'extension/' . $extension . '/analytics/' . $code); + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'modify', 'extension/' . $extension . '/analytics/' . $code); + + $namespace = str_replace(['_', '/'], ['', '\\'], ucwords($extension, '_/')); + + // Register controllers, models and system extension folders + $this->autoloader->register('Opencart\Admin\Controller\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/controller/'); + $this->autoloader->register('Opencart\Admin\Model\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/model/'); + $this->autoloader->register('Opencart\System\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/system/'); + + // Template directory + $this->template->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/view/template/'); + + // Language directory + $this->language->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/language/'); + + // Config directory + $this->config->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/system/config/'); + + // Call install method if it exists + $this->load->controller('extension/' . $extension . '/analytics/' . $code . '.install'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function uninstall(): void { + $this->load->language('extension/analytics'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'extension/analytics')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->uninstall('analytics', $this->request->get['code']); + + // Call uninstall method if it exists + $this->load->controller('extension/' . $this->request->get['extension'] . '/analytics/' . $this->request->get['code'] . '.uninstall'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/extension/captcha.php b/admininistrator/controller/extension/captcha.php new file mode 100644 index 0000000..65f525a --- /dev/null +++ b/admininistrator/controller/extension/captcha.php @@ -0,0 +1,161 @@ +response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + // Had top load again because the method is called directly. + $this->load->language('extension/captcha'); + + $available = []; + + $this->load->model('setting/extension'); + + $results = $this->model_setting_extension->getPaths('%/admin/controller/captcha/%.php'); + + foreach ($results as $result) { + $available[] = basename($result['path'], '.php'); + } + + $installed = []; + + $extensions = $this->model_setting_extension->getExtensionsByType('captcha'); + + foreach ($extensions as $extension) { + if (in_array($extension['code'], $available)) { + $installed[] = $extension['code']; + } else { + $this->model_setting_extension->uninstall('captcha', $extension['code']); + } + } + + $data['extensions'] = []; + + if ($results) { + foreach ($results as $result) { + $extension = substr($result['path'], 0, strpos($result['path'], '/')); + + $code = basename($result['path'], '.php'); + + $this->load->language('extension/' . $extension . '/captcha/' . $code, $code); + + $data['extensions'][] = [ + 'name' => $this->language->get($code . '_heading_title') . ($code == $this->config->get('config_captcha') ? $this->language->get('text_default') : ''), + 'status' => $this->config->get('captcha_' . $code . '_status') ? $this->language->get('text_enabled') : $this->language->get('text_disabled'), + 'install' => $this->url->link('extension/captcha.install', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'uninstall' => $this->url->link('extension/captcha.uninstall', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'installed' => in_array($code, $installed), + 'edit' => $this->url->link('extension/' . $extension . '/captcha/' . $code, 'user_token=' . $this->session->data['user_token']) + ]; + } + } + + $data['promotion'] = $this->load->controller('marketplace/promotion'); + + return $this->load->view('extension/captcha', $data); + } + + /** + * @return void + */ + public function install(): void { + $this->load->language('extension/captcha'); + + $json = []; + + if (isset($this->request->get['extension'])) { + $extension = basename($this->request->get['extension']); + } else { + $extension = ''; + } + + if (isset($this->request->get['code'])) { + $code = basename($this->request->get['code']); + } else { + $code = ''; + } + + if (!$this->user->hasPermission('modify', 'extension/captcha')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!is_file(DIR_EXTENSION . $extension . '/admin/controller/captcha/' . $code . '.php')) { + $json['error'] = $this->language->get('error_extension'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->install('captcha', $extension, $code); + + $this->load->model('user/user_group'); + + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'access', 'extension/' . $extension . '/captcha/' . $code); + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'modify', 'extension/' . $extension . '/captcha/' . $code); + + $namespace = str_replace(['_', '/'], ['', '\\'], ucwords($extension, '_/')); + + // Register controllers, models and system extension folders + $this->autoloader->register('Opencart\Admin\Controller\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/controller/'); + $this->autoloader->register('Opencart\Admin\Model\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/model/'); + $this->autoloader->register('Opencart\System\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/system/'); + + // Template directory + $this->template->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/view/template/'); + + // Language directory + $this->language->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/language/'); + + // Config directory + $this->config->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/system/config/'); + + // Call install method if it exists + $this->load->controller('extension/' . $extension . '/captcha/' . $code . '.install'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function uninstall(): void { + $this->load->language('extension/captcha'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'extension/captcha')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->uninstall('captcha', $this->request->get['code']); + + // Call uninstall method if it exists + $this->load->controller('extension/' . $this->request->get['extension'] . '/captcha/' . $this->request->get['code'] . '.uninstall'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/extension/currency.php b/admininistrator/controller/extension/currency.php new file mode 100644 index 0000000..df0814c --- /dev/null +++ b/admininistrator/controller/extension/currency.php @@ -0,0 +1,160 @@ +response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + $this->load->language('extension/currency'); + + $available = []; + + $this->load->model('setting/extension'); + + $results = $this->model_setting_extension->getPaths('%/admin/controller/currency/%.php'); + + foreach ($results as $result) { + $available[] = basename($result['path'], '.php'); + } + + $installed = []; + + $extensions = $this->model_setting_extension->getExtensionsByType('currency'); + + foreach ($extensions as $extension) { + if (in_array($extension['code'], $available)) { + $installed[] = $extension['code']; + } else { + $this->model_setting_extension->uninstall('currency', $extension['code']); + } + } + + $data['extensions'] = []; + + if ($results) { + foreach ($results as $result) { + $extension = substr($result['path'], 0, strpos($result['path'], '/')); + + $code = basename($result['path'], '.php'); + + $this->load->language('extension/' . $extension . '/currency/' . $code, $code); + + $data['extensions'][] = [ + 'name' => $this->language->get($code . '_heading_title') . ($code == $this->config->get('config_currency') ? $this->language->get('text_default') : ''), + 'status' => $this->config->get('currency_' . $code . '_status') ? $this->language->get('text_enabled') : $this->language->get('text_disabled'), + 'install' => $this->url->link('extension/currency.install', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'uninstall' => $this->url->link('extension/currency.uninstall', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'installed' => in_array($code, $installed), + 'edit' => $this->url->link('extension/' . $extension . '/currency/' . $code, 'user_token=' . $this->session->data['user_token']) + ]; + } + } + + $data['promotion'] = $this->load->controller('marketplace/promotion'); + + return $this->load->view('extension/currency', $data); + } + + /** + * @return void + */ + public function install(): void { + $this->load->language('extension/currency'); + + $json = []; + + if (isset($this->request->get['extension'])) { + $extension = basename($this->request->get['extension']); + } else { + $extension = ''; + } + + if (isset($this->request->get['code'])) { + $code = basename($this->request->get['code']); + } else { + $code = ''; + } + + if (!$this->user->hasPermission('modify', 'extension/currency')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!is_file(DIR_EXTENSION . $extension . '/admin/controller/currency/' . $code . '.php')) { + $json['error'] = $this->language->get('error_extension'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->install('currency', $extension, $code); + + $this->load->model('user/user_group'); + + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'access', 'extension/' . $extension . '/currency/' . $code); + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'modify', 'extension/' . $extension . '/currency/' . $code); + + $namespace = str_replace(['_', '/'], ['', '\\'], ucwords($extension, '_/')); + + // Register controllers, models and system extension folders + $this->autoloader->register('Opencart\Admin\Controller\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/controller/'); + $this->autoloader->register('Opencart\Admin\Model\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/model/'); + $this->autoloader->register('Opencart\System\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/system/'); + + // Template directory + $this->template->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/view/template/'); + + // Language directory + $this->language->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/language/'); + + // Config directory + $this->config->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/system/config/'); + + // Call install method if it exists + $this->load->controller('extension/' . $extension . '/currency/' . $code . '.install'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function uninstall(): void { + $this->load->language('extension/currency'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'extension/currency')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->uninstall('currency', $this->request->get['code']); + + // Call uninstall method if it exists + $this->load->controller('extension/' . $this->request->get['extension'] . '/currency/' . $this->request->get['code'] . '.uninstall'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/extension/dashboard.php b/admininistrator/controller/extension/dashboard.php new file mode 100644 index 0000000..4ce98ed --- /dev/null +++ b/admininistrator/controller/extension/dashboard.php @@ -0,0 +1,173 @@ +response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + $this->load->language('extension/dashboard'); + + $available = []; + + $this->load->model('setting/extension'); + + $results = $this->model_setting_extension->getPaths('%/admin/controller/dashboard/%.php'); + + foreach ($results as $result) { + $available[] = basename($result['path'], '.php'); + } + + $installed = []; + + $extensions = $this->model_setting_extension->getExtensionsByType('dashboard'); + + foreach ($extensions as $extension) { + if (in_array($extension['code'], $available)) { + $installed[] = $extension['code']; + } else { + $this->model_setting_extension->uninstall('dashboard', $extension['code']); + } + } + + $data['extensions'] = []; + + if ($results) { + foreach ($results as $result) { + $extension = substr($result['path'], 0, strpos($result['path'], '/')); + + $code = basename($result['path'], '.php'); + + $this->load->language('extension/' . $extension . '/dashboard/' . $code, $code); + + $data['extensions'][] = [ + 'name' => $this->language->get($code . '_heading_title'), + 'width' => $this->config->get('dashboard_' . $code . '_width'), + 'status' => $this->config->get('dashboard_' . $code . '_status') ? $this->language->get('text_enabled') : $this->language->get('text_disabled'), + 'sort_order' => $this->config->get('dashboard_' . $code . '_sort_order'), + 'install' => $this->url->link('extension/dashboard.install', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'uninstall' => $this->url->link('extension/dashboard.uninstall', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'installed' => in_array($code, $installed), + 'edit' => $this->url->link('extension/' . $extension . '/dashboard/' . $code, 'user_token=' . $this->session->data['user_token']) + ]; + } + } + + $data['promotion'] = $this->load->controller('marketplace/promotion'); + + return $this->load->view('extension/dashboard', $data); + } + + /** + * @return bool + */ + protected function validate(): bool { + if (!$this->user->hasPermission('modify', 'extension/dashboard')) { + $this->error['warning'] = $this->language->get('error_permission'); + } + + return !$this->error; + } + + /** + * @return void + */ + public function install(): void { + $this->load->language('extension/dashboard'); + + $json = []; + + if (isset($this->request->get['extension'])) { + $extension = basename($this->request->get['extension']); + } else { + $extension = ''; + } + + if (isset($this->request->get['code'])) { + $code = basename($this->request->get['code']); + } else { + $code = ''; + } + + if (!$this->user->hasPermission('modify', 'extension/dashboard')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!is_file(DIR_EXTENSION . $extension . '/admin/controller/dashboard/' . $code . '.php')) { + $json['error'] = $this->language->get('error_extension'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->install('dashboard', $extension, $code); + + $this->load->model('user/user_group'); + + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'access', 'extension/' . $extension . '/dashboard/' . $code); + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'modify', 'extension/' .$extension . '/dashboard/' . $code); + + $namespace = str_replace(['_', '/'], ['', '\\'], ucwords($extension, '_/')); + + // Register controllers, models and system extension folders + $this->autoloader->register('Opencart\Admin\Controller\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/controller/'); + $this->autoloader->register('Opencart\Admin\Model\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/model/'); + $this->autoloader->register('Opencart\System\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/system/'); + + // Template directory + $this->template->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/view/template/'); + + // Language directory + $this->language->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/language/'); + + // Config directory + $this->config->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/system/config/'); + + // Call install method if it exists + $this->load->controller('extension/' . $extension . '/dashboard/' . $code . '.install'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function uninstall(): void { + $this->load->language('extension/dashboard'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'extension/dashboard')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->uninstall('dashboard', $this->request->get['code']); + + // Call uninstall method if it exists + $this->load->controller('extension/' . $this->request->get['extension'] . '/dashboard/' . $this->request->get['code'] . '.uninstall'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/extension/feed.php b/admininistrator/controller/extension/feed.php new file mode 100644 index 0000000..323bd82 --- /dev/null +++ b/admininistrator/controller/extension/feed.php @@ -0,0 +1,171 @@ +response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + $this->load->language('extension/feed'); + + $available = []; + + $this->load->model('setting/extension'); + + $results = $this->model_setting_extension->getPaths('%/admin/controller/feed/%.php'); + + foreach ($results as $result) { + $available[] = basename($result['path'], '.php'); + } + + $installed = []; + + $extensions = $this->model_setting_extension->getExtensionsByType('feed'); + + foreach ($extensions as $extension) { + if (in_array($extension['code'], $available)) { + $installed[] = $extension['code']; + } else { + $this->model_setting_extension->uninstall('feed', $extension['code']); + } + } + + $data['extensions'] = []; + + if ($results) { + foreach ($results as $result) { + $extension = substr($result['path'], 0, strpos($result['path'], '/')); + + $code = basename($result['path'], '.php'); + + $this->load->language('extension/' . $extension . '/feed/' . $code, $code); + + $data['extensions'][] = [ + 'name' => $this->language->get($code . '_heading_title'), + 'status' => $this->config->get('feed_' . $code . '_status') ? $this->language->get('text_enabled') : $this->language->get('text_disabled'), + 'install' => $this->url->link('extension/feed.install', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'uninstall' => $this->url->link('extension/feed.uninstall', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'installed' => in_array($code, $installed), + 'edit' => $this->url->link('extension/' . $extension . '/feed/' . $code, 'user_token=' . $this->session->data['user_token']) + ]; + } + } + + $data['promotion'] = $this->load->controller('marketplace/promotion'); + + return $this->load->view('extension/feed', $data); + } + + /** + * @return bool + */ + protected function validate(): bool { + if (!$this->user->hasPermission('modify', 'extension/feed')) { + $this->error['warning'] = $this->language->get('error_permission'); + } + + return !$this->error; + } + + /** + * @return void + */ + public function install(): void { + $this->load->language('extension/feed'); + + $json = []; + + if (isset($this->request->get['extension'])) { + $extension = basename($this->request->get['extension']); + } else { + $extension = ''; + } + + if (isset($this->request->get['code'])) { + $code = basename($this->request->get['code']); + } else { + $code = ''; + } + + if (!$this->user->hasPermission('modify', 'extension/feed')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!is_file(DIR_EXTENSION . $extension . '/admin/controller/feed/' . $code . '.php')) { + $json['error'] = $this->language->get('error_extension'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->install('feed', $extension, $code); + + $this->load->model('user/user_group'); + + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'access', 'extension/' . $extension . '/feed/' . $code); + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'modify', 'extension/' . $extension . '/feed/' . $code); + + $namespace = str_replace(['_', '/'], ['', '\\'], ucwords($extension, '_/')); + + // Register controllers, models and system extension folders + $this->autoloader->register('Opencart\Admin\Controller\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/controller/'); + $this->autoloader->register('Opencart\Admin\Model\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/model/'); + $this->autoloader->register('Opencart\System\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/system/'); + + // Template directory + $this->template->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/view/template/'); + + // Language directory + $this->language->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/language/'); + + // Config directory + $this->config->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/system/config/'); + + // Call install method if it exists + $this->load->controller('extension/' . $extension . '/feed/' . $code . '.install'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function uninstall(): void { + $this->load->language('extension/feed'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'extension/feed')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->uninstall('feed', $this->request->get['code']); + + // Call uninstall method if it exists + $this->load->controller('extension/' . $this->request->get['extension'] . '/feed/' . $this->request->get['code'] . '.uninstall'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/extension/fraud.php b/admininistrator/controller/extension/fraud.php new file mode 100644 index 0000000..8886bdc --- /dev/null +++ b/admininistrator/controller/extension/fraud.php @@ -0,0 +1,160 @@ +response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + $this->load->language('extension/fraud'); + + $available = []; + + $results = $this->model_setting_extension->getPaths('%/admin/controller/fraud/%.php'); + + foreach ($results as $result) { + $available[] = basename($result['path'], '.php'); + } + + $installed = []; + + $this->load->model('setting/extension'); + + $extensions = $this->model_setting_extension->getExtensionsByType('fraud'); + + foreach ($extensions as $extension) { + if (in_array($extension['code'], $available)) { + $installed[] = $extension['code']; + } else { + $this->model_setting_extension->uninstall('fraud', $extension['code']); + } + } + + $data['extensions'] = []; + + if ($results) { + foreach ($results as $result) { + $extension = substr($result['path'], 0, strpos($result['path'], '/')); + + $code = basename($result['path'], '.php'); + + $this->load->language('extension/' . $extension . '/fraud/' . $code, $code); + + $data['extensions'][] = [ + 'name' => $this->language->get($code . '_heading_title'), + 'status' => $this->config->get('fraud_' . $code . '_status') ? $this->language->get('text_enabled') : $this->language->get('text_disabled'), + 'install' => $this->url->link('extension/fraud.install', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'uninstall' => $this->url->link('extension/fraud.uninstall', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'installed' => in_array($code, $installed), + 'edit' => $this->url->link('extension/' . $extension . '/fraud/' . $code, 'user_token=' . $this->session->data['user_token']) + ]; + } + } + + $data['promotion'] = $this->load->controller('marketplace/promotion'); + + return $this->load->view('extension/fraud', $data); + } + + /** + * @return void + */ + public function install(): void { + $this->load->language('extension/fraud'); + + $json = []; + + if (isset($this->request->get['extension'])) { + $extension = basename($this->request->get['extension']); + } else { + $extension = ''; + } + + if (isset($this->request->get['code'])) { + $code = basename($this->request->get['code']); + } else { + $code = ''; + } + + if (!$this->user->hasPermission('modify', 'extension/fraud')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!is_file(DIR_EXTENSION . $extension . '/admin/controller/fraud/' . $code . '.php')) { + $json['error'] = $this->language->get('error_extension'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->install('fraud', $extension, $code); + + $this->load->model('user/user_group'); + + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'access', 'extension/' . $extension . '/fraud/' . $code); + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'modify', 'extension/' . $extension . '/fraud/' . $code); + + $namespace = str_replace(['_', '/'], ['', '\\'], ucwords($extension, '_/')); + + // Register controllers, models and system extension folders + $this->autoloader->register('Opencart\Admin\Controller\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/controller/'); + $this->autoloader->register('Opencart\Admin\Model\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/model/'); + $this->autoloader->register('Opencart\System\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/system/'); + + // Template directory + $this->template->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/view/template/'); + + // Language directory + $this->language->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/language/'); + + // Config directory + $this->config->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/system/config/'); + + // Call install method if it exists + $this->load->controller('extension/' . $extension . '/fraud/' . $code . '.install'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function uninstall(): void { + $this->load->language('extension/fraud'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'extension/fraud')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->uninstall('fraud', $this->request->get['code']); + + // Call uninstall method if it exists + $this->load->controller('extension/' . $this->request->get['extension'] . '/fraud/' . $this->request->get['code'] . '.uninstall'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/extension/language.php b/admininistrator/controller/extension/language.php new file mode 100644 index 0000000..bba2f7b --- /dev/null +++ b/admininistrator/controller/extension/language.php @@ -0,0 +1,160 @@ +response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + $this->load->language('extension/language'); + + $available = []; + + $results = $this->model_setting_extension->getPaths('%/admin/controller/language/%.php'); + + foreach ($results as $result) { + $available[] = basename($result['path'], '.php'); + } + + $installed = []; + + $this->load->model('setting/extension'); + + $extensions = $this->model_setting_extension->getExtensionsByType('language'); + + foreach ($extensions as $extension) { + if (in_array($extension['code'], $available)) { + $installed[] = $extension['code']; + } else { + $this->model_setting_extension->uninstall('language', $extension['code']); + } + } + + $data['extensions'] = []; + + if ($results) { + foreach ($results as $result) { + $extension = substr($result['path'], 0, strpos($result['path'], '/')); + + $code = basename($result['path'], '.php'); + + $this->load->language('extension/' . $extension . '/language/' . $code, $code); + + $data['extensions'][] = [ + 'name' => $this->language->get($code . '_heading_title'), + 'status' => $this->config->get('language_' . $code . '_status') ? $this->language->get('text_enabled') : $this->language->get('text_disabled'), + 'install' => $this->url->link('extension/language.install', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'uninstall' => $this->url->link('extension/language.uninstall', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'installed' => in_array($code, $installed), + 'edit' => $this->url->link('extension/' . $extension . '/language/' . $code, 'user_token=' . $this->session->data['user_token']) + ]; + } + } + + $data['promotion'] = $this->load->controller('marketplace/promotion'); + + return $this->load->view('extension/language', $data); + } + + /** + * @return void + */ + public function install(): void { + $this->load->language('extension/language'); + + $json = []; + + if (isset($this->request->get['extension'])) { + $extension = basename((string)$this->request->get['extension']); + } else { + $extension = ''; + } + + if (isset($this->request->get['code'])) { + $code = basename((string)$this->request->get['code']); + } else { + $code = ''; + } + + if (!$this->user->hasPermission('modify', 'extension/language')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!is_file(DIR_EXTENSION . $extension . '/admin/controller/language/' . $code . '.php')) { + $json['error'] = $this->language->get('error_extension'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->install('language', $extension, $code); + + $this->load->model('user/user_group'); + + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'access', 'extension/' . $extension . '/language/' . $code); + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'modify', 'extension/' . $extension . '/language/' . $code); + + $namespace = str_replace(['_', '/'], ['', '\\'], ucwords($extension, '_/')); + + // Register controllers, models and system extension folders + $this->autoloader->register('Opencart\Admin\Controller\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/controller/'); + $this->autoloader->register('Opencart\Admin\Model\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/model/'); + $this->autoloader->register('Opencart\System\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/system/'); + + // Template directory + $this->template->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/view/template/'); + + // Language directory + $this->language->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/language/'); + + // Config directory + $this->config->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/system/config/'); + + // Call install method if it exists + $this->load->controller('extension/' . $extension . '/language/' . $code . '.install'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function uninstall(): void { + $this->load->language('extension/language'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'extension/language')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->uninstall('language', $this->request->get['code']); + + // Call uninstall method if it exists + $this->load->controller('extension/' . $this->request->get['extension'] . '/language/' . $this->request->get['code'] . '.uninstall'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/extension/marketplace.php b/admininistrator/controller/extension/marketplace.php new file mode 100644 index 0000000..0af88c1 --- /dev/null +++ b/admininistrator/controller/extension/marketplace.php @@ -0,0 +1,160 @@ +response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + $this->load->language('extension/marketplace'); + + $available = []; + + $results = $this->model_setting_extension->getPaths('%/admin/controller/marketplace/%.php'); + + foreach ($results as $result) { + $available[] = basename($result['path'], '.php'); + } + + $installed = []; + + $this->load->model('setting/extension'); + + $extensions = $this->model_setting_extension->getExtensionsByType('marketplace'); + + foreach ($extensions as $extension) { + if (in_array($extension['code'], $available)) { + $installed[] = $extension['code']; + } else { + $this->model_setting_extension->uninstall('marketplace', $extension['code']); + } + } + + $data['extensions'] = []; + + if ($results) { + foreach ($results as $result) { + $extension = substr($result['path'], 0, strpos($result['path'], '/')); + + $code = basename($result['path'], '.php'); + + $this->load->language('extension/' . $extension . '/marketplace/' . $code, $code); + + $data['extensions'][] = [ + 'name' => $this->language->get($code . '_heading_title'), + 'status' => $this->config->get('language_' . $code . '_status') ? $this->language->get('text_enabled') : $this->language->get('text_disabled'), + 'install' => $this->url->link('extension/marketplace.install', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'uninstall' => $this->url->link('extension/marketplace.uninstall', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'installed' => in_array($code, $installed), + 'edit' => $this->url->link('extension/' . $extension . '/marketplace/' . $code, 'user_token=' . $this->session->data['user_token']) + ]; + } + } + + $data['promotion'] = $this->load->controller('marketplace/promotion'); + + return $this->load->view('extension/marketplace', $data); + } + + /** + * @return void + */ + public function install(): void { + $this->load->language('extension/marketplace'); + + $json = []; + + if (isset($this->request->get['extension'])) { + $extension = basename((string)$this->request->get['extension']); + } else { + $extension = ''; + } + + if (isset($this->request->get['code'])) { + $code = basename((string)$this->request->get['code']); + } else { + $code = ''; + } + + if (!$this->user->hasPermission('modify', 'extension/marketplace')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!is_file(DIR_EXTENSION . $extension . '/admin/controller/marketplace/' . $code . '.php')) { + $json['error'] = $this->language->get('error_extension'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->install('marketplace', $extension, $code); + + $this->load->model('user/user_group'); + + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'access', 'extension/' . $extension . '/marketplace/' . $code); + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'modify', 'extension/' . $extension . '/marketplace/' . $code); + + $namespace = str_replace(['_', '/'], ['', '\\'], ucwords($extension, '_/')); + + // Register controllers, models and system extension folders + $this->autoloader->register('Opencart\Admin\Controller\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/controller/'); + $this->autoloader->register('Opencart\Admin\Model\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/model/'); + $this->autoloader->register('Opencart\System\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/system/'); + + // Template directory + $this->template->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/view/template/'); + + // Language directory + $this->language->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/language/'); + + // Config directory + $this->config->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/system/config/'); + + // Call install method if it exists + $this->load->controller('extension/' . $extension . '/marketplace/' . $code . '.install'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function uninstall(): void { + $this->load->language('extension/marketplace'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'extension/marketplace')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->uninstall('marketplace', $this->request->get['code']); + + // Call uninstall method if it exists + $this->load->controller('extension/' . $this->request->get['extension'] . '/marketplace/' . $this->request->get['code'] . '.uninstall'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/extension/module.php b/admininistrator/controller/extension/module.php new file mode 100644 index 0000000..24b2cb9 --- /dev/null +++ b/admininistrator/controller/extension/module.php @@ -0,0 +1,262 @@ +response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + $this->load->language('extension/module'); + + $this->load->model('setting/module'); + + $this->load->language('extension/module'); + + $data['text_layout'] = sprintf($this->language->get('text_layout'), $this->url->link('design/layout', 'user_token=' . $this->session->data['user_token'])); + + $available = []; + + $this->load->model('setting/extension'); + + $results = $this->model_setting_extension->getPaths('%/admin/controller/module/%.php'); + + foreach ($results as $result) { + $available[] = basename($result['path'], '.php'); + } + + $installed = []; + + $extensions = $this->model_setting_extension->getExtensionsByType('module'); + + foreach ($extensions as $extension) { + if (in_array($extension['code'], $available)) { + $installed[] = $extension['code']; + } else { + $this->model_setting_extension->uninstall('module', $extension['code']); + } + } + + $this->load->model('setting/module'); + + $data['extensions'] = []; + + if ($results) { + foreach ($results as $result) { + $extension = substr($result['path'], 0, strpos($result['path'], '/')); + + $code = basename($result['path'], '.php'); + + $this->load->language('extension/' . $extension . '/module/' . $code, $code); + + $module_data = []; + + $modules = $this->model_setting_module->getModulesByCode($extension . '.' . $code); + + foreach ($modules as $module) { + if ($module['setting']) { + $setting_info = json_decode($module['setting'], true); + } else { + $setting_info = []; + } + + $module_data[] = [ + 'name' => $module['name'], + 'status' => (bool)$setting_info['status'] ? $this->language->get('text_enabled') : $this->language->get('text_disabled'), + 'edit' => $this->url->link('extension/' . $extension . '/module/' . $code, 'user_token=' . $this->session->data['user_token'] . '&module_id=' . $module['module_id']), + 'delete' => $this->url->link('extension/module.delete', 'user_token=' . $this->session->data['user_token'] . '&module_id=' . $module['module_id']) + ]; + } + + if ($module_data) { + $status = ''; + } else { + $status = $this->config->get('module_' . $code . '_status') ? $this->language->get('text_enabled') : $this->language->get('text_disabled'); + } + + $data['extensions'][] = [ + 'name' => $this->language->get($code . '_heading_title'), + 'status' => $status, + 'module' => $module_data, + 'install' => $this->url->link('extension/module.install', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'uninstall' => $this->url->link('extension/module.uninstall', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'installed' => in_array($code, $installed), + 'edit' => $this->url->link('extension/' . $extension . '/module/' . $code, 'user_token=' . $this->session->data['user_token']) + ]; + } + } + + $sort_order = []; + + foreach ($data['extensions'] as $key => $value) { + $sort_order[$key] = $value['name']; + } + + array_multisort($sort_order, SORT_ASC, $data['extensions']); + + $data['promotion'] = $this->load->controller('marketplace/promotion'); + + return $this->load->view('extension/module', $data); + } + + /** + * @return void + */ + public function install(): void { + $this->load->language('extension/module'); + + $json = []; + + if (isset($this->request->get['extension'])) { + $extension = basename($this->request->get['extension']); + } else { + $extension = ''; + } + + if (isset($this->request->get['code'])) { + $code = basename($this->request->get['code']); + } else { + $code = ''; + } + + if (!$this->user->hasPermission('modify', 'extension/module')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!is_file(DIR_EXTENSION . $extension . '/admin/controller/module/' . $code . '.php')) { + $json['error'] = $this->language->get('error_extension'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->install('module', $extension, $code); + + $this->load->model('user/user_group'); + + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'access', 'extension/' . $extension . '/module/' . $code); + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'modify', 'extension/' . $extension . '/module/' . $code); + + $namespace = str_replace(['_', '/'], ['', '\\'], ucwords($extension, '_/')); + + // Register controllers, models and system extension folders + $this->autoloader->register('Opencart\Admin\Controller\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/controller/'); + $this->autoloader->register('Opencart\Admin\Model\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/model/'); + $this->autoloader->register('Opencart\System\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/system/'); + + // Template directory + $this->template->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/view/template/'); + + // Language directory + $this->language->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/language/'); + + // Config directory + $this->config->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/system/config/'); + + // Call install method if it exists + $this->load->controller('extension/' . $extension . '/module/' . $code . '.install'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function uninstall(): void { + $this->load->language('extension/module'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'extension/module')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->uninstall('module', $this->request->get['code']); + + $this->load->model('setting/module'); + + $this->model_setting_module->deleteModulesByCode($this->request->get['extension'] . '.' . $this->request->get['code']); + + // Call uninstall method if it exists + $this->load->controller('extension/' . $this->request->get['extension'] . '/module/' . $this->request->get['code'] . '.uninstall'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function add(): void { + $this->load->language('extension/module'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'extension/module')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->language('extension/' . $this->request->get['extension'] . '/module/' . $this->request->get['code'], 'extension'); + + $this->load->model('setting/module'); + + $this->model_setting_module->addModule($this->request->get['extension'] . '.' . $this->request->get['code'], $this->language->get('extension_heading_title')); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('extension/module'); + + $json = []; + + if (isset($this->request->get['module_id'])) { + $module_id = $this->request->get['module_id']; + } else { + $module_id = 0; + } + + if (!$this->user->hasPermission('modify', 'extension/module')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/module'); + + $this->model_setting_module->deleteModule($module_id); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/extension/other.php b/admininistrator/controller/extension/other.php new file mode 100644 index 0000000..a5ad4c9 --- /dev/null +++ b/admininistrator/controller/extension/other.php @@ -0,0 +1,161 @@ +response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + // Had top load again because the method is called directly. + $this->load->language('extension/other'); + + $available = []; + + $this->load->model('setting/extension'); + + $results = $this->model_setting_extension->getPaths('%/admin/controller/other/%.php'); + + foreach ($results as $result) { + $available[] = basename($result['path'], '.php'); + } + + $installed = []; + + $extensions = $this->model_setting_extension->getExtensionsByType('other'); + + foreach ($extensions as $extension) { + if (in_array($extension['code'], $available)) { + $installed[] = $extension['code']; + } else { + $this->model_setting_extension->uninstall('other', $extension['code']); + } + } + + $data['extensions'] = []; + + if ($results) { + foreach ($results as $result) { + $extension = substr($result['path'], 0, strpos($result['path'], '/')); + + $code = basename($result['path'], '.php'); + + $this->load->language('extension/' . $extension . '/other/' . $code, $code); + + $data['extensions'][] = [ + 'name' => $this->language->get($code . '_heading_title'), + 'status' => $this->config->get('other_' . $code . '_status') ? $this->language->get('text_enabled') : $this->language->get('text_disabled'), + 'install' => $this->url->link('extension/other.install', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'uninstall' => $this->url->link('extension/other.uninstall', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'installed' => in_array($code, $installed), + 'edit' => $this->url->link('extension/' . $extension . '/other/' . $code, 'user_token=' . $this->session->data['user_token']) + ]; + } + } + + $data['promotion'] = $this->load->controller('marketplace/promotion'); + + return $this->load->view('extension/other', $data); + } + + /** + * @return void + */ + public function install(): void { + $this->load->language('extension/other'); + + $json = []; + + if (isset($this->request->get['extension'])) { + $extension = basename($this->request->get['extension']); + } else { + $extension = ''; + } + + if (isset($this->request->get['code'])) { + $code = basename($this->request->get['code']); + } else { + $code = ''; + } + + if (!$this->user->hasPermission('modify', 'extension/other')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!is_file(DIR_EXTENSION . $extension . '/admin/controller/other/' . $code . '.php')) { + $json['error'] = $this->language->get('error_extension'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->install('other', $extension, $code); + + $this->load->model('user/user_group'); + + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'access', 'extension/' . $extension . '/other/' . $code); + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'modify', 'extension/' . $extension . '/other/' . $code); + + $namespace = str_replace(['_', '/'], ['', '\\'], ucwords($extension, '_/')); + + // Register controllers, models and system extension folders + $this->autoloader->register('Opencart\Admin\Controller\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/controller/'); + $this->autoloader->register('Opencart\Admin\Model\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/model/'); + $this->autoloader->register('Opencart\System\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/system/'); + + // Template directory + $this->template->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/view/template/'); + + // Language directory + $this->language->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/language/'); + + // Config directory + $this->config->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/system/config/'); + + // Call install method if it exists + $this->load->controller('extension/' . $extension . '/other/' . $code . '.install'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function uninstall(): void { + $this->load->language('extension/other'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'extension/other')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->uninstall('other', $this->request->get['code']); + + // Call uninstall method if it exists + $this->load->controller('extension/' . $this->request->get['extension'] . '/other/' . $this->request->get['code'] . '.uninstall'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/extension/payment.php b/admininistrator/controller/extension/payment.php new file mode 100644 index 0000000..b35fcd0 --- /dev/null +++ b/admininistrator/controller/extension/payment.php @@ -0,0 +1,170 @@ +response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + $this->load->language('extension/payment'); + + $available = []; + + $this->load->model('setting/extension'); + + $results = $this->model_setting_extension->getPaths('%/admin/controller/payment/%.php'); + + foreach ($results as $result) { + $available[] = basename($result['path'], '.php'); + } + + $installed = []; + + $extensions = $this->model_setting_extension->getExtensionsByType('payment'); + + foreach ($extensions as $extension) { + if (in_array($extension['code'], $available)) { + $installed[] = $extension['code']; + } else { + $this->model_setting_extension->uninstall('payment', $extension['code']); + } + } + + $data['extensions'] = []; + + if ($results) { + foreach ($results as $result) { + $extension = substr($result['path'], 0, strpos($result['path'], '/')); + + $code = basename($result['path'], '.php'); + + $this->load->language('extension/' . $extension . '/payment/' . $code, $code); + + $text_link = $this->language->get($code . '_text_' . $code); + + if ($text_link != $code . '_text_' . $code) { + $link = $text_link; + } else { + $link = ''; + } + + $data['extensions'][] = [ + 'name' => $this->language->get($code . '_heading_title'), + 'link' => $link, + 'status' => $this->config->get('payment_' . $code . '_status') ? $this->language->get('text_enabled') : $this->language->get('text_disabled'), + 'sort_order' => $this->config->get('payment_' . $code . '_sort_order'), + 'install' => $this->url->link('extension/payment.install', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'uninstall' => $this->url->link('extension/payment.uninstall', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'installed' => in_array($code, $installed), + 'edit' => $this->url->link('extension/' . $extension . '/payment/' . $code, 'user_token=' . $this->session->data['user_token']) + ]; + } + } + + $data['promotion'] = $this->load->controller('marketplace/promotion'); + + return $this->load->view('extension/payment', $data); + } + + /** + * @return void + */ + public function install(): void { + $this->load->language('extension/payment'); + + $json = []; + + if (isset($this->request->get['extension'])) { + $extension = basename($this->request->get['extension']); + } else { + $extension = ''; + } + + if (isset($this->request->get['code'])) { + $code = basename($this->request->get['code']); + } else { + $code = ''; + } + + if (!$this->user->hasPermission('modify', 'extension/payment')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!is_file(DIR_EXTENSION . $extension . '/admin/controller/payment/' . $code . '.php')) { + $json['error'] = $this->language->get('error_extension'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->install('payment', $extension, $code); + + $this->load->model('user/user_group'); + + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'access', 'extension/' . $extension . '/payment/' . $code); + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'modify', 'extension/' . $extension . '/payment/' . $code); + + $namespace = str_replace(['_', '/'], ['', '\\'], ucwords($extension, '_/')); + + // Register controllers, models and system extension folders + $this->autoloader->register('Opencart\Admin\Controller\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/controller/'); + $this->autoloader->register('Opencart\Admin\Model\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/model/'); + $this->autoloader->register('Opencart\System\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/system/'); + + // Template directory + $this->template->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/view/template/'); + + // Language directory + $this->language->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/language/'); + + // Config directory + $this->config->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/system/config/'); + + // Call install method if it exists + $this->load->controller('extension/' . $extension . '/payment/' . $code . '.install'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function uninstall(): void { + $this->load->language('extension/payment'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'extension/payment')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->uninstall('payment', $this->request->get['code']); + + // Call uninstall method if it exists + $this->load->controller('extension/' . $this->request->get['extension'] . '/payment/' . $this->request->get['code'] . '.uninstall'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/extension/report.php b/admininistrator/controller/extension/report.php new file mode 100644 index 0000000..83c3a87 --- /dev/null +++ b/admininistrator/controller/extension/report.php @@ -0,0 +1,161 @@ +response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + $this->load->language('extension/report'); + + $available = []; + + $this->load->model('setting/extension'); + + $results = $this->model_setting_extension->getPaths('%/admin/controller/report/%.php'); + + foreach ($results as $result) { + $available[] = basename($result['path'], '.php'); + } + + $installed = []; + + $extensions = $this->model_setting_extension->getExtensionsByType('report'); + + foreach ($extensions as $extension) { + if (in_array($extension['code'], $available)) { + $installed[] = $extension['code']; + } else { + $this->model_setting_extension->uninstall('report', $extension['code']); + } + } + + $data['extensions'] = []; + + if ($results) { + foreach ($results as $result) { + $extension = substr($result['path'], 0, strpos($result['path'], '/')); + + $code = basename($result['path'], '.php'); + + $this->load->language('extension/' . $extension . '/report/' . $code, $code); + + $data['extensions'][] = [ + 'name' => $this->language->get($code . '_heading_title'), + 'status' => $this->config->get('report_' . $code . '_status') ? $this->language->get('text_enabled') : $this->language->get('text_disabled'), + 'sort_order' => $this->config->get('report_' . $code . '_sort_order'), + 'install' => $this->url->link('extension/report.install', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'uninstall' => $this->url->link('extension/report.uninstall', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'installed' => in_array($code, $installed), + 'edit' => $this->url->link('extension/' . $extension . '/report/' . $code, 'user_token=' . $this->session->data['user_token']) + ]; + } + } + + $data['promotion'] = $this->load->controller('marketplace/promotion'); + + return $this->load->view('extension/report', $data); + } + + /** + * @return void + */ + public function install(): void { + $this->load->language('extension/report'); + + $json = []; + + if (isset($this->request->get['extension'])) { + $extension = basename($this->request->get['extension']); + } else { + $extension = ''; + } + + if (isset($this->request->get['code'])) { + $code = basename($this->request->get['code']); + } else { + $code = ''; + } + + if (!$this->user->hasPermission('modify', 'extension/report')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!is_file(DIR_EXTENSION . $extension . '/admin/controller/report/' . $code . '.php')) { + $json['error'] = $this->language->get('error_extension'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->install('report', $extension, $code); + + $this->load->model('user/user_group'); + + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'access', 'extension/' . $extension . '/report/' . $code); + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'modify', 'extension/' . $extension . '/report/' . $code); + + $namespace = str_replace(['_', '/'], ['', '\\'], ucwords($extension, '_/')); + + // Register controllers, models and system extension folders + $this->autoloader->register('Opencart\Admin\Controller\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/controller/'); + $this->autoloader->register('Opencart\Admin\Model\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/model/'); + $this->autoloader->register('Opencart\System\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/system/'); + + // Template directory + $this->template->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/view/template/'); + + // Language directory + $this->language->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/language/'); + + // Config directory + $this->config->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/system/config/'); + + // Call install method if it exists + $this->load->controller('extension/' . $extension . '/report/' . $code . '.install'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function uninstall(): void { + $this->load->language('extension/report'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'extension/report')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->uninstall('report', $this->request->get['code']); + + // Call uninstall method if it exists + $this->load->controller('extension/' . $this->request->get['extension'] . '/report/' . $this->request->get['code'] . '.uninstall'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/extension/shipping.php b/admininistrator/controller/extension/shipping.php new file mode 100644 index 0000000..fd414a9 --- /dev/null +++ b/admininistrator/controller/extension/shipping.php @@ -0,0 +1,161 @@ +response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + $this->load->language('extension/shipping'); + + $available = []; + + $this->load->model('setting/extension'); + + $results = $this->model_setting_extension->getPaths('%/admin/controller/shipping/%.php'); + + foreach ($results as $result) { + $available[] = basename($result['path'], '.php'); + } + + $installed = []; + + $extensions = $this->model_setting_extension->getExtensionsByType('shipping'); + + foreach ($extensions as $extension) { + if (in_array($extension['code'], $available)) { + $installed[] = $extension['code']; + } else { + $this->model_setting_extension->uninstall('shipping', $extension['code']); + } + } + + $data['extensions'] = []; + + if ($results) { + foreach ($results as $result) { + $extension = substr($result['path'], 0, strpos($result['path'], '/')); + + $code = basename($result['path'], '.php'); + + $this->load->language('extension/' . $extension . '/shipping/' . $code, $code); + + $data['extensions'][] = [ + 'name' => $this->language->get($code . '_heading_title'), + 'status' => $this->config->get('shipping_' . $code . '_status') ? $this->language->get('text_enabled') : $this->language->get('text_disabled'), + 'sort_order' => $this->config->get('shipping_' . $code . '_sort_order'), + 'install' => $this->url->link('extension/shipping.install', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'uninstall' => $this->url->link('extension/shipping.uninstall', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'installed' => in_array($code, $installed), + 'edit' => $this->url->link('extension/' . $extension . '/shipping/' . $code, 'user_token=' . $this->session->data['user_token']) + ]; + } + } + + $data['promotion'] = $this->load->controller('marketplace/promotion'); + + return $this->load->view('extension/shipping', $data); + } + + /** + * @return void + */ + public function install(): void { + $this->load->language('extension/shipping'); + + $json = []; + + if (isset($this->request->get['extension'])) { + $extension = basename($this->request->get['extension']); + } else { + $extension = ''; + } + + if (isset($this->request->get['code'])) { + $code = basename($this->request->get['code']); + } else { + $code = ''; + } + + if (!$this->user->hasPermission('modify', 'extension/shipping')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!is_file(DIR_EXTENSION . $extension . '/admin/controller/shipping/' . $code . '.php')) { + $json['error'] = $this->language->get('error_extension'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->install('shipping', $extension, $code); + + $this->load->model('user/user_group'); + + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'access', 'extension/' . $extension . '/shipping/' . $code); + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'modify', 'extension/' . $extension . '/shipping/' . $code); + + $namespace = str_replace(['_', '/'], ['', '\\'], ucwords($extension, '_/')); + + // Register controllers, models and system extension folders + $this->autoloader->register('Opencart\Admin\Controller\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/controller/'); + $this->autoloader->register('Opencart\Admin\Model\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/model/'); + $this->autoloader->register('Opencart\System\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/system/'); + + // Template directory + $this->template->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/view/template/'); + + // Language directory + $this->language->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/language/'); + + // Config directory + $this->config->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/system/config/'); + + // Call install method if it exists + $this->load->controller('extension/' . $extension . '/shipping/' . $code . '.install'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function uninstall(): void { + $this->load->language('extension/shipping'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'extension/shipping')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->uninstall('shipping', $this->request->get['code']); + + // Call uninstall method if it exists + $this->load->controller('extension/' . $this->request->get['extension'] . '/shipping/' . $this->request->get['code'] . '.uninstall'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/extension/theme.php b/admininistrator/controller/extension/theme.php new file mode 100644 index 0000000..1d4ce89 --- /dev/null +++ b/admininistrator/controller/extension/theme.php @@ -0,0 +1,180 @@ +response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + $this->load->language('extension/theme'); + + $available = []; + + $this->load->model('setting/extension'); + + $results = $this->model_setting_extension->getPaths('%/admin/controller/theme/%.php'); + + foreach ($results as $result) { + $available[] = basename($result['path'], '.php'); + } + + $installed = []; + + $extensions = $this->model_setting_extension->getExtensionsByType('theme'); + + foreach ($extensions as $extension) { + if (in_array($extension['code'], $available)) { + $installed[] = $extension['code']; + } else { + $this->model_setting_extension->uninstall('theme', $extension['code']); + } + } + + $this->load->model('setting/store'); + $this->load->model('setting/setting'); + + $stores = $this->model_setting_store->getStores(); + + $data['extensions'] = []; + + if ($results) { + foreach ($results as $result) { + $extension = substr($result['path'], 0, strpos($result['path'], '/')); + + $code = basename($result['path'], '.php'); + + $this->load->language('extension/' . $extension . '/theme/' . $code, $code); + + $store_data = []; + + $store_data[] = [ + 'name' => $this->config->get('config_name'), + 'edit' => $this->url->link('extension/' . $extension . '/theme/' . $code, 'user_token=' . $this->session->data['user_token'] . '&store_id=0'), + 'status' => $this->config->get('theme_' . $code . '_status') ? $this->language->get('text_enabled') : $this->language->get('text_disabled') + ]; + + foreach ($stores as $store) { + $store_data[] = [ + 'name' => $store['name'], + 'edit' => $this->url->link('extension/' . $extension . '/theme/' . $code, 'user_token=' . $this->session->data['user_token'] . '&store_id=' . $store['store_id']), + 'status' => $this->model_setting_setting->getValue('theme_' . $code . '_status', $store['store_id']) ? $this->language->get('text_enabled') : $this->language->get('text_disabled') + ]; + } + + $data['extensions'][] = [ + 'name' => $this->language->get($code . '_heading_title'), + 'install' => $this->url->link('extension/theme.install', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'uninstall' => $this->url->link('extension/theme.uninstall', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'installed' => in_array($code, $installed), + 'store' => $store_data + ]; + } + } + + $data['promotion'] = $this->load->controller('marketplace/promotion'); + + return $this->load->view('extension/theme', $data); + } + + /** + * @return void + */ + public function install(): void { + $this->load->language('extension/theme'); + + $json = []; + + if (isset($this->request->get['extension'])) { + $extension = basename($this->request->get['extension']); + } else { + $extension = ''; + } + + if (isset($this->request->get['code'])) { + $code = basename($this->request->get['code']); + } else { + $code = ''; + } + + if (!$this->user->hasPermission('modify', 'extension/theme')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!is_file(DIR_EXTENSION . $extension . '/admin/controller/theme/' . $code . '.php')) { + $json['error'] = $this->language->get('error_extension'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->install('theme', $extension, $code); + + $this->load->model('user/user_group'); + + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'access', 'extension/' . $extension . '/theme/' . $code); + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'modify', 'extension/' . $extension . '/theme/' . $code); + + $namespace = str_replace(['_', '/'], ['', '\\'], ucwords($extension, '_/')); + + // Register controllers, models and system extension folders + $this->autoloader->register('Opencart\Admin\Controller\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/controller/'); + $this->autoloader->register('Opencart\Admin\Model\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/model/'); + $this->autoloader->register('Opencart\System\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/system/'); + + // Template directory + $this->template->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/view/template/'); + + // Language directory + $this->language->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/language/'); + + // Config directory + $this->config->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/system/config/'); + + // Call install method if it exists + $this->load->controller('extension/' . $extension . '/theme/' . $code . '.install'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function uninstall(): void { + $this->load->language('extension/theme'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'extension/theme')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->uninstall('theme', $this->request->get['code']); + + // Call uninstall method if it exists + $this->load->controller('extension/' . $this->request->get['extension'] . '/theme/' . $this->request->get['code'] . '.uninstall'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/extension/total.php b/admininistrator/controller/extension/total.php new file mode 100644 index 0000000..5c5f789 --- /dev/null +++ b/admininistrator/controller/extension/total.php @@ -0,0 +1,161 @@ +response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + $this->load->language('extension/total'); + + $available = []; + + $this->load->model('setting/extension'); + + $results = $this->model_setting_extension->getPaths('%/admin/controller/total/%.php'); + + foreach ($results as $result) { + $available[] = basename($result['path'], '.php'); + } + + $installed = []; + + $extensions = $this->model_setting_extension->getExtensionsByType('total'); + + foreach ($extensions as $extension) { + if (in_array($extension['code'], $available)) { + $installed[] = $extension['code']; + } else { + $this->model_setting_extension->uninstall('total', $extension['code']); + } + } + + $data['extensions'] = []; + + if ($results) { + foreach ($results as $result) { + $extension = substr($result['path'], 0, strpos($result['path'], '/')); + + $code = basename($result['path'], '.php'); + + $this->load->language('extension/' . $extension . '/total/' . $code, $code); + + $data['extensions'][] = [ + 'name' => $this->language->get($code . '_heading_title'), + 'status' => $this->config->get('total_' . $code . '_status') ? $this->language->get('text_enabled') : $this->language->get('text_disabled'), + 'sort_order' => $this->config->get('total_' . $code . '_sort_order'), + 'install' => $this->url->link('extension/total.install', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'uninstall' => $this->url->link('extension/total.uninstall', 'user_token=' . $this->session->data['user_token'] . '&extension=' . $extension . '&code=' . $code), + 'installed' => in_array($code, $installed), + 'edit' => $this->url->link('extension/' . $extension . '/total/' . $code, 'user_token=' . $this->session->data['user_token']) + ]; + } + } + + $data['promotion'] = $this->load->controller('marketplace/promotion'); + + return $this->load->view('extension/total', $data); + } + + /** + * @return void + */ + public function install(): void { + $this->load->language('extension/total'); + + $json = []; + + if (isset($this->request->get['extension'])) { + $extension = basename($this->request->get['extension']); + } else { + $extension = ''; + } + + if (isset($this->request->get['code'])) { + $code = basename($this->request->get['code']); + } else { + $code = ''; + } + + if (!$this->user->hasPermission('modify', 'extension/total')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!is_file(DIR_EXTENSION . $extension . '/admin/controller/total/' . $code . '.php')) { + $json['error'] = $this->language->get('error_extension'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->install('total', $extension, $code); + + $this->load->model('user/user_group'); + + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'access', 'extension/' . $extension . '/total/' . $code); + $this->model_user_user_group->addPermission($this->user->getGroupId(), 'modify', 'extension/' . $extension . '/total/' . $code); + + $namespace = str_replace(['_', '/'], ['', '\\'], ucwords($extension, '_/')); + + // Register controllers, models and system extension folders + $this->autoloader->register('Opencart\Admin\Controller\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/controller/'); + $this->autoloader->register('Opencart\Admin\Model\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/admin/model/'); + $this->autoloader->register('Opencart\System\Extension\\' . $namespace, DIR_EXTENSION . $extension . '/system/'); + + // Template directory + $this->template->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/view/template/'); + + // Language directory + $this->language->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/admin/language/'); + + // Config directory + $this->config->addPath('extension/' . $extension, DIR_EXTENSION . $extension . '/system/config/'); + + // Call install method if it exists + $this->load->controller('extension/' . $extension . '/total/' . $code . '.install'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function uninstall(): void { + $this->load->language('extension/total'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'extension/total')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/extension'); + + $this->model_setting_extension->uninstall('total', $this->request->get['code']); + + // Call uninstall method if it exists + $this->load->controller('extension/' . $this->request->get['extension'] . '/total/' . $this->request->get['code'] . '.uninstall'); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/localisation/address_format.php b/admininistrator/controller/localisation/address_format.php new file mode 100644 index 0000000..2d6635b --- /dev/null +++ b/admininistrator/controller/localisation/address_format.php @@ -0,0 +1,249 @@ +load->language('localisation/address_format'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/address_format', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('localisation/address_format.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('localisation/address_format.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/address_format', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('localisation/address_format'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('localisation/address_format.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['address_formats'] = []; + + $filter_data = [ + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('localisation/address_format'); + + $address_format_total = $this->model_localisation_address_format->getTotalAddressFormats($filter_data); + + $results = $this->model_localisation_address_format->getAddressFormats($filter_data); + + foreach ($results as $result) { + $data['address_formats'][] = [ + 'address_format_id' => $result['address_format_id'], + 'name' => $result['name'] . (($result['address_format_id'] == $this->config->get('config_address_format_id')) ? $this->language->get('text_default') : ''), + 'address_format' => nl2br($result['address_format']), + 'edit' => $this->url->link('localisation/address_format.form', 'user_token=' . $this->session->data['user_token'] . '&address_format_id=' . $result['address_format_id'] . $url) + ]; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $address_format_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('localisation/address_format.list', 'user_token=' . $this->session->data['user_token'] . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($address_format_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($address_format_total - $this->config->get('config_pagination_admin'))) ? $address_format_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $address_format_total, ceil($address_format_total / $this->config->get('config_pagination_admin'))); + + return $this->load->view('localisation/address_format_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('localisation/address_format'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['address_format_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/address_format', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('localisation/address_format.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('localisation/address_format', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['address_format_id'])) { + $this->load->model('localisation/address_format'); + + $address_format_info = $this->model_localisation_address_format->getAddressFormat($this->request->get['address_format_id']); + } + + if (isset($this->request->get['address_format_id'])) { + $data['address_format_id'] = (int)$this->request->get['address_format_id']; + } else { + $data['address_format_id'] = 0; + } + + if (!empty($address_format_info)) { + $data['name'] = $address_format_info['name']; + } else { + $data['name'] = ''; + } + + if (!empty($address_format_info)) { + $data['address_format'] = $address_format_info['address_format']; + } else { + $data['address_format'] = ''; + } + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/address_format_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('localisation/address_format'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'localisation/address_format')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if ((oc_strlen($this->request->post['name']) < 1) || (oc_strlen($this->request->post['name']) > 128)) { + $json['error']['name'] = $this->language->get('error_name'); + } + + if (!$json) { + $this->load->model('localisation/address_format'); + + if (!$this->request->post['address_format_id']) { + $json['address_format_id'] = $this->model_localisation_address_format->addAddressFormat($this->request->post); + } else { + $this->model_localisation_address_format->editAddressFormat($this->request->post['address_format_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('localisation/address_format'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'localisation/address_format')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('localisation/country'); + + foreach ($selected as $address_format_id) { + if ($this->config->get('config_address_format_id') == $address_format_id) { + $json['error'] = $this->language->get('error_default'); + } + + $country_total = $this->model_localisation_country->getTotalCountriesByAddressFormatId($address_format_id); + + if ($country_total) { + $json['error'] = sprintf($this->language->get('error_country'), $country_total); + } + } + + if (!$json) { + $this->load->model('localisation/address_format'); + + foreach ($selected as $address_format_id) { + $this->model_localisation_address_format->deleteAddressFormat($address_format_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/localisation/country.php b/admininistrator/controller/localisation/country.php new file mode 100644 index 0000000..2535c89 --- /dev/null +++ b/admininistrator/controller/localisation/country.php @@ -0,0 +1,489 @@ +load->language('localisation/country'); + + $this->document->setTitle($this->language->get('heading_title')); + + if (isset($this->request->get['filter_name'])) { + $filter_name = (string)$this->request->get['filter_name']; + } else { + $filter_name = ''; + } + + if (isset($this->request->get['filter_iso_code_2'])) { + $filter_iso_code_2 = (string)$this->request->get['filter_iso_code_2']; + } else { + $filter_iso_code_2 = ''; + } + + if (isset($this->request->get['filter_iso_code_3'])) { + $filter_iso_code_3 = (string)$this->request->get['filter_iso_code_3']; + } else { + $filter_iso_code_3 = ''; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/country', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('localisation/country.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('localisation/country.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['filter_name'] = $filter_name; + $data['filter_iso_code_2'] = $filter_iso_code_2; + $data['filter_iso_code_3'] = $filter_iso_code_3; + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/country', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('localisation/country'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['filter_name'])) { + $filter_name = (string)$this->request->get['filter_name']; + } else { + $filter_name = ''; + } + + if (isset($this->request->get['filter_iso_code_2'])) { + $filter_iso_code_2 = (string)$this->request->get['filter_iso_code_2']; + } else { + $filter_iso_code_2 = ''; + } + + if (isset($this->request->get['filter_iso_code_3'])) { + $filter_iso_code_3 = (string)$this->request->get['filter_iso_code_3']; + } else { + $filter_iso_code_3 = ''; + } + + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_iso_code_2'])) { + $url .= '&filter_iso_code_2=' . urlencode(html_entity_decode($this->request->get['filter_iso_code_2'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_iso_code_3'])) { + $url .= '&filter_iso_code_3=' . urlencode(html_entity_decode($this->request->get['filter_iso_code_3'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('localisation/country.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['countries'] = []; + + $filter_data = [ + 'filter_name' => $filter_name, + 'filter_iso_code_2' => $filter_iso_code_2, + 'filter_iso_code_3' => $filter_iso_code_3, + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('localisation/country'); + + $country_total = $this->model_localisation_country->getTotalCountries($filter_data); + + $results = $this->model_localisation_country->getCountries($filter_data); + + foreach ($results as $result) { + $data['countries'][] = [ + 'country_id' => $result['country_id'], + 'name' => $result['name'] . (($result['country_id'] == $this->config->get('config_country_id')) ? $this->language->get('text_default') : ''), + 'status' => $result['status'], + 'iso_code_2' => $result['iso_code_2'], + 'iso_code_3' => $result['iso_code_3'], + 'edit' => $this->url->link('localisation/country.form', 'user_token=' . $this->session->data['user_token'] . '&country_id=' . $result['country_id'] . $url) + ]; + } + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_iso_code_2'])) { + $url .= '&filter_iso_code_2=' . urlencode(html_entity_decode($this->request->get['filter_iso_code_2'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_iso_code_3'])) { + $url .= '&filter_iso_code_3=' . urlencode(html_entity_decode($this->request->get['filter_iso_code_3'], ENT_QUOTES, 'UTF-8')); + } + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('localisation/country.list', 'user_token=' . $this->session->data['user_token'] . '&sort=name' . $url); + $data['sort_iso_code_2'] = $this->url->link('localisation/country.list', 'user_token=' . $this->session->data['user_token'] . '&sort=iso_code_2' . $url); + $data['sort_iso_code_3'] = $this->url->link('localisation/country.list', 'user_token=' . $this->session->data['user_token'] . '&sort=iso_code_3' . $url); + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_iso_code_2'])) { + $url .= '&filter_iso_code_2=' . urlencode(html_entity_decode($this->request->get['filter_iso_code_2'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_iso_code_3'])) { + $url .= '&filter_iso_code_3=' . urlencode(html_entity_decode($this->request->get['filter_iso_code_3'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $country_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('localisation/country.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($country_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($country_total - $this->config->get('config_pagination_admin'))) ? $country_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $country_total, ceil($country_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('localisation/country_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('localisation/country'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['country_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_iso_code_2'])) { + $url .= '&filter_iso_code_2=' . urlencode(html_entity_decode($this->request->get['filter_iso_code_2'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_iso_code_3'])) { + $url .= '&filter_iso_code_3=' . urlencode(html_entity_decode($this->request->get['filter_iso_code_3'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/country', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('localisation/country.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('localisation/country', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['country_id'])) { + $this->load->model('localisation/country'); + + $country_info = $this->model_localisation_country->getCountry($this->request->get['country_id']); + } + + if (isset($this->request->get['country_id'])) { + $data['country_id'] = (int)$this->request->get['country_id']; + } else { + $data['country_id'] = 0; + } + + if (!empty($country_info)) { + $data['name'] = $country_info['name']; + } else { + $data['name'] = ''; + } + + if (!empty($country_info)) { + $data['iso_code_2'] = $country_info['iso_code_2']; + } else { + $data['iso_code_2'] = ''; + } + + if (!empty($country_info)) { + $data['iso_code_3'] = $country_info['iso_code_3']; + } else { + $data['iso_code_3'] = ''; + } + + $this->load->model('localisation/address_format'); + + $data['address_formats'] = $this->model_localisation_address_format->getAddressFormats(); + + if (!empty($country_info)) { + $data['address_format_id'] = $country_info['address_format_id']; + } else { + $data['address_format_id'] = ''; + } + + if (!empty($country_info)) { + $data['postcode_required'] = $country_info['postcode_required']; + } else { + $data['postcode_required'] = 0; + } + + if (!empty($country_info)) { + $data['status'] = $country_info['status']; + } else { + $data['status'] = '1'; + } + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/country_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('localisation/country'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'localisation/country')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if ((oc_strlen($this->request->post['name']) < 1) || (oc_strlen($this->request->post['name']) > 128)) { + $json['error']['name'] = $this->language->get('error_name'); + } + + if (!$json) { + $this->load->model('localisation/country'); + + if (!$this->request->post['country_id']) { + $json['country_id'] = $this->model_localisation_country->addCountry($this->request->post); + } else { + $this->model_localisation_country->editCountry($this->request->post['country_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('localisation/country'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'localisation/country')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('setting/store'); + $this->load->model('customer/customer'); + $this->load->model('localisation/zone'); + $this->load->model('localisation/geo_zone'); + + foreach ($selected as $country_id) { + if ($this->config->get('config_country_id') == $country_id) { + $json['error'] = $this->language->get('error_default'); + } + + $store_total = $this->model_setting_store->getTotalStoresByCountryId($country_id); + + if ($store_total) { + $json['error'] = sprintf($this->language->get('error_store'), $store_total); + } + + $address_total = $this->model_customer_customer->getTotalAddressesByCountryId($country_id); + + if ($address_total) { + $json['error'] = sprintf($this->language->get('error_address'), $address_total); + } + + $zone_total = $this->model_localisation_zone->getTotalZonesByCountryId($country_id); + + if ($zone_total) { + $json['error'] = sprintf($this->language->get('error_zone'), $zone_total); + } + + $zone_to_geo_zone_total = $this->model_localisation_geo_zone->getTotalZoneToGeoZoneByCountryId($country_id); + + if ($zone_to_geo_zone_total) { + $json['error'] = sprintf($this->language->get('error_zone_to_geo_zone'), $zone_to_geo_zone_total); + } + } + + if (!$json) { + $this->load->model('localisation/country'); + + foreach ($selected as $country_id) { + $this->model_localisation_country->deleteCountry($country_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function country(): void { + $json = []; + + if (isset($this->request->get['country_id'])) { + $country_id = (int)$this->request->get['country_id']; + } else { + $country_id = 0; + } + + $this->load->model('localisation/country'); + + $country_info = $this->model_localisation_country->getCountry($country_id); + + if ($country_info) { + $this->load->model('localisation/zone'); + + $json = [ + 'country_id' => $country_info['country_id'], + 'name' => $country_info['name'], + 'iso_code_2' => $country_info['iso_code_2'], + 'iso_code_3' => $country_info['iso_code_3'], + 'address_format_id' => $country_info['address_format_id'], + 'postcode_required' => $country_info['postcode_required'], + 'zone' => $this->model_localisation_zone->getZonesByCountryId($country_id), + 'status' => $country_info['status'] + ]; + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/localisation/currency.php b/admininistrator/controller/localisation/currency.php new file mode 100644 index 0000000..cf430d3 --- /dev/null +++ b/admininistrator/controller/localisation/currency.php @@ -0,0 +1,406 @@ +load->language('localisation/currency'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/currency', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['refresh'] = $this->url->link('localisation/currency.refresh', 'user_token=' . $this->session->data['user_token'] . $url); + $data['add'] = $this->url->link('localisation/currency.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('localisation/currency.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/currency', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('localisation/currency'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'title'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/currency', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['action'] = $this->url->link('localisation/currency.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['currencies'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('localisation/currency'); + + $currency_total = $this->model_localisation_currency->getTotalCurrencies(); + + $results = $this->model_localisation_currency->getCurrencies($filter_data); + + foreach ($results as $result) { + $data['currencies'][] = [ + 'currency_id' => $result['currency_id'], + 'title' => $result['title'] . (($result['code'] == $this->config->get('config_currency')) ? $this->language->get('text_default') : ''), + 'code' => $result['code'], + 'value' => $result['value'], + 'status' => $result['status'], + 'date_modified' => date($this->language->get('date_format_short'), strtotime($result['date_modified'])), + 'edit' => $this->url->link('localisation/currency.form', 'user_token=' . $this->session->data['user_token'] . '¤cy_id=' . $result['currency_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_title'] = $this->url->link('localisation/currency.list', 'user_token=' . $this->session->data['user_token'] . '&sort=title' . $url); + $data['sort_code'] = $this->url->link('localisation/currency.list', 'user_token=' . $this->session->data['user_token'] . '&sort=code' . $url); + $data['sort_value'] = $this->url->link('localisation/currency.list', 'user_token=' . $this->session->data['user_token'] . '&sort=value' . $url); + $data['sort_status'] = $this->url->link('localisation/currency.list', 'user_token=' . $this->session->data['user_token'] . '&sort=status' . $url); + $data['sort_date_modified'] = $this->url->link('localisation/currency.list', 'user_token=' . $this->session->data['user_token'] . '&sort=date_modified' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $currency_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('localisation/currency.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($currency_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($currency_total - $this->config->get('config_pagination_admin'))) ? $currency_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $currency_total, ceil($currency_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('localisation/currency_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('localisation/currency'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['currency_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/currency', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('localisation/currency.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('localisation/currency', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['currency_id'])) { + $this->load->model('localisation/currency'); + + $currency_info = $this->model_localisation_currency->getCurrency($this->request->get['currency_id']); + } + + if (isset($this->request->get['currency_id'])) { + $data['currency_id'] = (int)$this->request->get['currency_id']; + } else { + $data['currency_id'] = 0; + } + + if (!empty($currency_info)) { + $data['title'] = $currency_info['title']; + } else { + $data['title'] = ''; + } + + if (!empty($currency_info)) { + $data['code'] = $currency_info['code']; + } else { + $data['code'] = ''; + } + + if (!empty($currency_info)) { + $data['symbol_left'] = $currency_info['symbol_left']; + } else { + $data['symbol_left'] = ''; + } + + if (!empty($currency_info)) { + $data['symbol_right'] = $currency_info['symbol_right']; + } else { + $data['symbol_right'] = ''; + } + + if (!empty($currency_info)) { + $data['decimal_place'] = $currency_info['decimal_place']; + } else { + $data['decimal_place'] = ''; + } + + if (!empty($currency_info)) { + $data['value'] = $currency_info['value']; + } else { + $data['value'] = ''; + } + + if (!empty($currency_info)) { + $data['status'] = $currency_info['status']; + } else { + $data['status'] = ''; + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/currency_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('localisation/currency'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'localisation/currency')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if ((oc_strlen($this->request->post['title']) < 3) || (oc_strlen($this->request->post['title']) > 32)) { + $json['error']['title'] = $this->language->get('error_title'); + } + + if (oc_strlen($this->request->post['code']) != 3) { + $json['error']['code'] = $this->language->get('error_code'); + } + + if (!$json) { + $this->load->model('localisation/currency'); + + if (!$this->request->post['currency_id']) { + $json['currency_id'] = $this->model_localisation_currency->addCurrency($this->request->post); + } else { + $this->model_localisation_currency->editCurrency($this->request->post['currency_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function refresh(): void { + $this->load->language('localisation/currency'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'localisation/currency')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('setting/extension'); + + $extension_info = $this->model_setting_extension->getExtensionByCode('currency', $this->config->get('config_currency_engine')); + + if (!$extension_info) { + $json['error'] = $this->language->get('error_extension'); + } + + if (!$json) { + $this->load->controller('extension/' . $extension_info['extension'] . '/currency/' . $extension_info['code'] . '.currency', $this->config->get('config_currency')); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('localisation/currency'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'localisation/currency')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('localisation/currency'); + $this->load->model('setting/store'); + $this->load->model('sale/order'); + + foreach ($selected as $currency_id) { + $currency_info = $this->model_localisation_currency->getCurrency($currency_id); + + if ($currency_info) { + if ($this->config->get('config_currency') == $currency_info['code']) { + $json['error'] = $this->language->get('error_default'); + } + + $store_total = $this->model_setting_store->getTotalStoresByCurrency($currency_info['code']); + + if ($store_total) { + $json['error'] = sprintf($this->language->get('error_store'), $store_total); + } + } + + $order_total = $this->model_sale_order->getTotalOrdersByCurrencyId($currency_id); + + if ($order_total) { + $json['error'] = sprintf($this->language->get('error_order'), $order_total); + } + } + + if (!$json) { + foreach ($selected as $currency_id) { + $this->model_localisation_currency->deleteCurrency($currency_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/localisation/geo_zone.php b/admininistrator/controller/localisation/geo_zone.php new file mode 100644 index 0000000..6154be4 --- /dev/null +++ b/admininistrator/controller/localisation/geo_zone.php @@ -0,0 +1,323 @@ +load->language('localisation/geo_zone'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/geo_zone', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('localisation/geo_zone.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('localisation/geo_zone.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/geo_zone', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('localisation/geo_zone'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('localisation/geo_zone.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['geo_zones'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('localisation/geo_zone'); + + $geo_zone_total = $this->model_localisation_geo_zone->getTotalGeoZones(); + + $results = $this->model_localisation_geo_zone->getGeoZones($filter_data); + + foreach ($results as $result) { + $data['geo_zones'][] = [ + 'geo_zone_id' => $result['geo_zone_id'], + 'name' => $result['name'], + 'description' => $result['description'], + 'edit' => $this->url->link('localisation/geo_zone.form', 'user_token=' . $this->session->data['user_token'] . '&geo_zone_id=' . $result['geo_zone_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('localisation/geo_zone.list', 'user_token=' . $this->session->data['user_token'] . '&sort=name' . $url); + $data['sort_description'] = $this->url->link('localisation/geo_zone.list', 'user_token=' . $this->session->data['user_token'] . '&sort=description' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $geo_zone_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('localisation/geo_zone.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($geo_zone_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($geo_zone_total - $this->config->get('config_pagination_admin'))) ? $geo_zone_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $geo_zone_total, ceil($geo_zone_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('localisation/geo_zone_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('localisation/geo_zone'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['geo_zone_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/geo_zone', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('localisation/geo_zone.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('localisation/geo_zone', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['geo_zone_id'])) { + $this->load->model('localisation/geo_zone'); + + $geo_zone_info = $this->model_localisation_geo_zone->getGeoZone($this->request->get['geo_zone_id']); + } + + if (isset($this->request->get['geo_zone_id'])) { + $data['geo_zone_id'] = (int)$this->request->get['geo_zone_id']; + } else { + $data['geo_zone_id'] = 0; + } + + if (!empty($geo_zone_info)) { + $data['name'] = $geo_zone_info['name']; + } else { + $data['name'] = ''; + } + + if (!empty($geo_zone_info)) { + $data['description'] = $geo_zone_info['description']; + } else { + $data['description'] = ''; + } + + $this->load->model('localisation/country'); + + $data['countries'] = $this->model_localisation_country->getCountries(); + + if (!empty($geo_zone_info)) { + $data['zone_to_geo_zones'] = $this->model_localisation_geo_zone->getZoneToGeoZones($this->request->get['geo_zone_id']); + } else { + $data['zone_to_geo_zones'] = []; + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/geo_zone_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('localisation/geo_zone'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'localisation/geo_zone')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if ((oc_strlen($this->request->post['name']) < 3) || (oc_strlen($this->request->post['name']) > 32)) { + $json['error']['name'] = $this->language->get('error_name'); + } + + if ((oc_strlen($this->request->post['description']) < 3) || (oc_strlen($this->request->post['description']) > 255)) { + $json['error']['description'] = $this->language->get('error_description'); + } + + if (!$json) { + $this->load->model('localisation/geo_zone'); + + if (!$this->request->post['geo_zone_id']) { + $json['geo_zone_id'] = $this->model_localisation_geo_zone->addGeoZone($this->request->post); + } else { + $this->model_localisation_geo_zone->editGeoZone($this->request->post['geo_zone_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('localisation/geo_zone'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'localisation/geo_zone')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('localisation/tax_rate'); + + foreach ($selected as $geo_zone_id) { + $tax_rate_total = $this->model_localisation_tax_rate->getTotalTaxRatesByGeoZoneId($geo_zone_id); + + if ($tax_rate_total) { + $json['error'] = sprintf($this->language->get('error_tax_rate'), $tax_rate_total); + } + } + + if (!$json) { + $this->load->model('localisation/geo_zone'); + + foreach ($selected as $geo_zone_id) { + $this->model_localisation_geo_zone->deleteGeoZone($geo_zone_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/localisation/language.php b/admininistrator/controller/localisation/language.php new file mode 100644 index 0000000..74c665b --- /dev/null +++ b/admininistrator/controller/localisation/language.php @@ -0,0 +1,373 @@ +load->language('localisation/language'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/language', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('localisation/language.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('localisation/language.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/language', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('localisation/language'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('localisation/language.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['languages'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('localisation/language'); + + $language_total = $this->model_localisation_language->getTotalLanguages(); + + $results = $this->model_localisation_language->getLanguages($filter_data); + + foreach ($results as $result) { + $data['languages'][] = [ + 'language_id' => $result['language_id'], + 'name' => $result['name'] . (($result['code'] == $this->config->get('config_language')) ? $this->language->get('text_default') : ''), + 'code' => $result['code'], + 'status' => $result['status'], + 'sort_order' => $result['sort_order'], + 'edit' => $this->url->link('localisation/language.form', 'user_token=' . $this->session->data['user_token'] . '&language_id=' . $result['language_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('localisation/language.list', 'user_token=' . $this->session->data['user_token'] . '&sort=name' . $url); + $data['sort_code'] = $this->url->link('localisation/language.list', 'user_token=' . $this->session->data['user_token'] . '&sort=code' . $url); + $data['sort_sort_order'] = $this->url->link('localisation/language.list', 'user_token=' . $this->session->data['user_token'] . '&sort=sort_order' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $language_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('localisation/language.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($language_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($language_total - $this->config->get('config_pagination_admin'))) ? $language_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $language_total, ceil($language_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('localisation/language_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('localisation/language'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['language_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/language', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('localisation/language.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('localisation/language', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['language_id'])) { + $this->load->model('localisation/language'); + + $language_info = $this->model_localisation_language->getLanguage($this->request->get['language_id']); + } + + if (isset($this->request->get['language_id'])) { + $data['language_id'] = (int)$this->request->get['language_id']; + } else { + $data['language_id'] = 0; + } + + if (!empty($language_info)) { + $data['name'] = $language_info['name']; + } else { + $data['name'] = ''; + } + + if (!empty($language_info)) { + $data['code'] = $language_info['code']; + } else { + $data['code'] = ''; + } + + if (!empty($language_info)) { + $data['locale'] = $language_info['locale']; + } else { + $data['locale'] = ''; + } + + if (!empty($language_info)) { + $data['extension'] = $language_info['extension']; + } else { + $data['extension'] = ''; + } + + if (!empty($language_info)) { + $data['sort_order'] = $language_info['sort_order']; + } else { + $data['sort_order'] = 1; + } + + if (!empty($language_info)) { + $data['status'] = $language_info['status']; + } else { + $data['status'] = 1; + } + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/language_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('localisation/language'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'localisation/language')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if ((oc_strlen($this->request->post['name']) < 1) || (oc_strlen($this->request->post['name']) > 32)) { + $json['error']['name'] = $this->language->get('error_name'); + } + + if ((oc_strlen($this->request->post['code']) < 2) || (oc_strlen($this->request->post['code']) > 5)) { + $json['error']['code'] = $this->language->get('error_code'); + } + + if ((oc_strlen($this->request->post['locale']) < 2) || (oc_strlen($this->request->post['locale']) > 255)) { + $json['error']['locale'] = $this->language->get('error_locale'); + } + + $language_info = $this->model_localisation_language->getLanguageByCode($this->request->post['code']); + + if (!$this->request->post['language_id']) { + if ($language_info) { + $json['error']['warning'] = $this->language->get('error_exists'); + } + } else { + if ($language_info && ($this->request->post['language_id'] != $language_info['language_id'])) { + $json['error']['warning'] = $this->language->get('error_exists'); + } + } + + if (!$json) { + $this->load->model('localisation/language'); + + if (!$this->request->post['language_id']) { + $json['language_id'] = $this->model_localisation_language->addLanguage($this->request->post); + } else { + $this->model_localisation_language->editLanguage($this->request->post['language_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('localisation/language'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'localisation/language')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('setting/store'); + $this->load->model('sale/order'); + + foreach ($selected as $language_id) { + $language_info = $this->model_localisation_language->getLanguage($language_id); + + if ($language_info) { + if ($this->config->get('config_language') == $language_info['code']) { + $json['error'] = $this->language->get('error_default'); + } + + if ($this->config->get('config_language_admin') == $language_info['code']) { + $json['error'] = $this->language->get('error_admin'); + } + + $store_total = $this->model_setting_store->getTotalStoresByLanguage($language_info['code']); + + if ($store_total) { + $json['error'] = sprintf($this->language->get('error_store'), $store_total); + } + } + + $order_total = $this->model_sale_order->getTotalOrdersByLanguageId($language_id); + + if ($order_total) { + $json['error'] = sprintf($this->language->get('error_order'), $order_total); + } + } + + if (!$json) { + $this->load->model('localisation/language'); + + foreach ($selected as $language_id) { + $this->model_localisation_language->deleteLanguage($language_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/localisation/length_class.php b/admininistrator/controller/localisation/length_class.php new file mode 100644 index 0000000..ae0ca10 --- /dev/null +++ b/admininistrator/controller/localisation/length_class.php @@ -0,0 +1,323 @@ +load->language('localisation/length_class'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/length_class', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('localisation/length_class.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('localisation/length_class.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/length_class', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('localisation/length_class'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'title'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('localisation/length_class.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['length_classes'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('localisation/length_class'); + + $length_class_total = $this->model_localisation_length_class->getTotalLengthClasses(); + + $results = $this->model_localisation_length_class->getLengthClasses($filter_data); + + foreach ($results as $result) { + $data['length_classes'][] = [ + 'length_class_id' => $result['length_class_id'], + 'title' => $result['title'] . (($result['length_class_id'] == $this->config->get('config_length_class_id')) ? $this->language->get('text_default') : ''), + 'unit' => $result['unit'], + 'value' => $result['value'], + 'edit' => $this->url->link('localisation/length_class.form', 'user_token=' . $this->session->data['user_token'] . '&length_class_id=' . $result['length_class_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_title'] = $this->url->link('localisation/length_class.list', 'user_token=' . $this->session->data['user_token'] . '&sort=title' . $url); + $data['sort_unit'] = $this->url->link('localisation/length_class.list', 'user_token=' . $this->session->data['user_token'] . '&sort=unit' . $url); + $data['sort_value'] = $this->url->link('localisation/length_class.list', 'user_token=' . $this->session->data['user_token'] . '&sort=value' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $length_class_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('localisation/length_class.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($length_class_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($length_class_total - $this->config->get('config_pagination_admin'))) ? $length_class_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $length_class_total, ceil($length_class_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('localisation/length_class_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('localisation/length_class'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['length_class_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/length_class', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('localisation/length_class.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('localisation/length_class', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['length_class_id'])) { + $this->load->model('localisation/length_class'); + + $length_class_info = $this->model_localisation_length_class->getLengthClass($this->request->get['length_class_id']); + } + + if (isset($this->request->get['length_class_id'])) { + $data['length_class_id'] = (int)$this->request->get['length_class_id']; + } else { + $data['length_class_id'] = 0; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (!empty($length_class_info)) { + $data['length_class_description'] = $this->model_localisation_length_class->getDescriptions($this->request->get['length_class_id']); + } else { + $data['length_class_description'] = []; + } + + if (!empty($length_class_info)) { + $data['value'] = $length_class_info['value']; + } else { + $data['value'] = ''; + } + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/length_class_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('localisation/length_class'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'localisation/length_class')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + foreach ($this->request->post['length_class_description'] as $language_id => $value) { + if ((oc_strlen($value['title']) < 3) || (oc_strlen($value['title']) > 32)) { + $json['error']['title_' . $language_id] = $this->language->get('error_title'); + } + + if (!$value['unit'] || (oc_strlen($value['unit']) > 4)) { + $json['error']['unit_' . $language_id] = $this->language->get('error_unit'); + } + } + + if (!$json) { + $this->load->model('localisation/length_class'); + + if (!$this->request->post['length_class_id']) { + $json['length_class_id'] = $this->model_localisation_length_class->addLengthClass($this->request->post); + } else { + $this->model_localisation_length_class->editLengthClass($this->request->post['length_class_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('localisation/length_class'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'localisation/length_class')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('catalog/product'); + + foreach ($selected as $length_class_id) { + if ($this->config->get('config_length_class_id') == $length_class_id) { + $json['error'] = $this->language->get('error_default'); + } + + $product_total = $this->model_catalog_product->getTotalProductsByLengthClassId($length_class_id); + + if ($product_total) { + $json['error'] = sprintf($this->language->get('error_product'), $product_total); + } + } + + if (!$json) { + $this->load->model('localisation/length_class'); + + foreach ($selected as $length_class_id) { + $this->model_localisation_length_class->deleteLengthClass($length_class_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/localisation/location.php b/admininistrator/controller/localisation/location.php new file mode 100644 index 0000000..0bccbfe --- /dev/null +++ b/admininistrator/controller/localisation/location.php @@ -0,0 +1,349 @@ +load->language('localisation/location'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/location', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('localisation/location.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('localisation/location.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/location', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('localisation/location'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('localisation/location.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['locations'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('localisation/location'); + + $location_total = $this->model_localisation_location->getTotalLocations(); + + $results = $this->model_localisation_location->getLocations($filter_data); + + foreach ($results as $result) { + $data['locations'][] = [ + 'location_id' => $result['location_id'], + 'name' => $result['name'], + 'address' => $result['address'], + 'edit' => $this->url->link('localisation/location.form', 'user_token=' . $this->session->data['user_token'] . '&location_id=' . $result['location_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('localisation/location.list', 'user_token=' . $this->session->data['user_token'] . '&sort=name' . $url); + $data['sort_address'] = $this->url->link('localisation/location.list', 'user_token=' . $this->session->data['user_token'] . '&sort=address' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $location_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('localisation/location.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($location_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($location_total - $this->config->get('config_pagination_admin'))) ? $location_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $location_total, ceil($location_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('localisation/location_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('localisation/location'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['location_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/location', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('localisation/location.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('localisation/location', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['location_id'])) { + $this->load->model('localisation/location'); + + $location_info = $this->model_localisation_location->getLocation($this->request->get['location_id']); + } + + if (isset($this->request->get['location_id'])) { + $data['location_id'] = (int)$this->request->get['location_id']; + } else { + $data['location_id'] = 0; + } + + $this->load->model('setting/store'); + + if (!empty($location_info)) { + $data['name'] = $location_info['name']; + } else { + $data['name'] = ''; + } + + if (!empty($location_info)) { + $data['address'] = $location_info['address']; + } else { + $data['address'] = ''; + } + + if (!empty($location_info)) { + $data['geocode'] = $location_info['geocode']; + } else { + $data['geocode'] = ''; + } + + if (!empty($location_info)) { + $data['telephone'] = $location_info['telephone']; + } else { + $data['telephone'] = ''; + } + + if (!empty($location_info)) { + $data['image'] = $location_info['image']; + } else { + $data['image'] = ''; + } + + $this->load->model('tool/image'); + + $data['placeholder'] = $this->model_tool_image->resize('no_image.png', 100, 100); + + if (is_file(DIR_IMAGE . html_entity_decode($data['image'], ENT_QUOTES, 'UTF-8'))) { + $data['thumb'] = $this->model_tool_image->resize(html_entity_decode($data['image'], ENT_QUOTES, 'UTF-8'), 100, 100); + } else { + $data['thumb'] = $data['placeholder']; + } + + if (!empty($location_info)) { + $data['open'] = $location_info['open']; + } else { + $data['open'] = ''; + } + + if (!empty($location_info)) { + $data['comment'] = $location_info['comment']; + } else { + $data['comment'] = ''; + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/location_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('localisation/location'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'localisation/location')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if ((oc_strlen($this->request->post['name']) < 3) || (oc_strlen($this->request->post['name']) > 32)) { + $json['error']['name'] = $this->language->get('error_name'); + } + + if ((oc_strlen($this->request->post['address']) < 3) || (oc_strlen($this->request->post['address']) > 128)) { + $json['error']['address'] = $this->language->get('error_address'); + } + + if ((oc_strlen($this->request->post['telephone']) < 3) || (oc_strlen($this->request->post['telephone']) > 32)) { + $json['error']['telephone'] = $this->language->get('error_telephone'); + } + + if (!$json) { + $this->load->model('localisation/location'); + + if (!$this->request->post['location_id']) { + $json['location_id'] = $this->model_localisation_location->addLocation($this->request->post); + } else { + $this->model_localisation_location->editLocation($this->request->post['location_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('localisation/location'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'localisation/location')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('localisation/location'); + + foreach ($selected as $location_id) { + $this->model_localisation_location->deleteLocation($location_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/localisation/order_status.php b/admininistrator/controller/localisation/order_status.php new file mode 100644 index 0000000..a8fdc19 --- /dev/null +++ b/admininistrator/controller/localisation/order_status.php @@ -0,0 +1,314 @@ +load->language('localisation/order_status'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/order_status', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('localisation/order_status.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('localisation/order_status.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/order_status', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('localisation/order_status'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('localisation/order_status.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['order_statuses'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('localisation/order_status'); + + $order_status_total = $this->model_localisation_order_status->getTotalOrderStatuses(); + + $results = $this->model_localisation_order_status->getOrderStatuses($filter_data); + + foreach ($results as $result) { + $data['order_statuses'][] = [ + 'order_status_id' => $result['order_status_id'], + 'name' => $result['name'] . (($result['order_status_id'] == $this->config->get('config_order_status_id')) ? $this->language->get('text_default') : ''), + 'edit' => $this->url->link('localisation/order_status.form', 'user_token=' . $this->session->data['user_token'] . '&order_status_id=' . $result['order_status_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('localisation/order_status.list', 'user_token=' . $this->session->data['user_token'] . '&sort=name' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $order_status_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('localisation/order_status.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($order_status_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($order_status_total - $this->config->get('config_pagination_admin'))) ? $order_status_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $order_status_total, ceil($order_status_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('localisation/order_status_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('localisation/order_status'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['order_status_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/order_status', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('localisation/order_status.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('localisation/order_status', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['order_status_id'])) { + $data['order_status_id'] = (int)$this->request->get['order_status_id']; + } else { + $data['order_status_id'] = 0; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (isset($this->request->get['order_status_id'])) { + $this->load->model('localisation/order_status'); + + $data['order_status'] = $this->model_localisation_order_status->getDescriptions($this->request->get['order_status_id']); + } else { + $data['order_status'] = []; + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/order_status_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('localisation/order_status'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'localisation/order_status')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + foreach ($this->request->post['order_status'] as $language_id => $value) { + if ((oc_strlen($value['name']) < 3) || (oc_strlen($value['name']) > 32)) { + $json['error']['name_' . $language_id] = $this->language->get('error_name'); + } + } + + if (!$json) { + $this->load->model('localisation/order_status'); + + if (!$this->request->post['order_status_id']) { + $json['order_status_id'] = $this->model_localisation_order_status->addOrderStatus($this->request->post); + } else { + $this->model_localisation_order_status->editOrderStatus($this->request->post['order_status_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('localisation/order_status'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'localisation/order_status')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('setting/store'); + $this->load->model('sale/order'); + + foreach ($selected as $order_status_id) { + if ($this->config->get('config_order_status_id') == $order_status_id) { + $json['error'] = $this->language->get('error_default'); + } + + $order_total = $this->model_sale_order->getTotalOrdersByOrderStatusId($order_status_id); + + if ($order_total) { + $json['error'] = sprintf($this->language->get('error_order'), $order_total); + } + + $order_total = $this->model_sale_order->getTotalHistoriesByOrderStatusId($order_status_id); + + if ($order_total) { + $json['error'] = sprintf($this->language->get('error_order'), $order_total); + } + } + + if (!$json) { + $this->load->model('localisation/order_status'); + + foreach ($selected as $order_status_id) { + $this->model_localisation_order_status->deleteOrderStatus($order_status_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/localisation/return_action.php b/admininistrator/controller/localisation/return_action.php new file mode 100644 index 0000000..49bd4b3 --- /dev/null +++ b/admininistrator/controller/localisation/return_action.php @@ -0,0 +1,302 @@ +load->language('localisation/return_action'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/return_action', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('localisation/return_action.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('localisation/return_action.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/return_action', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('localisation/return_action'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('localisation/return_action.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['return_actions'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('localisation/return_action'); + + $return_action_total = $this->model_localisation_return_action->getTotalReturnActions(); + + $results = $this->model_localisation_return_action->getReturnActions($filter_data); + + foreach ($results as $result) { + $data['return_actions'][] = [ + 'return_action_id' => $result['return_action_id'], + 'name' => $result['name'], + 'edit' => $this->url->link('localisation/return_action.form', 'user_token=' . $this->session->data['user_token'] . '&return_action_id=' . $result['return_action_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('localisation/return_action.list', 'user_token=' . $this->session->data['user_token'] . '&sort=name' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $return_action_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('localisation/return_action.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($return_action_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($return_action_total - $this->config->get('config_pagination_admin'))) ? $return_action_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $return_action_total, ceil($return_action_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('localisation/return_action_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('localisation/return_action'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['return_action_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/return_action', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('localisation/return_action.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('localisation/return_action', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['return_action_id'])) { + $data['return_action_id'] = (int)$this->request->get['return_action_id']; + } else { + $data['return_action_id'] = 0; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (isset($this->request->get['return_action_id'])) { + $this->load->model('localisation/return_action'); + + $data['return_action'] = $this->model_localisation_return_action->getDescriptions($this->request->get['return_action_id']); + } else { + $data['return_action'] = []; + } + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/return_action_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('localisation/return_action'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'localisation/return_action')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + foreach ($this->request->post['return_action'] as $language_id => $value) { + if ((oc_strlen($value['name']) < 3) || (oc_strlen($value['name']) > 64)) { + $json['error']['name_' . $language_id] = $this->language->get('error_name'); + } + } + + if (!$json) { + $this->load->model('localisation/return_action'); + + if (!$this->request->post['return_action_id']) { + $json['return_action_id'] = $this->model_localisation_return_action->addReturnAction($this->request->post); + } else { + $this->model_localisation_return_action->editReturnAction($this->request->post['return_action_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('localisation/return_action'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'localisation/return_action')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('sale/returns'); + + foreach ($selected as $return_action_id) { + $return_total = $this->model_sale_returns->getTotalReturnsByReturnActionId($return_action_id); + + if ($return_total) { + $json['error'] = sprintf($this->language->get('error_return'), $return_total); + } + } + + if (!$json) { + $this->load->model('localisation/return_action'); + + foreach ($selected as $return_action_id) { + $this->model_localisation_return_action->deleteReturnAction($return_action_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/localisation/return_reason.php b/admininistrator/controller/localisation/return_reason.php new file mode 100644 index 0000000..9532f3f --- /dev/null +++ b/admininistrator/controller/localisation/return_reason.php @@ -0,0 +1,301 @@ +load->language('localisation/return_reason'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/return_reason', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('localisation/return_reason.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('localisation/return_reason.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/return_reason', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('localisation/return_reason'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('localisation/return_reason.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['return_reasons'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('localisation/return_reason'); + + $return_reason_total = $this->model_localisation_return_reason->getTotalReturnReasons(); + + $results = $this->model_localisation_return_reason->getReturnReasons($filter_data); + + foreach ($results as $result) { + $data['return_reasons'][] = [ + 'return_reason_id' => $result['return_reason_id'], + 'name' => $result['name'], + 'edit' => $this->url->link('localisation/return_reason.form', 'user_token=' . $this->session->data['user_token'] . '&return_reason_id=' . $result['return_reason_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('localisation/return_reason.list', 'user_token=' . $this->session->data['user_token'] . '&sort=name' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $return_reason_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('localisation/return_reason.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($return_reason_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($return_reason_total - $this->config->get('config_pagination_admin'))) ? $return_reason_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $return_reason_total, ceil($return_reason_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('localisation/return_reason_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('localisation/return_reason'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['return_reason_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/return_reason', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('localisation/return_reason.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('localisation/return_reason', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['return_reason_id'])) { + $data['return_reason_id'] = (int)$this->request->get['return_reason_id']; + } else { + $data['return_reason_id'] = 0; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (isset($this->request->get['return_reason_id'])) { + $this->load->model('localisation/return_reason'); + + $data['return_reason'] = $this->model_localisation_return_reason->getDescriptions($this->request->get['return_reason_id']); + } else { + $data['return_reason'] = []; + } + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/return_reason_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('localisation/return_reason'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'localisation/return_reason')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + foreach ($this->request->post['return_reason'] as $language_id => $value) { + if ((oc_strlen($value['name']) < 3) || (oc_strlen($value['name']) > 128)) { + $json['error']['name_' . $language_id] = $this->language->get('error_name'); + } + } + + if (!$json) { + $this->load->model('localisation/return_reason'); + + if (!$this->request->post['return_reason_id']) { + $json['return_reason_id'] = $this->model_localisation_return_reason->addReturnReason($this->request->post); + } else { + $this->model_localisation_return_reason->editReturnReason($this->request->post['return_reason_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('localisation/return_reason'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'localisation/return_reason')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('sale/returns'); + + foreach ($selected as $return_reason_id) { + $return_total = $this->model_sale_returns->getTotalReturnsByReturnReasonId($return_reason_id); + + if ($return_total) { + $json['error'] = sprintf($this->language->get('error_return'), $return_total); + } + } + + if (!$json) { + $this->load->model('localisation/return_reason'); + + foreach ($selected as $return_reason_id) { + $this->model_localisation_return_reason->deleteReturnReason($return_reason_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/localisation/return_status.php b/admininistrator/controller/localisation/return_status.php new file mode 100644 index 0000000..e1adf57 --- /dev/null +++ b/admininistrator/controller/localisation/return_status.php @@ -0,0 +1,311 @@ +load->language('localisation/return_status'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/return_status', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('localisation/return_status.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('localisation/return_status.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/return_status', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('localisation/return_status'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('localisation/return_status.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['return_statuses'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('localisation/return_status'); + + $return_status_total = $this->model_localisation_return_status->getTotalReturnStatuses(); + + $results = $this->model_localisation_return_status->getReturnStatuses($filter_data); + + foreach ($results as $result) { + $data['return_statuses'][] = [ + 'return_status_id' => $result['return_status_id'], + 'name' => $result['name'] . (($result['return_status_id'] == $this->config->get('config_return_status_id')) ? $this->language->get('text_default') : ''), + 'edit' => $this->url->link('localisation/return_status.form', 'user_token=' . $this->session->data['user_token'] . '&return_status_id=' . $result['return_status_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('localisation/return_status.list', 'user_token=' . $this->session->data['user_token'] . '&sort=name' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $return_status_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('localisation/return_status.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($return_status_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($return_status_total - $this->config->get('config_pagination_admin'))) ? $return_status_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $return_status_total, ceil($return_status_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('localisation/return_status_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('localisation/return_status'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['return_status_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/return_status', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('localisation/return_status.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('localisation/return_status', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['return_status_id'])) { + $data['return_status_id'] = (int)$this->request->get['return_status_id']; + } else { + $data['return_status_id'] = 0; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (isset($this->request->get['return_status_id'])) { + $this->load->model('localisation/return_status'); + + $data['return_status'] = $this->model_localisation_return_status->getDescriptions($this->request->get['return_status_id']); + } else { + $data['return_status'] = []; + } + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/return_status_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('localisation/return_status'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'localisation/return_status')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + foreach ($this->request->post['return_status'] as $language_id => $value) { + if ((oc_strlen($value['name']) < 3) || (oc_strlen($value['name']) > 32)) { + $json['error']['name_' . $language_id] = $this->language->get('error_name'); + } + } + + if (!$json) { + $this->load->model('localisation/return_status'); + + if (!$this->request->post['return_status_id']) { + $json['return_status_id'] = $this->model_localisation_return_status->addReturnStatus($this->request->post); + } else { + $this->model_localisation_return_status->editReturnStatus($this->request->post['return_status_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('localisation/return_status'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'localisation/return_status')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('sale/returns'); + + foreach ($this->request->post['selected'] as $return_status_id) { + if ($this->config->get('config_return_status_id') == $return_status_id) { + $json['error'] = $this->language->get('error_default'); + } + + $return_total = $this->model_sale_returns->getTotalReturnsByReturnStatusId($return_status_id); + + if ($return_total) { + $json['error'] = sprintf($this->language->get('error_return'), $return_total); + } + + $return_total = $this->model_sale_returns->getTotalHistoriesByReturnStatusId($return_status_id); + + if ($return_total) { + $json['error'] = sprintf($this->language->get('error_return'), $return_total); + } + } + + if (!$json) { + $this->load->model('localisation/return_status'); + + foreach ($selected as $return_status_id) { + $this->model_localisation_return_status->deleteReturnStatus($return_status_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/localisation/stock_status.php b/admininistrator/controller/localisation/stock_status.php new file mode 100644 index 0000000..5a9f95e --- /dev/null +++ b/admininistrator/controller/localisation/stock_status.php @@ -0,0 +1,301 @@ +load->language('localisation/stock_status'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/stock_status', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('localisation/stock_status.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('localisation/stock_status.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/stock_status', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('localisation/stock_status'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('localisation/stock_status.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['stock_statuses'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('localisation/stock_status'); + + $stock_status_total = $this->model_localisation_stock_status->getTotalStockStatuses(); + + $results = $this->model_localisation_stock_status->getStockStatuses($filter_data); + + foreach ($results as $result) { + $data['stock_statuses'][] = [ + 'stock_status_id' => $result['stock_status_id'], + 'name' => $result['name'], + 'edit' => $this->url->link('localisation/stock_status.form', 'user_token=' . $this->session->data['user_token'] . '&stock_status_id=' . $result['stock_status_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('localisation/stock_status.list', 'user_token=' . $this->session->data['user_token'] . '&sort=name' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $stock_status_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('localisation/stock_status.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($stock_status_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($stock_status_total - $this->config->get('config_pagination_admin'))) ? $stock_status_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $stock_status_total, ceil($stock_status_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('localisation/stock_status_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('localisation/stock_status'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['stock_status_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/stock_status', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('localisation/stock_status.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('localisation/stock_status', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['stock_status_id'])) { + $data['stock_status_id'] = (int)$this->request->get['stock_status_id']; + } else { + $data['stock_status_id'] = 0; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (isset($this->request->get['stock_status_id'])) { + $this->load->model('localisation/stock_status'); + + $data['stock_status'] = $this->model_localisation_stock_status->getDescriptions($this->request->get['stock_status_id']); + } else { + $data['stock_status'] = []; + } + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/stock_status_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('localisation/stock_status'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'localisation/stock_status')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + foreach ($this->request->post['stock_status'] as $language_id => $value) { + if ((oc_strlen($value['name']) < 3) || (oc_strlen($value['name']) > 32)) { + $json['error']['name_' . $language_id] = $this->language->get('error_name'); + } + } + + if (!$json) { + $this->load->model('localisation/stock_status'); + + if (!$this->request->post['stock_status_id']) { + $json['stock_status_id'] = $this->model_localisation_stock_status->addStockStatus($this->request->post); + } else { + $this->model_localisation_stock_status->editStockStatus($this->request->post['stock_status_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('localisation/stock_status'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'localisation/stock_status')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('catalog/product'); + + foreach ($selected as $stock_status_id) { + $product_total = $this->model_catalog_product->getTotalProductsByStockStatusId($stock_status_id); + + if ($product_total) { + $json['error'] = sprintf($this->language->get('error_product'), $product_total); + } + } + + if (!$json) { + $this->load->model('localisation/stock_status'); + + foreach ($selected as $stock_status_id) { + $this->model_localisation_stock_status->deleteStockStatus($stock_status_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/localisation/subscription_status.php b/admininistrator/controller/localisation/subscription_status.php new file mode 100644 index 0000000..3147566 --- /dev/null +++ b/admininistrator/controller/localisation/subscription_status.php @@ -0,0 +1,314 @@ +load->language('localisation/subscription_status'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/subscription_status', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('localisation/subscription_status.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('localisation/subscription_status.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/subscription_status', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('localisation/subscription_status'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('localisation/subscription_status.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['subscription_statuses'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('localisation/subscription_status'); + + $subscription_status_total = $this->model_localisation_subscription_status->getTotalSubscriptionStatuses(); + + $results = $this->model_localisation_subscription_status->getSubscriptionStatuses($filter_data); + + foreach ($results as $result) { + $data['subscription_statuses'][] = [ + 'subscription_status_id' => $result['subscription_status_id'], + 'name' => $result['name'] . (($result['subscription_status_id'] == $this->config->get('config_subscription_status_id')) ? $this->language->get('text_default') : ''), + 'edit' => $this->url->link('localisation/subscription_status.form', 'user_token=' . $this->session->data['user_token'] . '&subscription_status_id=' . $result['subscription_status_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('localisation/subscription_status.list', 'user_token=' . $this->session->data['user_token'] . '&sort=name' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $subscription_status_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('localisation/subscription_status.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($subscription_status_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($subscription_status_total - $this->config->get('config_pagination_admin'))) ? $subscription_status_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $subscription_status_total, ceil($subscription_status_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('localisation/subscription_status_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('localisation/subscription_status'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['subscription_status_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/subscription_status', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('localisation/subscription_status.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('localisation/subscription_status', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['subscription_status_id'])) { + $data['subscription_status_id'] = (int)$this->request->get['subscription_status_id']; + } else { + $data['subscription_status_id'] = 0; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (isset($this->request->get['subscription_status_id'])) { + $this->load->model('localisation/subscription_status'); + + $data['subscription_status'] = $this->model_localisation_subscription_status->getDescriptions($this->request->get['subscription_status_id']); + } else { + $data['subscription_status'] = []; + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/subscription_status_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('localisation/subscription_status'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'localisation/subscription_status')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + foreach ($this->request->post['subscription_status'] as $language_id => $value) { + if ((oc_strlen($value['name']) < 3) || (oc_strlen($value['name']) > 32)) { + $json['error']['name_' . $language_id] = $this->language->get('error_name'); + } + } + + if (!$json) { + $this->load->model('localisation/subscription_status'); + + if (!$this->request->post['subscription_status_id']) { + $json['subscription_status_id'] = $this->model_localisation_subscription_status->addSubscriptionStatus($this->request->post); + } else { + $this->model_localisation_subscription_status->editSubscriptionStatus($this->request->post['subscription_status_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('localisation/subscription_status'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'localisation/subscription_status')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('setting/store'); + $this->load->model('sale/subscription'); + + foreach ($selected as $subscription_status_id) { + if ($this->config->get('config_subscription_status_id') == $subscription_status_id) { + $json['error'] = $this->language->get('error_default'); + } + + $subscription_total = $this->model_sale_subscription->getTotalSubscriptionsBySubscriptionStatusId($subscription_status_id); + + if ($subscription_total) { + $json['error'] = sprintf($this->language->get('error_subscription'), $subscription_total); + } + + $subscription_total = $this->model_sale_subscription->getTotalHistoriesBySubscriptionStatusId($subscription_status_id); + + if ($subscription_total) { + $json['error'] = sprintf($this->language->get('error_subscription'), $subscription_total); + } + } + + if (!$json) { + $this->load->model('localisation/subscription_status'); + + foreach ($selected as $subscription_status_id) { + $this->model_localisation_subscription_status->deleteSubscriptionStatus($subscription_status_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/localisation/tax_class.php b/admininistrator/controller/localisation/tax_class.php new file mode 100644 index 0000000..972e421 --- /dev/null +++ b/admininistrator/controller/localisation/tax_class.php @@ -0,0 +1,319 @@ +load->language('localisation/tax_class'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/tax_class', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('localisation/tax_class.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('localisation/tax_class.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/tax_class', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('localisation/tax_class'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'title'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('localisation/tax_class.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['tax_classes'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('localisation/tax_class'); + + $tax_class_total = $this->model_localisation_tax_class->getTotalTaxClasses(); + + $results = $this->model_localisation_tax_class->getTaxClasses($filter_data); + + foreach ($results as $result) { + $data['tax_classes'][] = [ + 'tax_class_id' => $result['tax_class_id'], + 'title' => $result['title'], + 'edit' => $this->url->link('localisation/tax_class.form', 'user_token=' . $this->session->data['user_token'] . '&tax_class_id=' . $result['tax_class_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_title'] = $this->url->link('localisation/tax_class.list', 'user_token=' . $this->session->data['user_token'] . '&sort=title' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $tax_class_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('localisation/tax_class.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($tax_class_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($tax_class_total - $this->config->get('config_pagination_admin'))) ? $tax_class_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $tax_class_total, ceil($tax_class_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('localisation/tax_class_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('localisation/tax_class'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['tax_class_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/tax_class', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('localisation/tax_class.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('localisation/tax_class', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['tax_class_id'])) { + $this->load->model('localisation/tax_class'); + + $tax_class_info = $this->model_localisation_tax_class->getTaxClass($this->request->get['tax_class_id']); + } + + if (isset($this->request->get['tax_class_id'])) { + $data['tax_class_id'] = (int)$this->request->get['tax_class_id']; + } else { + $data['tax_class_id'] = 0; + } + + if (!empty($tax_class_info)) { + $data['title'] = $tax_class_info['title']; + } else { + $data['title'] = ''; + } + + if (!empty($tax_class_info)) { + $data['description'] = $tax_class_info['description']; + } else { + $data['description'] = ''; + } + + $this->load->model('localisation/tax_rate'); + + $data['tax_rates'] = $this->model_localisation_tax_rate->getTaxRates(); + + if (isset($this->request->get['tax_class_id'])) { + $data['tax_rules'] = $this->model_localisation_tax_class->getTaxRules($this->request->get['tax_class_id']); + } else { + $data['tax_rules'] = []; + } + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/tax_class_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('localisation/tax_class'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'localisation/tax_class')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if ((oc_strlen($this->request->post['title']) < 3) || (oc_strlen($this->request->post['title']) > 32)) { + $json['error']['title'] = $this->language->get('error_title'); + } + + if ((oc_strlen($this->request->post['description']) < 3) || (oc_strlen($this->request->post['description']) > 255)) { + $json['error']['description'] = $this->language->get('error_description'); + } + + if (!$json) { + $this->load->model('localisation/tax_class'); + + if (!$this->request->post['tax_class_id']) { + $json['tax_class_id'] = $this->model_localisation_tax_class->addTaxClass($this->request->post); + } else { + $this->model_localisation_tax_class->editTaxClass($this->request->post['tax_class_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('localisation/tax_class'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'localisation/tax_class')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('catalog/product'); + + foreach ($selected as $tax_class_id) { + $product_total = $this->model_catalog_product->getTotalProductsByTaxClassId($tax_class_id); + + if ($product_total) { + $json['error'] = sprintf($this->language->get('error_product'), $product_total); + } + } + + if (!$json) { + $this->load->model('localisation/tax_class'); + + foreach ($selected as $tax_class_id) { + $this->model_localisation_tax_class->deleteTaxClass($tax_class_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/localisation/tax_rate.php b/admininistrator/controller/localisation/tax_rate.php new file mode 100644 index 0000000..b8b0046 --- /dev/null +++ b/admininistrator/controller/localisation/tax_rate.php @@ -0,0 +1,345 @@ +load->language('localisation/tax_rate'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/tax_rate', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('localisation/tax_rate.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('localisation/tax_rate.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/tax_rate', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('localisation/tax_rate'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'tr.name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('localisation/tax_rate.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['tax_rates'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('localisation/tax_rate'); + + $tax_rate_total = $this->model_localisation_tax_rate->getTotalTaxRates(); + + $results = $this->model_localisation_tax_rate->getTaxRates($filter_data); + + foreach ($results as $result) { + $data['tax_rates'][] = [ + 'tax_rate_id' => $result['tax_rate_id'], + 'name' => $result['name'], + 'rate' => $result['rate'], + 'type' => ($result['type'] == 'F' ? $this->language->get('text_amount') : $this->language->get('text_percent')), + 'geo_zone' => $result['geo_zone'], + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])), + 'date_modified' => date($this->language->get('date_format_short'), strtotime($result['date_modified'])), + 'edit' => $this->url->link('localisation/tax_rate.form', 'user_token=' . $this->session->data['user_token'] . '&tax_rate_id=' . $result['tax_rate_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('localisation/tax_rate.list', 'user_token=' . $this->session->data['user_token'] . '&sort=tr.name' . $url); + $data['sort_rate'] = $this->url->link('localisation/tax_rate.list', 'user_token=' . $this->session->data['user_token'] . '&sort=tr.rate' . $url); + $data['sort_type'] = $this->url->link('localisation/tax_rate.list', 'user_token=' . $this->session->data['user_token'] . '&sort=tr.type' . $url); + $data['sort_geo_zone'] = $this->url->link('localisation/tax_rate.list', 'user_token=' . $this->session->data['user_token'] . '&sort=gz.name' . $url); + $data['sort_date_added'] = $this->url->link('localisation/tax_rate.list', 'user_token=' . $this->session->data['user_token'] . '&sort=tr.date_added' . $url); + $data['sort_date_modified'] = $this->url->link('localisation/tax_rate.list', 'user_token=' . $this->session->data['user_token'] . '&sort=tr.date_modified' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $tax_rate_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('localisation/tax_rate.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($tax_rate_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($tax_rate_total - $this->config->get('config_pagination_admin'))) ? $tax_rate_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $tax_rate_total, ceil($tax_rate_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('localisation/tax_rate_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('localisation/tax_rate'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['tax_rate_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/tax_rate', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('localisation/tax_rate.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('localisation/tax_rate', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['tax_rate_id'])) { + $this->load->model('localisation/tax_rate'); + + $tax_rate_info = $this->model_localisation_tax_rate->getTaxRate($this->request->get['tax_rate_id']); + } + + if (isset($this->request->get['tax_rate_id'])) { + $data['tax_rate_id'] = (int)$this->request->get['tax_rate_id']; + } else { + $data['tax_rate_id'] = 0; + } + + if (!empty($tax_rate_info)) { + $data['name'] = $tax_rate_info['name']; + } else { + $data['name'] = ''; + } + + if (!empty($tax_rate_info)) { + $data['rate'] = $tax_rate_info['rate']; + } else { + $data['rate'] = ''; + } + + if (!empty($tax_rate_info)) { + $data['type'] = $tax_rate_info['type']; + } else { + $data['type'] = ''; + } + + $this->load->model('customer/customer_group'); + + $data['customer_groups'] = $this->model_customer_customer_group->getCustomerGroups(); + + if (isset($this->request->get['tax_rate_id'])) { + $data['tax_rate_customer_group'] = $this->model_localisation_tax_rate->getCustomerGroups($this->request->get['tax_rate_id']); + } else { + $data['tax_rate_customer_group'] = [$this->config->get('config_customer_group_id')]; + } + + $this->load->model('localisation/geo_zone'); + + $data['geo_zones'] = $this->model_localisation_geo_zone->getGeoZones(); + + if (!empty($tax_rate_info)) { + $data['geo_zone_id'] = $tax_rate_info['geo_zone_id']; + } else { + $data['geo_zone_id'] = ''; + } + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/tax_rate_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('localisation/tax_rate'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'localisation/tax_rate')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if ((oc_strlen($this->request->post['name']) < 3) || (oc_strlen($this->request->post['name']) > 32)) { + $json['error']['name'] = $this->language->get('error_name'); + } + + if (!$this->request->post['rate']) { + $json['error']['rate'] = $this->language->get('error_rate'); + } + + if (!$json) { + $this->load->model('localisation/tax_rate'); + + if (!$this->request->post['tax_rate_id']) { + $json['tax_rate_id'] = $this->model_localisation_tax_rate->addTaxRate($this->request->post); + } else { + $this->model_localisation_tax_rate->editTaxRate($this->request->post['tax_rate_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('localisation/tax_rate'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'localisation/tax_rate')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('localisation/tax_class'); + + foreach ($this->request->post['selected'] as $tax_rate_id) { + $tax_rule_total = $this->model_localisation_tax_class->getTotalTaxRulesByTaxRateId($tax_rate_id); + + if ($tax_rule_total) { + $json['error'] = sprintf($this->language->get('error_tax_rule'), $tax_rule_total); + } + } + + if (!$json) { + $this->load->model('localisation/tax_rate'); + + foreach ($selected as $tax_rate_id) { + $this->model_localisation_tax_rate->deleteTaxRate($tax_rate_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/localisation/weight_class.php b/admininistrator/controller/localisation/weight_class.php new file mode 100644 index 0000000..5322953 --- /dev/null +++ b/admininistrator/controller/localisation/weight_class.php @@ -0,0 +1,321 @@ +load->language('localisation/weight_class'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/weight_class', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('localisation/weight_class.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('localisation/weight_class.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/weight_class', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('localisation/weight_class'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'title'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('localisation/weight_class.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['weight_classes'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('localisation/weight_class'); + + $weight_class_total = $this->model_localisation_weight_class->getTotalWeightClasses(); + + $results = $this->model_localisation_weight_class->getWeightClasses($filter_data); + + foreach ($results as $result) { + $data['weight_classes'][] = [ + 'weight_class_id' => $result['weight_class_id'], + 'title' => $result['title'] . (($result['weight_class_id'] == $this->config->get('config_weight_class_id')) ? $this->language->get('text_default') : ''), + 'unit' => $result['unit'], + 'value' => $result['value'], + 'edit' => $this->url->link('localisation/weight_class.form', 'user_token=' . $this->session->data['user_token'] . '&weight_class_id=' . $result['weight_class_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_title'] = $this->url->link('localisation/weight_class.list', 'user_token=' . $this->session->data['user_token'] . '&sort=title' . $url); + $data['sort_unit'] = $this->url->link('localisation/weight_class.list', 'user_token=' . $this->session->data['user_token'] . '&sort=unit' . $url); + $data['sort_value'] = $this->url->link('localisation/weight_class.list', 'user_token=' . $this->session->data['user_token'] . '&sort=value' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $weight_class_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('localisation/weight_class.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($weight_class_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($weight_class_total - $this->config->get('config_pagination_admin'))) ? $weight_class_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $weight_class_total, ceil($weight_class_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('localisation/weight_class_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('localisation/weight_class'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['weight_class_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/weight_class', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('localisation/weight_class.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('localisation/weight_class', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['weight_class_id'])) { + $this->load->model('localisation/weight_class'); + + $weight_class_info = $this->model_localisation_weight_class->getWeightClass($this->request->get['weight_class_id']); + } + + if (isset($this->request->get['weight_class_id'])) { + $data['weight_class_id'] = (int)$this->request->get['weight_class_id']; + } else { + $data['weight_class_id'] = 0; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (isset($this->request->get['weight_class_id'])) { + $data['weight_class_description'] = $this->model_localisation_weight_class->getDescriptions($this->request->get['weight_class_id']); + } else { + $data['weight_class_description'] = []; + } + + if (!empty($weight_class_info)) { + $data['value'] = $weight_class_info['value']; + } else { + $data['value'] = ''; + } + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/weight_class_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('localisation/weight_class'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'localisation/weight_class')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + foreach ($this->request->post['weight_class_description'] as $language_id => $value) { + if ((oc_strlen($value['title']) < 3) || (oc_strlen($value['title']) > 32)) { + $json['error']['title_' . $language_id] = $this->language->get('error_title'); + } + + if (!$value['unit'] || (oc_strlen($value['unit']) > 4)) { + $json['error']['unit_' . $language_id] = $this->language->get('error_unit'); + } + } + + if (!$json) { + $this->load->model('localisation/weight_class'); + + if (!$this->request->post['weight_class_id']) { + $json['weight_class_id'] = $this->model_localisation_weight_class->addWeightClass($this->request->post); + } else { + $this->model_localisation_weight_class->editWeightClass($this->request->post['weight_class_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('localisation/weight_class'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'localisation/weight_class')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('catalog/product'); + + foreach ($selected as $weight_class_id) { + if ($this->config->get('config_weight_class_id') == $weight_class_id) { + $json['error'] = $this->language->get('error_default'); + } + + $product_total = $this->model_catalog_product->getTotalProductsByWeightClassId($weight_class_id); + + if ($product_total) { + $json['error'] = sprintf($this->language->get('error_product'), $product_total); + } + } + + if (!$json) { + $this->load->model('localisation/weight_class'); + + foreach ($selected as $weight_class_id) { + $this->model_localisation_weight_class->deleteWeightClass($weight_class_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/localisation/zone.php b/admininistrator/controller/localisation/zone.php new file mode 100644 index 0000000..79eef3a --- /dev/null +++ b/admininistrator/controller/localisation/zone.php @@ -0,0 +1,435 @@ +load->language('localisation/zone'); + + $this->document->setTitle($this->language->get('heading_title')); + + if (isset($this->request->get['filter_name'])) { + $filter_name = (string)$this->request->get['filter_name']; + } else { + $filter_name = ''; + } + + if (isset($this->request->get['filter_country'])) { + $filter_country = (string)$this->request->get['filter_country']; + } else { + $filter_country = ''; + } + + if (isset($this->request->get['filter_code'])) { + $filter_code = (string)$this->request->get['filter_code']; + } else { + $filter_code = ''; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/zone', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('localisation/zone.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('localisation/zone.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['filter_name'] = $filter_name; + $data['filter_country'] = $filter_country; + $data['filter_code'] = $filter_code; + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/zone', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('localisation/zone'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['filter_name'])) { + $filter_name = (string)$this->request->get['filter_name']; + } else { + $filter_name = ''; + } + + if (isset($this->request->get['filter_country'])) { + $filter_country = (string)$this->request->get['filter_country']; + } else { + $filter_country = ''; + } + + if (isset($this->request->get['filter_code'])) { + $filter_code = (string)$this->request->get['filter_code']; + } else { + $filter_code = ''; + } + + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'c.name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_country'])) { + $url .= '&filter_country=' . urlencode(html_entity_decode($this->request->get['filter_country'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_code'])) { + $url .= '&filter_code=' . urlencode(html_entity_decode($this->request->get['filter_code'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('localisation/zone.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['zones'] = []; + + $filter_data = [ + 'filter_name' => $filter_name, + 'filter_country' => $filter_country, + 'filter_code' => $filter_code, + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('localisation/zone'); + + $zone_total = $this->model_localisation_zone->getTotalZones($filter_data); + + $results = $this->model_localisation_zone->getZones($filter_data); + + foreach ($results as $result) { + $data['zones'][] = [ + 'zone_id' => $result['zone_id'], + 'country' => $result['country'], + 'name' => $result['name'] . (($result['zone_id'] == $this->config->get('config_zone_id')) ? $this->language->get('text_default') : ''), + 'code' => $result['code'], + 'status' => $result['status'], + 'edit' => $this->url->link('localisation/zone.form', 'user_token=' . $this->session->data['user_token'] . '&zone_id=' . $result['zone_id'] . $url) + ]; + } + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_country'])) { + $url .= '&filter_country=' . urlencode(html_entity_decode($this->request->get['filter_country'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_code'])) { + $url .= '&filter_code=' . urlencode(html_entity_decode($this->request->get['filter_code'], ENT_QUOTES, 'UTF-8')); + } + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_country'] = $this->url->link('localisation/zone.list', 'user_token=' . $this->session->data['user_token'] . '&sort=c.name' . $url); + $data['sort_name'] = $this->url->link('localisation/zone.list', 'user_token=' . $this->session->data['user_token'] . '&sort=z.name' . $url); + $data['sort_code'] = $this->url->link('localisation/zone.list', 'user_token=' . $this->session->data['user_token'] . '&sort=z.code' . $url); + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_country'])) { + $url .= '&filter_country=' . urlencode(html_entity_decode($this->request->get['filter_country'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_code'])) { + $url .= '&filter_code=' . urlencode(html_entity_decode($this->request->get['filter_code'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $zone_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('localisation/zone.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($zone_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($zone_total - $this->config->get('config_pagination_admin'))) ? $zone_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $zone_total, ceil($zone_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('localisation/zone_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('localisation/zone'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['zone_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_country'])) { + $url .= '&filter_country=' . urlencode(html_entity_decode($this->request->get['filter_country'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_code'])) { + $url .= '&filter_code=' . urlencode(html_entity_decode($this->request->get['filter_code'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('localisation/zone', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('localisation/zone.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('localisation/zone', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['zone_id'])) { + $this->load->model('localisation/zone'); + + $zone_info = $this->model_localisation_zone->getZone($this->request->get['zone_id']); + } + + if (isset($this->request->get['zone_id'])) { + $data['zone_id'] = (int)$this->request->get['zone_id']; + } else { + $data['zone_id'] = 0; + } + + if (!empty($zone_info)) { + $data['status'] = $zone_info['status']; + } else { + $data['status'] = '1'; + } + + if (!empty($zone_info)) { + $data['name'] = $zone_info['name']; + } else { + $data['name'] = ''; + } + + if (!empty($zone_info)) { + $data['code'] = $zone_info['code']; + } else { + $data['code'] = ''; + } + + $this->load->model('localisation/country'); + + $data['countries'] = $this->model_localisation_country->getCountries(); + + if (!empty($zone_info)) { + $data['country_id'] = $zone_info['country_id']; + } else { + $data['country_id'] = ''; + } + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('localisation/zone_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('localisation/zone'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'localisation/zone')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if ((oc_strlen($this->request->post['name']) < 1) || (oc_strlen($this->request->post['name']) > 64)) { + $json['error']['name'] = $this->language->get('error_name'); + } + + if (!$json) { + $this->load->model('localisation/zone'); + + if (!$this->request->post['zone_id']) { + $json['zone_id'] = $this->model_localisation_zone->addZone($this->request->post); + } else { + $this->model_localisation_zone->editZone($this->request->post['zone_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('localisation/zone'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'localisation/zone')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('setting/store'); + $this->load->model('customer/customer'); + $this->load->model('localisation/geo_zone'); + + foreach ($selected as $zone_id) { + if ($this->config->get('config_zone_id') == $zone_id) { + $json['error'] = $this->language->get('error_default'); + } + + $store_total = $this->model_setting_store->getTotalStoresByZoneId($zone_id); + + if ($store_total) { + $json['error'] = sprintf($this->language->get('error_store'), $store_total); + } + + $address_total = $this->model_customer_customer->getTotalAddressesByZoneId($zone_id); + + if ($address_total) { + $json['error'] = sprintf($this->language->get('error_address'), $address_total); + } + + $zone_to_geo_zone_total = $this->model_localisation_geo_zone->getTotalZoneToGeoZoneByZoneId($zone_id); + + if ($zone_to_geo_zone_total) { + $json['error'] = sprintf($this->language->get('error_zone_to_geo_zone'), $zone_to_geo_zone_total); + } + } + + if (!$json) { + $this->load->model('localisation/zone'); + + foreach ($selected as $zone_id) { + $this->model_localisation_zone->deleteZone($zone_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/mail/affiliate.php b/admininistrator/controller/mail/affiliate.php new file mode 100644 index 0000000..23a52cc --- /dev/null +++ b/admininistrator/controller/mail/affiliate.php @@ -0,0 +1,174 @@ +load->model('customer/customer'); + + $customer_info = $this->model_customer_customer->getCustomer($customer_id); + + if ($customer_info) { + $this->load->model('setting/store'); + + $store_info = $this->model_setting_store->getStore($customer_info['store_id']); + + if ($store_info) { + $store_name = html_entity_decode($store_info['name'], ENT_QUOTES, 'UTF-8'); + $store_url = $store_info['url']; + } else { + $store_name = html_entity_decode($this->config->get('config_name'), ENT_QUOTES, 'UTF-8'); + $store_url = HTTP_CATALOG; + } + + $this->load->model('localisation/language'); + + $language_info = $this->model_localisation_language->getLanguage($customer_info['language_id']); + + if ($language_info) { + $language_code = $language_info['code']; + } else { + $language_code = $this->config->get('config_language'); + } + + // Load the language for any mails using a different country code and prefixing it so it does not pollute the main data pool. + $this->load->language('default', 'mail', $language_code); + $this->load->language('mail/affiliate_approve', 'mail', $language_code); + + // Add language vars to the template folder + $results = $this->language->all('mail'); + + foreach ($results as $key => $value) { + $data[$key] = $value; + } + + $subject = sprintf($this->language->get('mail_text_subject'), $store_name); + + $data['text_welcome'] = sprintf($this->language->get('mail_text_welcome'), $store_name); + + $data['login'] = $store_url . 'index.php?route=affiliate/login'; + + $data['store'] = $store_name; + $data['store_url'] = $store_url; + + if ($this->config->get('config_mail_engine')) { + $mail_option = [ + 'parameter' => $this->config->get('config_mail_parameter'), + 'smtp_hostname' => $this->config->get('config_mail_smtp_hostname'), + 'smtp_username' => $this->config->get('config_mail_smtp_username'), + 'smtp_password' => html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8'), + 'smtp_port' => $this->config->get('config_mail_smtp_port'), + 'smtp_timeout' => $this->config->get('config_mail_smtp_timeout') + ]; + + $mail = new \Opencart\System\Library\Mail($this->config->get('config_mail_engine'), $mail_option); + $mail->setTo($customer_info['email']); + $mail->setFrom($this->config->get('config_email')); + $mail->setSender($store_name); + $mail->setSubject($subject); + $mail->setHtml($this->load->view('mail/affiliate_approve', $data)); + $mail->send(); + } + } + } + + /** + * @param string $route + * @param array $args + * @param mixed $output + * + * @return void + * @throws \Exception + */ + public function deny(string &$route, array &$args, mixed &$output): void { + if (isset($args[0])) { + $customer_id = (int)$args[0]; + } else { + $customer_id = 0; + } + + $this->load->model('customer/customer'); + + $customer_info = $this->model_customer_customer->getCustomer($customer_id); + + if ($customer_info) { + $this->load->model('setting/store'); + + $store_info = $this->model_setting_store->getStore($customer_info['store_id']); + + if ($store_info) { + $store_name = html_entity_decode($store_info['name'], ENT_QUOTES, 'UTF-8'); + $store_url = $store_info['url']; + } else { + $store_name = html_entity_decode($this->config->get('config_name'), ENT_QUOTES, 'UTF-8'); + $store_url = HTTP_CATALOG; + } + + $this->load->model('localisation/language'); + + $language_info = $this->model_localisation_language->getLanguage($customer_info['language_id']); + + if ($language_info) { + $language_code = $language_info['code']; + } else { + $language_code = $this->config->get('config_language'); + } + + // Load the language for any mails using a different country code and prefixing it so it does not pollute the main data pool. + $this->load->language('default', 'mail', $language_code); + $this->load->language('mail/affiliate_deny', 'mail', $language_code); + + // Add language vars to the template folder + $results = $this->language->all('mail'); + + foreach ($results as $key => $value) { + $data[$key] = $value; + } + + $subject = sprintf($this->language->get('mail_text_subject'), $store_name); + + $data['text_welcome'] = sprintf($this->language->get('mail_text_welcome'), $store_name); + + $data['contact'] = $store_url . 'index.php?route=information/contact'; + + $data['store'] = $store_name; + $data['store_url'] = $store_url; + + if ($this->config->get('config_mail_engine')) { + $mail_option = [ + 'parameter' => $this->config->get('config_mail_parameter'), + 'smtp_hostname' => $this->config->get('config_mail_smtp_hostname'), + 'smtp_username' => $this->config->get('config_mail_smtp_username'), + 'smtp_password' => html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8'), + 'smtp_port' => $this->config->get('config_mail_smtp_port'), + 'smtp_timeout' => $this->config->get('config_mail_smtp_timeout') + ]; + + $mail = new \Opencart\System\Library\Mail($this->config->get('config_mail_engine'), $mail_option); + $mail->setTo($customer_info['email']); + $mail->setFrom($this->config->get('config_email')); + $mail->setSender($store_name); + $mail->setSubject($subject); + $mail->setHtml($this->load->view('mail/affiliate_deny', $data)); + $mail->send(); + } + } + } +} \ No newline at end of file diff --git a/admininistrator/controller/mail/authorize.php b/admininistrator/controller/mail/authorize.php new file mode 100644 index 0000000..633f6b6 --- /dev/null +++ b/admininistrator/controller/mail/authorize.php @@ -0,0 +1,119 @@ +request->get['route'])) { + $route = (string)$this->request->get['route']; + } else { + $route = ''; + } + + $email = $this->user->getEmail(); + + if (isset($this->session->data['code'])) { + $code = $this->session->data['code']; + } else { + $code = ''; + } + + if ($email && $code && ($route == 'common/authorize.send') && filter_var($email, FILTER_VALIDATE_EMAIL)) { + $this->load->language('mail/authorize'); + + $data['username'] = $this->user->getUsername(); + $data['code'] = $code; + $data['ip'] = $this->request->server['REMOTE_ADDR']; + $data['store'] = html_entity_decode($this->config->get('config_name'), ENT_QUOTES, 'UTF-8'); + + if ($this->config->get('config_mail_engine')) { + $mail_option = [ + 'parameter' => $this->config->get('config_mail_parameter'), + 'smtp_hostname' => $this->config->get('config_mail_smtp_hostname'), + 'smtp_username' => $this->config->get('config_mail_smtp_username'), + 'smtp_password' => html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8'), + 'smtp_port' => $this->config->get('config_mail_smtp_port'), + 'smtp_timeout' => $this->config->get('config_mail_smtp_timeout') + ]; + + $mail = new \Opencart\System\Library\Mail($this->config->get('config_mail_engine'), $mail_option); + $mail->setTo($email); + $mail->setFrom($this->config->get('config_email')); + $mail->setSender($this->config->get('config_name')); + $mail->setSubject($this->language->get('text_subject')); + $mail->setText($this->load->view('mail/authorize', $data)); + $mail->send(); + } + } + } + + // admin/model/user/user/editCode/after + + /** + * @param $route + * @param $args + * @param $output + * + * @return void + * @throws \Exception + */ + public function reset(&$route, &$args, &$output) { + if (isset($this->request->get['route'])) { + $route = $this->request->get['route']; + } else { + $route = ''; + } + + if (isset($args[0])) { + $email = (string)$args[0]; + } else { + $email = ''; + } + + if (isset($args[1])) { + $code = (string)$args[1]; + } else { + $code = ''; + } + + if ($email && $code && ($route == 'common/authorize.confirm') && filter_var($email, FILTER_VALIDATE_EMAIL)) { + $this->load->language('mail/authorize_reset'); + + $data['username'] = $this->user->getUsername(); + $data['reset'] = $this->url->link('common/authorize.reset', 'email=' . $email . '&code=' . $code, true); + $data['ip'] = $this->request->server['REMOTE_ADDR']; + $data['store'] = html_entity_decode($this->config->get('config_name'), ENT_QUOTES, 'UTF-8'); + + if ($this->config->get('config_mail_engine')) { + $mail_option = [ + 'parameter' => $this->config->get('config_mail_parameter'), + 'smtp_hostname' => $this->config->get('config_mail_smtp_hostname'), + 'smtp_username' => $this->config->get('config_mail_smtp_username'), + 'smtp_password' => html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8'), + 'smtp_port' => $this->config->get('config_mail_smtp_port'), + 'smtp_timeout' => $this->config->get('config_mail_smtp_timeout') + ]; + + $mail = new \Opencart\System\Library\Mail($this->config->get('config_mail_engine'), $mail_option); + $mail->setTo($email); + $mail->setFrom($this->config->get('config_email')); + $mail->setSender($this->config->get('config_name')); + $mail->setSubject($this->language->get('text_subject')); + $mail->setText($this->load->view('mail/authorize_reset', $data)); + $mail->send(); + } + } + } +} diff --git a/admininistrator/controller/mail/customer.php b/admininistrator/controller/mail/customer.php new file mode 100644 index 0000000..c479620 --- /dev/null +++ b/admininistrator/controller/mail/customer.php @@ -0,0 +1,198 @@ +load->model('customer/customer'); + + $customer_info = $this->model_customer_customer->getCustomer($customer_id); + + if ($customer_info) { + $this->load->model('setting/store'); + + $store_info = $this->model_setting_store->getStore($customer_info['store_id']); + + if ($store_info) { + $this->load->model('setting/setting'); + + $store_logo = html_entity_decode($this->model_setting_setting->getValue('config_logo', $store_info['store_id']), ENT_QUOTES, 'UTF-8'); + $store_name = html_entity_decode($store_info['name'], ENT_QUOTES, 'UTF-8'); + $store_url = $store_info['url']; + } else { + $store_logo = html_entity_decode($this->config->get('config_logo'), ENT_QUOTES, 'UTF-8'); + $store_name = html_entity_decode($this->config->get('config_name'), ENT_QUOTES, 'UTF-8'); + $store_url = HTTP_CATALOG; + } + + $this->load->model('localisation/language'); + + $language_info = $this->model_localisation_language->getLanguage($customer_info['language_id']); + + if ($language_info) { + $language_code = $language_info['code']; + } else { + $language_code = $this->config->get('config_language'); + } + + // Load the language for any mails using a different country code and prefixing it so it does not pollute the main data pool. + $this->load->language('default', 'mail', $language_code); + $this->load->language('mail/customer_approve', 'mail', $language_code); + + // Add language vars to the template folder + $results = $this->language->all('mail'); + + foreach ($results as $key => $value) { + $data[$key] = $value; + } + + $this->load->model('tool/image'); + + if (is_file(DIR_IMAGE . $store_logo)) { + $data['logo'] = $store_url . 'image/' . $store_logo; + } else { + $data['logo'] = ''; + } + + $subject = sprintf($this->language->get('mail_text_subject'), $store_name); + + $data['text_welcome'] = sprintf($this->language->get('mail_text_welcome'), $store_name); + + $data['login'] = $store_url . 'index.php?route=account/login'; + + $data['store'] = $store_name; + $data['store_url'] = $store_url; + + if ($this->config->get('config_mail_engine')) { + $mail_option = [ + 'parameter' => $this->config->get('config_mail_parameter'), + 'smtp_hostname' => $this->config->get('config_mail_smtp_hostname'), + 'smtp_username' => $this->config->get('config_mail_smtp_username'), + 'smtp_password' => html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8'), + 'smtp_port' => $this->config->get('config_mail_smtp_port'), + 'smtp_timeout' => $this->config->get('config_mail_smtp_timeout') + ]; + + $mail = new \Opencart\System\Library\Mail($this->config->get('config_mail_engine'), $mail_option); + $mail->setTo($customer_info['email']); + $mail->setFrom($this->config->get('config_email')); + $mail->setSender($store_name); + $mail->setSubject($subject); + $mail->setHtml($this->load->view('mail/customer_approve', $data)); + $mail->send(); + } + } + } + + /** + * @param string $route + * @param array $args + * @param mixed $output + * + * @return void + * @throws \Exception + */ + public function deny(string &$route, array &$args, mixed &$output): void { + if (isset($args[0])) { + $customer_id = (int)$args[0]; + } else { + $customer_id = 0; + } + + $this->load->model('customer/customer'); + + $customer_info = $this->model_customer_customer->getCustomer($customer_id); + + if ($customer_info) { + $this->load->model('setting/store'); + + $store_info = $this->model_setting_store->getStore($customer_info['store_id']); + + if ($store_info) { + $this->load->model('setting/setting'); + + $store_logo = html_entity_decode($this->model_setting_setting->getValue('config_logo', $customer_info['store_id']), ENT_QUOTES, 'UTF-8'); + $store_name = html_entity_decode($store_info['name'], ENT_QUOTES, 'UTF-8'); + $store_url = $store_info['url']; + } else { + $store_logo = html_entity_decode($this->config->get('config_logo'), ENT_QUOTES, 'UTF-8'); + $store_name = html_entity_decode($this->config->get('config_name'), ENT_QUOTES, 'UTF-8'); + $store_url = HTTP_CATALOG; + } + + $this->load->model('localisation/language'); + + $language_info = $this->model_localisation_language->getLanguage($customer_info['language_id']); + + if ($language_info) { + $language_code = $language_info['code']; + } else { + $language_code = $this->config->get('config_language'); + } + + // Load the language for any mails using a different country code and prefixing it so it does not pollute the main data pool. + $this->load->language('default', 'mail', $language_code); + $this->load->language('mail/customer_deny', 'mail', $language_code); + + // Add language vars to the template folder + $results = $this->language->all('mail'); + + foreach ($results as $key => $value) { + $data[$key] = $value; + } + + $this->load->model('tool/image'); + + if (is_file(DIR_IMAGE . $store_logo)) { + $data['logo'] = $store_url . 'image/' . $store_logo; + } else { + $data['logo'] = ''; + } + + $subject = sprintf($this->language->get('mail_text_subject'), $store_name); + + $data['text_welcome'] = sprintf($this->language->get('mail_text_welcome'), $store_name); + + $data['contact'] = $store_url . 'index.php?route=information/contact'; + + $data['store'] = $store_name; + $data['store_url'] = $store_url; + + if ($this->config->get('config_mail_engine')) { + $mail_option = [ + 'parameter' => $this->config->get('config_mail_parameter'), + 'smtp_hostname' => $this->config->get('config_mail_smtp_hostname'), + 'smtp_username' => $this->config->get('config_mail_smtp_username'), + 'smtp_password' => html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8'), + 'smtp_port' => $this->config->get('config_mail_smtp_port'), + 'smtp_timeout' => $this->config->get('config_mail_smtp_timeout') + ]; + + $mail = new \Opencart\System\Library\Mail($this->config->get('config_mail_engine'), $mail_option); + $mail->setTo($customer_info['email']); + $mail->setFrom($this->config->get('config_email')); + $mail->setSender($store_name); + $mail->setSubject($subject); + $mail->setHtml($this->load->view('mail/customer_deny', $data)); + $mail->send(); + } + } + } +} diff --git a/admininistrator/controller/mail/forgotten.php b/admininistrator/controller/mail/forgotten.php new file mode 100644 index 0000000..58c98ce --- /dev/null +++ b/admininistrator/controller/mail/forgotten.php @@ -0,0 +1,74 @@ +request->get['route'])) { + $route = (string)$this->request->get['route']; + } else { + $route = ''; + } + + if (isset($args[0])) { + $email = urldecode((string)$args[0]); + } else { + $email = ''; + } + + if (isset($args[1])) { + $code = (string)$args[1]; + } else { + $code = ''; + } + + if ($email && $code && ($route == 'common/forgotten.confirm') && filter_var($email, FILTER_VALIDATE_EMAIL)) { + $this->load->language('mail/forgotten'); + + $store_name = html_entity_decode($this->config->get('config_name'), ENT_QUOTES, 'UTF-8'); + + $subject = sprintf($this->language->get('text_subject'), $store_name); + + $data['text_greeting'] = sprintf($this->language->get('text_greeting'), $store_name); + + $data['reset'] = $this->url->link('common/forgotten.reset', 'email=' . $email . '&code=' . $code, true); + $data['ip'] = $this->request->server['REMOTE_ADDR']; + + $data['store'] = $store_name; + $data['store_url'] = $this->config->get('config_store_url'); + + if ($this->config->get('config_mail_engine')) { + $mail_option = [ + 'parameter' => $this->config->get('config_mail_parameter'), + 'smtp_hostname' => $this->config->get('config_mail_smtp_hostname'), + 'smtp_username' => $this->config->get('config_mail_smtp_username'), + 'smtp_password' => html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8'), + 'smtp_port' => $this->config->get('config_mail_smtp_port'), + 'smtp_timeout' => $this->config->get('config_mail_smtp_timeout') + ]; + + $mail = new \Opencart\System\Library\Mail($this->config->get('config_mail_engine'), $mail_option); + $mail->setTo($email); + $mail->setFrom($this->config->get('config_email')); + $mail->setSender($store_name); + $mail->setSubject($subject); + $mail->setHtml($this->load->view('mail/forgotten', $data)); + $mail->send(); + } + } + } +} diff --git a/admininistrator/controller/mail/gdpr.php b/admininistrator/controller/mail/gdpr.php new file mode 100644 index 0000000..fb1fff2 --- /dev/null +++ b/admininistrator/controller/mail/gdpr.php @@ -0,0 +1,493 @@ +load->model('customer/gdpr'); + + $gdpr_info = $this->model_customer_gdpr->getGdpr($args[0]); + + if ($gdpr_info) { + // Choose which mail to send + + // Export plus complete + if ($gdpr_info['action'] == 'export' && (int)$args[1] == 3) { + $this->export($gdpr_info); + } + + // Approve plus processing + if ($gdpr_info['action'] == 'approve' && (int)$args[1] == 2) { + $this->approve($gdpr_info); + } + + // Remove plus complete + if ($gdpr_info['action'] == 'remove' && (int)$args[1] == 3) { + $this->remove($gdpr_info); + } + + // Deny + if ($args[1] == -1) { + $this->deny($gdpr_info); + } + } + } + + /** + * @param array $gdpr_info + * + * @return void + * @throws \Exception + */ + public function export(array $gdpr_info): void { + $this->load->model('setting/store'); + + $store_info = $this->model_setting_store->getStore($gdpr_info['store_id']); + + if ($store_info) { + $this->load->model('setting/setting'); + + $store_logo = html_entity_decode($this->model_setting_setting->getValue('config_logo', $store_info['store_id']), ENT_QUOTES, 'UTF-8'); + $store_name = html_entity_decode($store_info['name'], ENT_QUOTES, 'UTF-8'); + $store_url = $store_info['url']; + } else { + $store_logo = html_entity_decode($this->config->get('config_logo'), ENT_QUOTES, 'UTF-8'); + $store_name = html_entity_decode($this->config->get('config_name'), ENT_QUOTES, 'UTF-8'); + $store_url = HTTP_CATALOG; + } + + // Send the email in the correct language + $this->load->model('localisation/language'); + + $language_info = $this->model_localisation_language->getLanguage($gdpr_info['language_id']); + + if ($language_info) { + $language_code = $language_info['code']; + } else { + $language_code = $this->config->get('config_language'); + } + + // Load the language for any mails using a different country code and prefixing it so it does not pollute the main data pool. + $this->load->language('default', 'mail', $language_code); + $this->load->language('mail/gdpr_export', 'mail', $language_code); + + // Add language vars to the template folder + $results = $this->language->all('mail'); + + foreach ($results as $key => $value) { + $data[$key] = $value; + } + + $subject = sprintf($this->language->get('mail_text_subject'), $store_name); + + if (is_file(DIR_IMAGE . $store_logo)) { + $data['logo'] = $store_url . 'image/' . $store_logo; + } else { + $data['logo'] = ''; + } + + $this->load->model('customer/customer'); + + $customer_info = $this->model_customer_customer->getCustomerByEmail($gdpr_info['email']); + + if ($customer_info) { + $data['text_hello'] = sprintf($this->language->get('mail_text_hello'), html_entity_decode($customer_info['firstname'], ENT_QUOTES, 'UTF-8')); + } else { + $data['text_hello'] = sprintf($this->language->get('mail_text_hello'), $this->language->get('mail_text_user')); + } + + // Personal info + if ($customer_info) { + $data['customer_id'] = $customer_info['customer_id']; + $data['firstname'] = $customer_info['firstname']; + $data['lastname'] = $customer_info['lastname']; + $data['email'] = $customer_info['email']; + $data['telephone'] = $customer_info['telephone']; + } + + // Addresses + $data['addresses'] = []; + + if ($customer_info) { + $results = $this->model_customer_customer->getAddresses($customer_info['customer_id']); + + foreach ($results as $result) { + $address = [ + 'firstname' => $result['firstname'], + 'lastname' => $result['lastname'], + 'address_1' => $result['address_1'], + 'address_2' => $result['address_2'], + 'city' => $result['city'], + 'postcode' => $result['postcode'], + 'country' => $result['country'], + 'zone' => $result['zone'] + ]; + + if (!in_array($address, $data['addresses'])) { + $data['addresses'][] = $address; + } + } + } + + // Order Addresses + $this->load->model('sale/order'); + + $results = $this->model_sale_order->getOrders(['filter_email' => $gdpr_info['email']]); + + foreach ($results as $result) { + $order_info = $this->model_sale_order->getOrder($result['order_id']); + + if ($order_info['payment_country_id']) { + $address = [ + 'firstname' => $order_info['payment_firstname'], + 'lastname' => $order_info['payment_lastname'], + 'address_1' => $order_info['payment_address_1'], + 'address_2' => $order_info['payment_address_2'], + 'city' => $order_info['payment_city'], + 'postcode' => $order_info['payment_postcode'], + 'country' => $order_info['payment_country'], + 'zone' => $order_info['payment_zone'] + ]; + + if (!in_array($address, $data['addresses'])) { + $data['addresses'][] = $address; + } + } + + if ($order_info['shipping_country_id']) { + $address = [ + 'firstname' => $order_info['shipping_firstname'], + 'lastname' => $order_info['shipping_lastname'], + 'address_1' => $order_info['shipping_address_1'], + 'address_2' => $order_info['shipping_address_2'], + 'city' => $order_info['shipping_city'], + 'postcode' => $order_info['shipping_postcode'], + 'country' => $order_info['shipping_country'], + 'zone' => $order_info['shipping_zone'] + ]; + + if (!in_array($address, $data['addresses'])) { + $data['addresses'][] = $address; + } + } + } + + // Ip's + $data['ips'] = []; + + if ($customer_info) { + $results = $this->model_customer_customer->getIps($customer_info['customer_id']); + + foreach ($results as $result) { + $data['ips'][] = [ + 'ip' => $result['ip'], + 'date_added' => date($this->language->get('mail_datetime_format'), strtotime($result['date_added'])) + ]; + } + } + + $data['store_name'] = $store_name; + $data['store_url'] = $store_url; + + if ($this->config->get('config_mail_engine')) { + $mail_option = [ + 'parameter' => $this->config->get('config_mail_parameter'), + 'smtp_hostname' => $this->config->get('config_mail_smtp_hostname'), + 'smtp_username' => $this->config->get('config_mail_smtp_username'), + 'smtp_password' => html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8'), + 'smtp_port' => $this->config->get('config_mail_smtp_port'), + 'smtp_timeout' => $this->config->get('config_mail_smtp_timeout') + ]; + + $mail = new \Opencart\System\Library\Mail($this->config->get('config_mail_engine'), $mail_option); + $mail->setTo($gdpr_info['email']); + $mail->setFrom($this->config->get('config_email')); + $mail->setSender($store_name); + $mail->setSubject($subject); + $mail->setHtml($this->load->view('mail/gdpr_export', $data)); + $mail->send(); + } + } + + /** + * @param array $gdpr_info + * + * @return void + * @throws \Exception + */ + public function approve(array $gdpr_info): void { + $this->load->model('setting/store'); + + $store_info = $this->model_setting_store->getStore($gdpr_info['store_id']); + + if ($store_info) { + $this->load->model('setting/setting'); + + $store_logo = html_entity_decode($this->model_setting_setting->getValue('config_logo', $store_info['store_id']), ENT_QUOTES, 'UTF-8'); + $store_name = html_entity_decode($store_info['name'], ENT_QUOTES, 'UTF-8'); + $store_url = $store_info['url']; + } else { + $store_logo = html_entity_decode($this->config->get('config_logo'), ENT_QUOTES, 'UTF-8'); + $store_name = html_entity_decode($this->config->get('config_name'), ENT_QUOTES, 'UTF-8'); + $store_url = HTTP_CATALOG; + } + + // Send the email in the correct language + $this->load->model('localisation/language'); + + $language_info = $this->model_localisation_language->getLanguage($gdpr_info['language_id']); + + if ($language_info) { + $language_code = $language_info['code']; + } else { + $language_code = $this->config->get('config_language'); + } + + // Load the language for any mails using a different country code and prefixing it so it does not pollute the main data pool. + $this->load->language('default', 'mail', $language_code); + $this->load->language('mail/gdpr_approve', 'mail', $language_code); + + // Add language vars to the template folder + $results = $this->language->all('mail'); + + foreach ($results as $key => $value) { + $data[$key] = $value; + } + + $subject = sprintf($this->language->get('mail_text_subject'), $store_name); + + $this->load->model('tool/image'); + + if (is_file(DIR_IMAGE . $store_logo)) { + $data['logo'] = $store_url . 'image/' . $store_logo; + } else { + $data['logo'] = ''; + } + + $this->load->model('customer/customer'); + + $customer_info = $this->model_customer_customer->getCustomerByEmail($gdpr_info['email']); + + if ($customer_info) { + $data['text_hello'] = sprintf($this->language->get('mail_text_hello'), html_entity_decode($customer_info['firstname'], ENT_QUOTES, 'UTF-8')); + } else { + $data['text_hello'] = sprintf($this->language->get('mail_text_hello'), $this->language->get('mail_text_user')); + } + + $data['text_gdpr'] = sprintf($this->language->get('mail_text_gdpr'), $this->config->get('config_gdpr_limit')); + $data['text_a'] = sprintf($this->language->get('mail_text_a'), $this->config->get('config_gdpr_limit')); + + $data['store_name'] = $store_name; + $data['store_url'] = $store_url; + + if ($this->config->get('config_mail_engine')) { + $mail_option = [ + 'parameter' => $this->config->get('config_mail_parameter'), + 'smtp_hostname' => $this->config->get('config_mail_smtp_hostname'), + 'smtp_username' => $this->config->get('config_mail_smtp_username'), + 'smtp_password' => html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8'), + 'smtp_port' => $this->config->get('config_mail_smtp_port'), + 'smtp_timeout' => $this->config->get('config_mail_smtp_timeout') + ]; + + $mail = new \Opencart\System\Library\Mail($this->config->get('config_mail_engine'), $mail_option); + $mail->setTo($gdpr_info['email']); + $mail->setFrom($this->config->get('config_email')); + $mail->setSender($store_name); + $mail->setSubject($subject); + $mail->setHtml($this->load->view('mail/gdpr_approve', $data)); + $mail->send(); + } + } + + /** + * @param array $gdpr_info + * + * @return void + * @throws \Exception + */ + public function deny(array $gdpr_info): void { + $this->load->model('setting/store'); + + $store_info = $this->model_setting_store->getStore($gdpr_info['store_id']); + + if ($store_info) { + $this->load->model('setting/setting'); + + $store_logo = html_entity_decode($this->model_setting_setting->getValue('config_logo', $store_info['store_id']), ENT_QUOTES, 'UTF-8'); + $store_name = html_entity_decode($store_info['name'], ENT_QUOTES, 'UTF-8'); + $store_url = $store_info['url']; + } else { + $store_logo = html_entity_decode($this->config->get('config_logo'), ENT_QUOTES, 'UTF-8'); + $store_name = html_entity_decode($this->config->get('config_name'), ENT_QUOTES, 'UTF-8'); + $store_url = HTTP_CATALOG; + } + + // Send the email in the correct language + $this->load->model('localisation/language'); + + $language_info = $this->model_localisation_language->getLanguage($gdpr_info['language_id']); + + if ($language_info) { + $language_code = $language_info['code']; + } else { + $language_code = $this->config->get('config_language'); + } + + // Load the language for any mails using a different country code and prefixing it so it does not pollute the main data pool. + $this->load->language('default', 'mail', $language_code); + $this->load->language('mail/gdpr_deny', 'mail', $language_code); + + // Add language vars to the template folder + $results = $this->language->all('mail'); + + foreach ($results as $key => $value) { + $data[$key] = $value; + } + + $subject = sprintf($this->language->get('mail_text_subject'), $store_name); + + $this->load->model('tool/image'); + + if (is_file(DIR_IMAGE . $store_logo)) { + $data['logo'] = $store_url . 'image/' . $store_logo; + } else { + $data['logo'] = ''; + } + + $data['text_request'] = $this->language->get('mail_text_' . $gdpr_info['action']); + + $this->load->model('customer/customer'); + + $customer_info = $this->model_customer_customer->getCustomerByEmail($gdpr_info['email']); + + if ($customer_info) { + $data['text_hello'] = sprintf($this->language->get('mail_text_hello'), html_entity_decode($customer_info['firstname'], ENT_QUOTES, 'UTF-8')); + } else { + $data['text_hello'] = sprintf($this->language->get('mail_text_hello'), $this->language->get('mail_text_user')); + } + + $data['store_name'] = $store_name; + $data['store_url'] = $store_url; + $data['contact'] = $store_url . 'index.php?route=information/contact'; + + if ($this->config->get('config_mail_engine')) { + $mail_option = [ + 'parameter' => $this->config->get('config_mail_parameter'), + 'smtp_hostname' => $this->config->get('config_mail_smtp_hostname'), + 'smtp_username' => $this->config->get('config_mail_smtp_username'), + 'smtp_password' => html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8'), + 'smtp_port' => $this->config->get('config_mail_smtp_port'), + 'smtp_timeout' => $this->config->get('config_mail_smtp_timeout') + ]; + + $mail = new \Opencart\System\Library\Mail($this->config->get('config_mail_engine'), $mail_option); + $mail->setTo($gdpr_info['email']); + $mail->setFrom($this->config->get('config_email')); + $mail->setSender($store_name); + $mail->setSubject($subject); + $mail->setHtml($this->load->view('mail/gdpr_deny', $data)); + $mail->send(); + } + } + + /** + * @param array $gdpr_info + * + * @return void + * @throws \Exception + */ + public function remove(array $gdpr_info): void { + $this->load->model('setting/store'); + + $store_info = $this->model_setting_store->getStore($gdpr_info['store_id']); + + if ($store_info) { + $this->load->model('setting/setting'); + + $store_logo = html_entity_decode($this->model_setting_setting->getValue('config_logo', $store_info['store_id']), ENT_QUOTES, 'UTF-8'); + $store_name = html_entity_decode($store_info['name'], ENT_QUOTES, 'UTF-8'); + $store_url = $store_info['url']; + } else { + $store_logo = html_entity_decode($this->config->get('config_logo'), ENT_QUOTES, 'UTF-8'); + $store_name = html_entity_decode($this->config->get('config_name'), ENT_QUOTES, 'UTF-8'); + $store_url = HTTP_CATALOG; + } + + // Send the email in the correct language + $this->load->model('localisation/language'); + + $language_info = $this->model_localisation_language->getLanguage($gdpr_info['language_id']); + + if ($language_info) { + $language_code = $language_info['code']; + } else { + $language_code = $this->config->get('config_language'); + } + + // Load the language for any mails using a different country code and prefixing it so it does not pollute the main data pool. + $this->load->language('default', 'mail', $language_code); + $this->load->language('mail/gdpr_delete', 'mail', $language_code); + + // Add language vars to the template folder + $results = $this->language->all('mail'); + + foreach ($results as $key => $value) { + $data[$key] = $value; + } + + $subject = sprintf($this->language->get('mail_text_subject'), $store_name); + + $this->load->model('tool/image'); + + if (is_file(DIR_IMAGE . $store_logo)) { + $data['logo'] = $store_url . 'image/' . $store_logo; + } else { + $data['logo'] = ''; + } + + $this->load->model('customer/customer'); + + $customer_info = $this->model_customer_customer->getCustomerByEmail($gdpr_info['email']); + + if ($customer_info) { + $data['text_hello'] = sprintf($this->language->get('mail_text_hello'), html_entity_decode($customer_info['firstname'], ENT_QUOTES, 'UTF-8')); + } else { + $data['text_hello'] = sprintf($this->language->get('mail_text_hello'), $this->language->get('mail_text_user')); + } + + $data['store_name'] = $store_name; + $data['store_url'] = $store_url; + $data['contact'] = $store_url . 'index.php?route=information/contact'; + + if ($this->config->get('config_mail_engine')) { + $mail_option = [ + 'parameter' => $this->config->get('config_mail_parameter'), + 'smtp_hostname' => $this->config->get('config_mail_smtp_hostname'), + 'smtp_username' => $this->config->get('config_mail_smtp_username'), + 'smtp_password' => html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8'), + 'smtp_port' => $this->config->get('config_mail_smtp_port'), + 'smtp_timeout' => $this->config->get('config_mail_smtp_timeout') + ]; + + $mail = new \Opencart\System\Library\Mail($this->config->get('config_mail_engine'), $mail_option); + $mail->setTo($gdpr_info['email']); + $mail->setFrom($this->config->get('config_email')); + $mail->setSender($store_name); + $mail->setSubject($subject); + $mail->setHtml($this->load->view('mail/gdpr_delete', $data)); + $mail->send(); + } + } +} diff --git a/admininistrator/controller/mail/returns.php b/admininistrator/controller/mail/returns.php new file mode 100644 index 0000000..2114619 --- /dev/null +++ b/admininistrator/controller/mail/returns.php @@ -0,0 +1,104 @@ +load->model('sale/returns'); + + $return_info = $this->model_sale_returns->getReturn($return_id); + + if ($return_info) { + $this->load->model('sale/order'); + + $order_info = $this->model_sale_order->getOrder($return_info['order_id']); + + if ($order_info) { + $store_name = html_entity_decode($order_info['store_name'], ENT_QUOTES, 'UTF-8'); + $store_url = $order_info['store_url']; + } else { + $store_name = html_entity_decode($this->config->get('config_name'), ENT_QUOTES, 'UTF-8'); + $store_url = HTTP_CATALOG; + } + + $this->load->model('localisation/language'); + + $language_info = $this->model_localisation_language->getLanguage($return_info['language_id']); + + if ($language_info) { + $language_code = $language_info['code']; + } else { + $language_code = $this->config->get('config_language'); + } + + $this->load->language('default', 'mail', $language_code); + $this->load->language('mail/returns', 'mail', $language_code); + + $subject = sprintf($this->language->get('mail_text_subject'), $store_name, $return_id); + + $data['return_id'] = $return_id; + $data['date_added'] = date($this->language->get('date_format_short'), strtotime($return_info['date_modified'])); + $data['return_status'] = $return_info['return_status']; + $data['comment'] = nl2br($comment); + + $data['store'] = $store_name; + $data['store_url'] = $store_url; + + if ($this->config->get('config_mail_engine')) { + $mail_option = [ + 'parameter' => $this->config->get('config_mail_parameter'), + 'smtp_hostname' => $this->config->get('config_mail_smtp_hostname'), + 'smtp_username' => $this->config->get('config_mail_smtp_username'), + 'smtp_password' => html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8'), + 'smtp_port' => $this->config->get('config_mail_smtp_port'), + 'smtp_timeout' => $this->config->get('config_mail_smtp_timeout') + ]; + + $mail = new \Opencart\System\Library\Mail($this->config->get('config_mail_engine'), $mail_option); + $mail->setTo($return_info['email']); + $mail->setFrom($this->config->get('config_email')); + $mail->setSender($store_name); + $mail->setSubject($subject); + $mail->setHtml($this->load->view('mail/returns', $data)); + $mail->send(); + } + } + } + } +} diff --git a/admininistrator/controller/mail/reward.php b/admininistrator/controller/mail/reward.php new file mode 100644 index 0000000..0bbddef --- /dev/null +++ b/admininistrator/controller/mail/reward.php @@ -0,0 +1,102 @@ +load->model('customer/customer'); + + $customer_info = $this->model_customer_customer->getCustomer($customer_id); + + if ($customer_info) { + $this->load->language('mail/reward'); + + $this->load->model('setting/store'); + + $store_info = $this->model_setting_store->getStore($customer_info['store_id']); + + if ($store_info) { + $store_name = html_entity_decode($store_info['name'], ENT_QUOTES, 'UTF-8'); + $store_url = $store_info['url']; + } else { + $store_name = html_entity_decode($this->config->get('config_name'), ENT_QUOTES, 'UTF-8'); + $store_url = HTTP_CATALOG; + } + + $this->load->model('localisation/language'); + + $language_info = $this->model_localisation_language->getLanguage($customer_info['language_id']); + + if ($language_info) { + $language_code = $language_info['code']; + } else { + $language_code = $this->config->get('config_language'); + } + + $this->load->language('default', 'mail', $language_code); + $this->load->language('mail/reward', 'mail', $language_code); + + $subject = sprintf($this->language->get('mail_text_subject'), $store_name); + + $data['text_received'] = sprintf($this->language->get('mail_text_received'), $points); + $data['text_total'] = sprintf($this->language->get('mail_text_total'), $this->model_customer_customer->getRewardTotal($customer_id)); + + $data['store'] = $store_name; + $data['store_url'] = $store_url; + + if ($this->config->get('config_mail_engine')) { + $mail_option = [ + 'parameter' => $this->config->get('config_mail_parameter'), + 'smtp_hostname' => $this->config->get('config_mail_smtp_hostname'), + 'smtp_username' => $this->config->get('config_mail_smtp_username'), + 'smtp_password' => html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8'), + 'smtp_port' => $this->config->get('config_mail_smtp_port'), + 'smtp_timeout' => $this->config->get('config_mail_smtp_timeout') + ]; + + $mail = new \Opencart\System\Library\Mail($this->config->get('config_mail_engine'), $mail_option); + $mail->setTo($customer_info['email']); + $mail->setFrom($this->config->get('config_email')); + $mail->setSender($store_name); + $mail->setSubject($subject); + $mail->setHtml($this->load->view('mail/reward', $data)); + $mail->send(); + } + } + } +} diff --git a/admininistrator/controller/mail/subscription.php b/admininistrator/controller/mail/subscription.php new file mode 100644 index 0000000..4c4c172 --- /dev/null +++ b/admininistrator/controller/mail/subscription.php @@ -0,0 +1,284 @@ +load->model('sale/subscription'); + + $filter_data = [ + 'filter_subscription_id' => $subscription_id, + 'filter_subscription_status_id' => $subscription_status_id, + 'filter_date_next' => date('Y-m-d H:i:s') + ]; + + $subscriptions = $this->model_checkout_subscription->getSubscriptions($filter_data); + + if ($subscriptions) { + foreach ($subscriptions as $subscription) { + // Subscription histories + $history_total = $this->model_sale_subscription->getTotalHistoriesBySubscriptionStatusId($subscription_status_id); + + // The charge() method handles the subscription statuses in the cron/subscription + // controller from the catalog whereas an extension needs to return the active subscription status + if ($history_total && $subscription['subscription_status_id'] == $subscription_status_id) { + // Subscription Statuses + $this->load->model('localisation/subscription_status'); + + $subscription_status_info = $this->model_localisation_subscription_status->getSubscriptionStatus($subscription_status_id); + + if ($subscription_status_info) { + // Customers + $this->load->model('customer/customer'); + + // Customer payment + $customer_payment_info = $this->model_customer_customer->getPaymentMehod($subscription['customer_id'], $subscription['customer_payment_id']); + + if ($customer_payment_info) { + // Since the customer payment is integrated into the customer/customer page, + // we need to gather the customer's information rather than the order + $customer_info = $this->model_customer_customer->getCustomer($subscription['customer_id']); + + if ($customer_info) { + // Settings + $this->load->model('setting/setting'); + + // Store + $store_info = $this->model_setting_setting->getSetting('config', $customer_info['store_id']); + + if ($store_info) { + $from = $store_info['config_email']; + $store_name = $store_info['config_name']; + $store_url = $store_info['config_url']; + $alert_email = $store_info['config_mail_alert_email']; + } else { + $from = $this->config->get('config_email'); + $store_name = $this->config->get('config_name'); + $store_url = HTTP_CATALOG; + $alert_email = $this->config->get('config_mail_alert_email'); + } + + // Languages + $this->load->model('localisation/language'); + + $language_info = $this->model_localisation_language->getLanguage($customer_info['language_id']); + + if ($language_info) { + if ($comment && $notify) { + $data['comment'] = nl2br($comment); + } else { + $data['comment'] = ''; + } + + $data['subscription_status'] = $subscription_status_info['name']; + + // Languages + $this->load->model('localisation/language'); + + $language_info = $this->model_localisation_language->getLanguage($customer_info['language_id']); + + if ($language_info) { + $language_code = $language_info['code']; + } else { + $language_code = $this->config->get('config_language'); + } + + // Load the language for any mails using a different country code and prefixing it so it does not pollute the main data pool. + $this->load->language('default', 'mail', $language_code); + $this->load->language('mail/subscription', 'mail', $language_code); + + $data['date_added'] = date($this->language->get('mail_date_format_short'), $subscription['date_added']); + + // Text + $data['text_comment'] = $this->language->get('mail_text_comment'); + $data['text_date_added'] = $this->language->get('mail_text_date_added'); + $data['text_footer'] = $this->language->get('mail_text_footer'); + $data['text_subscription_status'] = $this->language->get('mail_text_subscription_status'); + + if ($this->config->get('config_mail_engine')) { + $mail = new \Opencart\System\Library\Mail($this->config->get('config_mail_engine')); + $mail->parameter = $this->config->get('config_mail_parameter'); + $mail->smtp_hostname = $this->config->get('config_mail_smtp_hostname'); + $mail->smtp_username = $this->config->get('config_mail_smtp_username'); + $mail->smtp_password = html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8'); + $mail->smtp_port = $this->config->get('config_mail_smtp_port'); + $mail->smtp_timeout = $this->config->get('config_mail_smtp_timeout'); + + $mail->setTo($customer_info['email']); + $mail->setFrom($from); + $mail->setSender(html_entity_decode($store_name, ENT_QUOTES, 'UTF-8')); + $mail->setSubject(html_entity_decode(sprintf($this->language->get('mail_text_subject'), $store_name), ENT_QUOTES, 'UTF-8')); + $mail->setText($this->load->view('mail/subscription_history', $data)); + $mail->send(); + } + } + } + } + } + } + } + } + } + + // admin/controller/sale/subscription/addTransaction/after + + /** + * @param string $route + * @param array $args + * @param mixed $output + * + * @return void + * @throws \Exception + */ + public function transaction(string &$route, array &$args, mixed &$output): void { + if (isset($args[0])) { + $subscription_id = $args[0]; + } else { + $subscription_id = 0; + } + + if (isset($args[1])) { + $order_id = $args[1]; + } else { + $order_id = 0; + } + + if (isset($args[2])) { + $comment = $args[2]; + } else { + $comment = ''; + } + + if (isset($args[3])) { + $amount = $args[3]; + } else { + $amount = ''; + } + + if (isset($args[4])) { + $type = $args[4]; + } else { + $type = ''; + } + + if (isset($args[5])) { + $payment_method = $args[5]; + } else { + $payment_method = ''; + } + + if (isset($args[6])) { + $payment_code = $args[6]; + } else { + $payment_code = ''; + } + + // Subscription + $this->load->model('sale/subscription'); + + $filter_data = [ + 'filter_subscription_id' => $subscription_id, + 'filter_subscription_status_id' => $this->config->get('config_subscription_canceled_status_id'), + 'filter_date_next' => date('Y-m-d H:i:s') + ]; + + $subscriptions = $this->model_checkout_subscription->getSubscriptions($filter_data); + + if ($subscriptions) { + foreach ($subscriptions as $subscription) { + $transaction_total = $this->model_sale_subscription->getTotalTransactions($subscription_id); + + if ($transaction_total) { + // Orders + $this->load->model('sale/order'); + + $order_info = $this->model_sale_order->getOrder($order_id); + + // In this case, since we're canceling a subscription, + // the order ID needs to be identical + if ($order_info && $subscription['order_id'] == $order_info['order_id']) { + // Same for the payment method + if ($order_info['payment_method'] == $subscription['payment_method'] && $subscription['payment_method'] == $payment_method) { + // Same for the payment code + if ($order_info['payment_code'] == $subscription['payment_code'] && $subscription['payment_code'] == $payment_code) { + $this->load->language('mail/subscription'); + + // Store + $from = $this->config->get('config_email'); + $store_name = $this->config->get('config_name'); + $store_url = HTTP_CATALOG; + $alert_email = $this->config->get('config_mail_alert_email'); + + if ($comment) { + $data['comment'] = nl2br($comment); + } else { + $data['comment'] = ''; + } + + $data['subscription_id'] = $subscription_id; + $data['payment_method'] = $payment_method; + $data['payment_code'] = $payment_code; + + $data['date_added'] = date($this->language->get('date_format_short'), $subscription['date_added']); + + if ($this->config->get('config_mail_engine')) { + $mail = new \Opencart\System\Library\Mail($this->config->get('config_mail_engine')); + $mail->parameter = $this->config->get('config_mail_parameter'); + $mail->smtp_hostname = $this->config->get('config_mail_smtp_hostname'); + $mail->smtp_username = $this->config->get('config_mail_smtp_username'); + $mail->smtp_password = html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8'); + $mail->smtp_port = $this->config->get('config_mail_smtp_port'); + $mail->smtp_timeout = $this->config->get('config_mail_smtp_timeout'); + + $mail->setTo($from); + $mail->setFrom($from); + $mail->setSender(html_entity_decode($store_name, ENT_QUOTES, 'UTF-8')); + $mail->setSubject(html_entity_decode(sprintf($this->language->get('text_subject'), $store_name), ENT_QUOTES, 'UTF-8')); + $mail->setText($this->load->view('mail/subscription_canceled', $data)); + $mail->send(); + } + } + } + } + } + } + } + } +} diff --git a/admininistrator/controller/mail/transaction.php b/admininistrator/controller/mail/transaction.php new file mode 100644 index 0000000..9a4ec55 --- /dev/null +++ b/admininistrator/controller/mail/transaction.php @@ -0,0 +1,102 @@ +load->model('customer/customer'); + + $customer_info = $this->model_customer_customer->getCustomer($customer_id); + + if ($customer_info) { + $this->load->language('mail/transaction'); + + $this->load->model('setting/store'); + + $store_info = $this->model_setting_store->getStore($customer_info['store_id']); + + if ($store_info) { + $store_name = html_entity_decode($store_info['name'], ENT_QUOTES, 'UTF-8'); + $store_url = $store_info['store_url']; + } else { + $store_name = html_entity_decode($this->config->get('config_name'), ENT_QUOTES, 'UTF-8'); + $store_url = $this->config->get('config_url'); + } + + $this->load->model('localisation/language'); + + $language_info = $this->model_localisation_language->getLanguage($customer_info['language_id']); + + if ($language_info) { + $language_code = $language_info['code']; + } else { + $language_code = $this->config->get('config_language'); + } + + $this->load->language('default', 'mail', $language_code); + $this->load->language('mail/transaction', 'mail', $language_code); + + $subject = sprintf($this->language->get('mail_text_subject'), $store_name); + + $data['text_received'] = sprintf($this->language->get('mail_text_received'), $this->currency->format($amount, $this->config->get('config_currency'))); + $data['text_total'] = sprintf($this->language->get('mail_text_total'), $this->currency->format($this->model_customer_customer->getTransactionTotal($customer_id), $this->config->get('config_currency'))); + + $data['store'] = $store_name; + $data['store_url'] = $store_url; + + if ($this->config->get('config_mail_engine')) { + $mail_option = [ + 'parameter' => $this->config->get('config_mail_parameter'), + 'smtp_hostname' => $this->config->get('config_mail_smtp_hostname'), + 'smtp_username' => $this->config->get('config_mail_smtp_username'), + 'smtp_password' => html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8'), + 'smtp_port' => $this->config->get('config_mail_smtp_port'), + 'smtp_timeout' => $this->config->get('config_mail_smtp_timeout') + ]; + + $mail = new \Opencart\System\Library\Mail($this->config->get('config_mail_engine'), $mail_option); + $mail->setTo($customer_info['email']); + $mail->setFrom($this->config->get('config_email')); + $mail->setSender($store_name); + $mail->setSubject($subject); + $mail->setHtml($this->load->view('mail/transaction', $data)); + $mail->send(); + } + } + } +} diff --git a/admininistrator/controller/mail/voucher.php b/admininistrator/controller/mail/voucher.php new file mode 100644 index 0000000..dd4426f --- /dev/null +++ b/admininistrator/controller/mail/voucher.php @@ -0,0 +1,130 @@ +load->model('sale/order'); + + $voucher_info = $this->model_sale_voucher->getVoucher($voucher_id); + + if ($voucher_info) { + // If voucher does not belong to an order + $this->load->language('mail/voucher'); + + if ($voucher_info['order_id']) { + $order_id = $voucher_info['order_id']; + } else { + $order_id = 0; + } + + $order_info = $this->model_sale_order->getOrder($order_id); + + // If voucher belongs to an order + if ($order_info) { + $this->load->model('localisation/language'); + + $language_info = $this->model_localisation_language->getLanguage($order_info['language_id']); + + if ($language_info) { + $language_code = $language_info['code']; + } else { + $language_code = $this->config->get('config_language'); + } + + $this->load->language('default', 'mail', $language_code); + $this->load->language('mail/voucher', 'mail', $language_code); + + $store_name = html_entity_decode($order_info['store_name'], ENT_QUOTES, 'UTF-8'); + + // Add language vars to the template folder + $results = $this->language->all('mail'); + + foreach ($results as $key => $value) { + $data[$key] = $value; + } + + $from_name = html_entity_decode($voucher_info['from_name'], ENT_QUOTES, 'UTF-8'); + + $subject = sprintf($this->language->get('mail_text_subject'), $from_name); + + // HTML Mail + $data['title'] = sprintf($this->language->get('mail_text_subject'), $from_name); + + $data['text_greeting'] = sprintf($this->language->get('mail_text_greeting'), $this->currency->format($voucher_info['amount'], (!empty($order_info['currency_code']) ? $order_info['currency_code'] : $this->config->get('config_currency')), (!empty($order_info['currency_value']) ? $order_info['currency_value'] : $this->currency->getValue($this->config->get('config_currency'))))); + $data['text_from'] = sprintf($this->language->get('mail_text_from'), $from_name); + $data['text_redeem'] = sprintf($this->language->get('mail_text_redeem'), $voucher_info['code']); + + $this->load->model('sale/voucher_theme'); + + $voucher_theme_info = $this->model_sale_voucher_theme->getVoucherTheme($voucher_info['voucher_theme_id']); + + if ($voucher_theme_info && is_file(DIR_IMAGE . $voucher_theme_info['image'])) { + $data['image'] = HTTP_CATALOG . 'image/' . $voucher_theme_info['image']; + } else { + $data['image'] = ''; + } + + $data['message'] = nl2br($voucher_info['message']); + + $data['store_name'] = $store_name; + $data['store_url'] = $order_info['store_url']; + } else { + $store_name = html_entity_decode($this->config->get('config_name'), ENT_QUOTES, 'UTF-8'); + + $from_name = html_entity_decode($voucher_info['from_name'], ENT_QUOTES, 'UTF-8'); + + $subject = html_entity_decode(sprintf($this->language->get('text_subject'), $from_name), ENT_QUOTES, 'UTF-8'); + + $data['title'] = sprintf($this->language->get('text_subject'), $from_name); + + $data['text_greeting'] = sprintf($this->language->get('text_greeting'), $this->currency->format($voucher_info['amount'], $this->config->get('config_currency'))); + $data['text_from'] = sprintf($this->language->get('text_from'), $from_name); + $data['text_redeem'] = sprintf($this->language->get('text_redeem'), $voucher_info['code']); + + $this->load->model('sale/voucher_theme'); + + $voucher_theme_info = $this->model_sale_voucher_theme->getVoucherTheme($voucher_info['voucher_theme_id']); + + if ($voucher_theme_info && is_file(DIR_IMAGE . $voucher_theme_info['image'])) { + $data['image'] = HTTP_CATALOG . 'image/' . $voucher_theme_info['image']; + } else { + $data['image'] = ''; + } + + $data['message'] = nl2br($voucher_info['message']); + + $data['store_name'] = $store_name; + $data['store_url'] = HTTP_CATALOG; + } + + if ($this->config->get('config_mail_engine')) { + $mail_option = [ + 'parameter' => $this->config->get('config_mail_parameter'), + 'smtp_hostname' => $this->config->get('config_mail_smtp_hostname'), + 'smtp_username' => $this->config->get('config_mail_smtp_username'), + 'smtp_password' => html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8'), + 'smtp_port' => $this->config->get('config_mail_smtp_port'), + 'smtp_timeout' => $this->config->get('config_mail_smtp_timeout') + ]; + + $mail = new \Opencart\System\Library\Mail($this->config->get('config_mail_engine'), $mail_option); + $mail->setTo($voucher_info['to_email']); + $mail->setFrom($this->config->get('config_email')); + $mail->setSender($store_name); + $mail->setSubject($subject); + $mail->setHtml($this->load->view('mail/voucher', $data)); + $mail->send(); + } + } + } +} diff --git a/admininistrator/controller/marketing/affiliate.php b/admininistrator/controller/marketing/affiliate.php new file mode 100644 index 0000000..6b3f3a8 --- /dev/null +++ b/admininistrator/controller/marketing/affiliate.php @@ -0,0 +1,1059 @@ +load->language('marketing/affiliate'); + + $this->document->setTitle($this->language->get('heading_title')); + + if (isset($this->request->get['filter_customer'])) { + $filter_customer = $this->request->get['filter_customer']; + } else { + $filter_customer = ''; + } + + if (isset($this->request->get['filter_tracking'])) { + $filter_tracking = $this->request->get['filter_tracking']; + } else { + $filter_tracking = ''; + } + + if (isset($this->request->get['filter_payment_method'])) { + $filter_payment_method = (string)$this->request->get['filter_payment_method']; + } else { + $filter_payment_method = ''; + } + + if (isset($this->request->get['filter_commission'])) { + $filter_commission = $this->request->get['filter_commission']; + } else { + $filter_commission = ''; + } + + if (isset($this->request->get['filter_date_from'])) { + $filter_date_from = $this->request->get['filter_date_from']; + } else { + $filter_date_from = ''; + } + + if (isset($this->request->get['filter_date_to'])) { + $filter_date_to = $this->request->get['filter_date_to']; + } else { + $filter_date_to = ''; + } + + if (isset($this->request->get['filter_status'])) { + $filter_status = $this->request->get['filter_status']; + } else { + $filter_status = ''; + } + + if (isset($this->request->get['limit'])) { + $limit = (int)$this->request->get['limit']; + } else { + $limit = $this->config->get('config_pagination'); + } + + $url = ''; + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_tracking'])) { + $url .= '&filter_tracking=' . $this->request->get['filter_tracking']; + } + + if (isset($this->request->get['filter_payment_method'])) { + $url .= '&filter_payment_method=' . $this->request->get['filter_payment_method']; + } + + if (isset($this->request->get['filter_commission'])) { + $url .= '&filter_commission=' . $this->request->get['filter_commission']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + if (isset($this->request->get['limit'])) { + $url .= '&limit=' . $this->request->get['limit']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('marketing/affiliate', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['csv'] = $this->url->link('marketing/affiliate.csv', 'user_token=' . $this->session->data['user_token']); + $data['complete'] = $this->url->link('marketing/affiliate.complete', 'user_token=' . $this->session->data['user_token']); + $data['add'] = $this->url->link('marketing/affiliate.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('marketing/affiliate.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['payment_methods'] = []; + + $data['payment_methods'][] = [ + 'text' => $this->language->get('text_cheque'), + 'value' => 'cheque' + ]; + + $data['payment_methods'][] = [ + 'text' => $this->language->get('text_paypal'), + 'value' => 'paypal' + ]; + + $data['payment_methods'][] = [ + 'text' => $this->language->get('text_bank'), + 'value' => 'bank' + ]; + + $data['limits'] = []; + + $data['limits'][] = [ + 'text' => $this->config->get('config_pagination'), + 'value' => $this->config->get('config_pagination') + ]; + + $data['limits'][] = [ + 'text' => 100, + 'value' => 100 + ]; + + $data['limits'][] = [ + 'text' => 200, + 'value' => 200 + ]; + + $data['limits'][] = [ + 'text' => 400, + 'value' => 400 + ]; + + $data['limits'][] = [ + 'text' => 800, + 'value' => 800 + ]; + + $data['user_token'] = $this->session->data['user_token']; + + $data['filter_customer'] = $filter_customer; + $data['filter_tracking'] = $filter_tracking; + $data['filter_payment_method'] = $filter_payment_method; + $data['filter_commission'] = $filter_commission; + $data['filter_date_from'] = $filter_date_from; + $data['filter_date_to'] = $filter_date_to; + $data['filter_status'] = $filter_status; + + $data['limit'] = $limit; + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('marketing/affiliate', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('marketing/affiliate'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['filter_customer'])) { + $filter_customer = (string)$this->request->get['filter_customer']; + } else { + $filter_customer = ''; + } + + if (isset($this->request->get['filter_tracking'])) { + $filter_tracking = (string)$this->request->get['filter_tracking']; + } else { + $filter_tracking = ''; + } + + if (isset($this->request->get['filter_payment_method'])) { + $filter_payment_method = (string)$this->request->get['filter_payment_method']; + } else { + $filter_payment_method = ''; + } + + if (isset($this->request->get['filter_commission'])) { + $filter_commission = $this->request->get['filter_commission']; + } else { + $filter_commission = ''; + } + + if (isset($this->request->get['filter_date_from'])) { + $filter_date_from = (string)$this->request->get['filter_date_from']; + } else { + $filter_date_from = ''; + } + + if (isset($this->request->get['filter_date_to'])) { + $filter_date_to = (string)$this->request->get['filter_date_to']; + } else { + $filter_date_to = ''; + } + + if (isset($this->request->get['filter_status'])) { + $filter_status = $this->request->get['filter_status']; + } else { + $filter_status = ''; + } + + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + if (isset($this->request->get['limit'])) { + $limit = (int)$this->request->get['limit']; + } else { + $limit = $this->config->get('config_pagination'); + } + + $url = ''; + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_tracking'])) { + $url .= '&filter_tracking=' . $this->request->get['filter_tracking']; + } + + if (isset($this->request->get['filter_payment_method'])) { + $url .= '&filter_payment_method=' . $this->request->get['filter_payment_method']; + } + + if (isset($this->request->get['filter_commission'])) { + $url .= '&filter_commission=' . $this->request->get['filter_commission']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + if (isset($this->request->get['limit'])) { + $url .= '&limit=' . $this->request->get['limit']; + } + + $data['action'] = $this->url->link('marketing/affiliate.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['affiliates'] = []; + + $filter_data = [ + 'filter_name' => $filter_customer, + 'filter_tracking' => $filter_tracking, + 'filter_payment_method' => $filter_payment_method, + 'filter_commission' => $filter_commission, + 'filter_date_from' => $filter_date_from, + 'filter_date_to' => $filter_date_to, + 'filter_status' => $filter_status, + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $limit, + 'limit' => $limit + ]; + + $this->load->model('marketing/affiliate'); + $this->load->model('customer/customer'); + + $affiliate_total = $this->model_marketing_affiliate->getTotalAffiliates($filter_data); + + $results = $this->model_marketing_affiliate->getAffiliates($filter_data); + + foreach ($results as $result) { + $data['affiliates'][] = [ + 'customer_id' => $result['customer_id'], + 'name' => $result['name'], + 'tracking' => $result['tracking'], + 'commission' => $result['commission'], + 'balance' => $this->currency->format($result['balance'], $this->config->get('config_currency')), + 'status' => $result['status'], + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])), + 'customer' => $this->url->link('customer/customer.form', 'user_token=' . $this->session->data['user_token'] . '&customer_id=' . $result['customer_id']), + 'edit' => $this->url->link('marketing/affiliate.form', 'user_token=' . $this->session->data['user_token'] . '&customer_id=' . $result['customer_id'] . $url) + ]; + } + + $url = ''; + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_tracking'])) { + $url .= '&filter_tracking=' . $this->request->get['filter_tracking']; + } + + if (isset($this->request->get['filter_payment_method'])) { + $url .= '&filter_payment_method=' . $this->request->get['filter_payment_method']; + } + + if (isset($this->request->get['filter_commission'])) { + $url .= '&filter_commission=' . $this->request->get['filter_commission']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + if (isset($this->request->get['limit'])) { + $url .= '&limit=' . $this->request->get['limit']; + } + + $data['sort_name'] = $this->url->link('marketing/affiliate.list', 'user_token=' . $this->session->data['user_token'] . '&sort=name' . $url); + $data['sort_tracking'] = $this->url->link('marketing/affiliate.list', 'user_token=' . $this->session->data['user_token'] . '&sort=ca.tracking' . $url); + $data['sort_commission'] = $this->url->link('marketing/affiliate.list', 'user_token=' . $this->session->data['user_token'] . '&sort=ca.commission' . $url); + $data['sort_date_added'] = $this->url->link('marketing/affiliate.list', 'user_token=' . $this->session->data['user_token'] . '&sort=ca.date_added' . $url); + + $url = ''; + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_tracking'])) { + $url .= '&filter_tracking=' . $this->request->get['filter_tracking']; + } + + if (isset($this->request->get['filter_payment_method'])) { + $url .= '&filter_payment_method=' . $this->request->get['filter_payment_method']; + } + + if (isset($this->request->get['filter_commission'])) { + $url .= '&filter_commission=' . $this->request->get['filter_commission']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['limit'])) { + $url .= '&limit=' . $this->request->get['limit']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $affiliate_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('marketing/affiliate.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($affiliate_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($affiliate_total - $limit)) ? $affiliate_total : ((($page - 1) * $limit) + $limit), $affiliate_total, ceil($affiliate_total / $limit)); + + $data['sort'] = $sort; + $data['order'] = $order; + $data['limit'] = $limit; + + return $this->load->view('marketing/affiliate_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('marketing/affiliate'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['customer_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $data['error_upload_size'] = sprintf($this->language->get('error_upload_size'), $this->config->get('config_file_max_size')); + + $data['config_file_max_size'] = ((int)$this->config->get('config_file_max_size') * 1024 * 1024); + + $url = ''; + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_tracking'])) { + $url .= '&filter_tracking=' . $this->request->get['filter_tracking']; + } + + if (isset($this->request->get['filter_payment_method'])) { + $url .= '&filter_payment_method=' . $this->request->get['filter_payment_method']; + } + + if (isset($this->request->get['filter_commission'])) { + $url .= '&filter_commission=' . $this->request->get['filter_commission']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + if (isset($this->request->get['limit'])) { + $url .= '&limit=' . $this->request->get['limit']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('marketing/affiliate', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('marketing/affiliate.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('marketing/affiliate', 'user_token=' . $this->session->data['user_token'] . $url); + $data['upload'] = $this->url->link('tool/upload.upload', 'user_token=' . $this->session->data['user_token']); + + // Affiliate + if (isset($this->request->get['customer_id'])) { + $this->load->model('marketing/affiliate'); + + $affiliate_info = $this->model_marketing_affiliate->getAffiliate($this->request->get['customer_id']); + } + + if (isset($this->request->get['customer_id'])) { + $data['customer_id'] = (int)$this->request->get['customer_id']; + } else { + $data['customer_id'] = 0; + } + + if (!empty($affiliate_info)) { + $data['customer'] = $affiliate_info['customer']; + } else { + $data['customer'] = ''; + } + + if (!empty($affiliate_info)) { + $data['customer_group_id'] = $affiliate_info['customer_group_id']; + } else { + $data['customer_group_id'] = ''; + } + + if (!empty($affiliate_info)) { + $data['company'] = $affiliate_info['company']; + } else { + $data['company'] = ''; + } + + if (!empty($affiliate_info)) { + $data['website'] = $affiliate_info['website']; + } else { + $data['website'] = ''; + } + + if (!empty($affiliate_info)) { + $data['tracking'] = $affiliate_info['tracking']; + } else { + $data['tracking'] = oc_token(10); + } + + if (!empty($affiliate_info)) { + $data['commission'] = $affiliate_info['commission']; + } else { + $data['commission'] = $this->config->get('config_affiliate_commission'); + } + + if (!empty($affiliate_info)) { + $data['status'] = $affiliate_info['status']; + } else { + $data['status'] = ''; + } + + if (!empty($affiliate_info)) { + $data['tax'] = $affiliate_info['tax']; + } else { + $data['tax'] = ''; + } + + if (!empty($affiliate_info)) { + $data['payment_method'] = $affiliate_info['payment_method']; + } else { + $data['payment_method'] = 'cheque'; + } + + if (!empty($affiliate_info)) { + $data['cheque'] = $affiliate_info['cheque']; + } else { + $data['cheque'] = ''; + } + + if (!empty($affiliate_info)) { + $data['paypal'] = $affiliate_info['paypal']; + } else { + $data['paypal'] = ''; + } + + if (!empty($affiliate_info)) { + $data['bank_name'] = $affiliate_info['bank_name']; + } else { + $data['bank_name'] = ''; + } + + if (!empty($affiliate_info)) { + $data['bank_branch_number'] = $affiliate_info['bank_branch_number']; + } else { + $data['bank_branch_number'] = ''; + } + + if (!empty($affiliate_info)) { + $data['bank_swift_code'] = $affiliate_info['bank_swift_code']; + } else { + $data['bank_swift_code'] = ''; + } + + if (!empty($affiliate_info)) { + $data['bank_account_name'] = $affiliate_info['bank_account_name']; + } else { + $data['bank_account_name'] = ''; + } + + if (!empty($affiliate_info)) { + $data['bank_account_number'] = $affiliate_info['bank_account_number']; + } else { + $data['bank_account_number'] = ''; + } + + $data['custom_fields'] = []; + + $filter_data = [ + 'sort' => 'cf.sort_order', + 'order' => 'ASC' + ]; + + // Custom Fields + $this->load->model('customer/custom_field'); + + $custom_fields = $this->model_customer_custom_field->getCustomFields($filter_data); + + foreach ($custom_fields as $custom_field) { + if ($custom_field['status']) { + $data['custom_fields'][] = [ + 'custom_field_id' => $custom_field['custom_field_id'], + 'custom_field_value' => $this->model_customer_custom_field->getValues($custom_field['custom_field_id']), + 'name' => $custom_field['name'], + 'value' => $custom_field['value'], + 'type' => $custom_field['type'], + 'location' => $custom_field['location'], + 'sort_order' => $custom_field['sort_order'] + ]; + } + } + + if (!empty($affiliate_info)) { + $data['affiliate_custom_field'] = json_decode($affiliate_info['custom_field'], true); + } else { + $data['affiliate_custom_field'] = []; + } + + $data['history'] = $this->load->controller('customer/customer.getHistory'); + $data['transaction'] = $this->load->controller('customer/customer.getTransaction'); + $data['report'] = $this->getReport(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('marketing/affiliate_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('marketing/affiliate'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'marketing/affiliate')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + $this->load->model('customer/customer'); + + $customer_info = $this->model_customer_customer->getCustomer((int)$this->request->post['customer_id']); + + if (!$customer_info) { + $json['error']['customer'] = $this->language->get('error_customer'); + } + + // Check to see if customer is already a affiliate + $this->load->model('marketing/affiliate'); + + $affiliate_info = $this->model_marketing_affiliate->getAffiliate((int)$this->request->post['customer_id']); + + if ($affiliate_info && (!isset($this->request->post['customer_id']) || ($this->request->post['customer_id'] != $affiliate_info['customer_id']))) { + $json['error']['warning'] = $this->language->get('error_already'); + } + + if (!$this->request->post['tracking']) { + $json['error']['tracking'] = $this->language->get('error_tracking'); + } + + $affiliate_info = $this->model_marketing_affiliate->getAffiliateByTracking($this->request->post['tracking']); + + if ($affiliate_info && (!isset($this->request->post['customer_id']) || ($this->request->post['customer_id'] != $affiliate_info['customer_id']))) { + $json['error']['tracking'] = $this->language->get('error_exists'); + } + + // Payment validation + if (empty($this->request->post['payment_method'])) { + $json['error']['payment_method'] = $this->language->get('error_payment_method'); + } + + if ($this->request->post['payment_method'] == 'cheque' && $this->request->post['cheque'] == '') { + $json['error']['cheque'] = $this->language->get('error_cheque'); + } elseif ($this->request->post['payment_method'] == 'paypal' && ((oc_strlen($this->request->post['paypal']) > 96) || !filter_var($this->request->post['paypal'], FILTER_VALIDATE_EMAIL))) { + $json['error']['paypal'] = $this->language->get('error_paypal'); + } elseif ($this->request->post['payment_method'] == 'bank') { + if ($this->request->post['bank_account_name'] == '') { + $json['error']['bank_account_name'] = $this->language->get('error_bank_account_name'); + } + + if ($this->request->post['bank_account_number'] == '') { + $json['error']['bank_account_number'] = $this->language->get('error_bank_account_number'); + } + } + + // Custom field validation + if ($customer_info) { + $this->load->model('customer/custom_field'); + + $custom_fields = $this->model_customer_custom_field->getCustomFields(['filter_customer_group_id' => $customer_info['customer_group_id']]); + + foreach ($custom_fields as $custom_field) { + if ($custom_field['status']) { + if (($custom_field['location'] == 'affiliate') && $custom_field['required'] && empty($this->request->post['custom_field'][$custom_field['custom_field_id']])) { + $json['error']['custom_field_' . $custom_field['custom_field_id']] = sprintf($this->language->get('error_custom_field'), $custom_field['name']); + } elseif (($custom_field['location'] == 'affiliate') && ($custom_field['type'] == 'text') && !empty($custom_field['validation']) && !preg_match(html_entity_decode($custom_field['validation'], ENT_QUOTES, 'UTF-8'), $this->request->post['custom_field'][$custom_field['custom_field_id']])) { + $json['error']['custom_field_' . $custom_field['custom_field_id']] = sprintf($this->language->get('error_regex'), $custom_field['name']); + } + } + } + } + + if (isset($json['error']) && !isset($json['error']['warning'])) { + $json['error']['warning'] = $this->language->get('error_warning'); + } + + if (!$json) { + // Use affiliate + if (!$affiliate_info) { + $this->model_marketing_affiliate->addAffiliate($this->request->post); + } else { + $this->model_marketing_affiliate->editAffiliate($this->request->post['customer_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('marketing/affiliate'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'marketing/affiliate')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('marketing/affiliate'); + + foreach ($selected as $affiliate_id) { + $this->model_marketing_affiliate->deleteAffiliate($affiliate_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function calculate() { + $this->load->language('marketing/affiliate'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'marketing/affiliate')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('marketing/affiliate'); + $this->load->model('customer/customer'); + + $results = $this->model_marketing_affiliate->getAffiliates(['filter_status' => 1]); + + foreach ($results as $result) { + $this->model_marketing_affiliate->editBalance($result['customer_id'], $this->model_customer_customer->getTransactionTotal($result['customer_id'])); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return \Opencart\System\Engine\Action|void + */ + public function csv() { + $this->load->language('marketing/affiliate'); + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if ($this->user->hasPermission('modify', 'marketing/affiliate')) { + $this->load->model('marketing/affiliate'); + + $csv = ''; + + foreach ($selected as $customer_id) { + $affiliate_info = $this->model_marketing_affiliate->getAffiliate($customer_id); + + if ($affiliate_info && $affiliate_info['status'] && (float)$affiliate_info['balance'] > 0) { + $balance = $this->currency->format($affiliate_info['balance'], $this->config->get('config_currency'), 1.00000000, false); + + if ($affiliate_info['payment_method'] == 'cheque') { + $csv .= $affiliate_info['cheque'] . ',' . $balance . ',' . $this->config->get('config_currency') . ',' . $affiliate_info['customer'] . "\n"; + } + + if ($affiliate_info['payment_method'] == 'paypal') { + $csv .= $affiliate_info['paypal'] . ',' . $balance . ',' . $this->config->get('config_currency') . ',' . $affiliate_info['customer'] . ',Thanks for your business!' . "\n"; + } + + if ($affiliate_info['payment_method'] == 'bank') { + $csv .= $affiliate_info['bank_name'] . ',' . $affiliate_info['bank_branch_number'] . ',' . $affiliate_info['bank_swift_code'] . ',' . $affiliate_info['bank_account_name'] . ',' . $affiliate_info['bank_account_number'] . ',' . $balance . ',' . $this->config->get('config_currency') . ',' . $affiliate_info['customer'] . "\n"; + } + } + } + + if (!headers_sent()) { + header('Pragma: public'); + header('Expires: 0'); + header('Content-Description: File Transfer'); + header('Content-Type: application/octet-stream'); + header('Content-Transfer-Encoding: binary'); + header('Content-Disposition: attachment; filename=payout-' . date('d-m-Y') . '.csv"'); + header('Content-Length: ' . strlen($csv)); + + print($csv); + } else { + exit('Error: Headers already sent out!'); + } + } else { + return new \Opencart\System\Engine\Action('error/permission'); + } + } + + /** + * @return void + */ + public function complete() { + $this->load->language('marketing/affiliate'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'marketing/affiliate')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('marketing/affiliate'); + $this->load->model('customer/customer'); + + foreach ($selected as $customer_id) { + $affiliate_info = $this->model_marketing_affiliate->getAffiliate($customer_id); + + if ($affiliate_info && $affiliate_info['status'] && (float)$affiliate_info['balance'] > 0) { + $this->model_customer_customer->addTransaction($affiliate_info['customer_id'], $this->language->get('text_payment_' . $affiliate_info['payment_method']), -$affiliate_info['balance']); + + $this->model_marketing_affiliate->editBalance($affiliate_info['customer_id'], 0); + } + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function report(): void { + $this->load->language('marketing/affiliate'); + + $this->response->setOutput($this->getReport()); + } + + /** + * @return string + */ + private function getReport(): string { + if (isset($this->request->get['customer_id'])) { + $customer_id = (int)$this->request->get['customer_id']; + } else { + $customer_id = 0; + } + + if (isset($this->request->get['page']) && $this->request->get['route'] == 'marketing/affiliate.report') { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $limit = 10; + + $data['reports'] = []; + + $this->load->model('marketing/affiliate'); + $this->load->model('customer/customer'); + $this->load->model('setting/store'); + + $results = $this->model_marketing_affiliate->getReports($customer_id, ($page - 1) * $limit, $limit); + + foreach ($results as $result) { + $store_info = $this->model_setting_store->getStore($result['store_id']); + + if ($store_info) { + $store = $store_info['name']; + } elseif (!$result['store_id']) { + $store = $this->config->get('config_name'); + } else { + $store = ''; + } + + $data['reports'][] = [ + 'ip' => $result['ip'], + 'account' => $this->model_customer_customer->getTotalCustomersByIp($result['ip']), + 'store' => $store, + 'country' => $result['country'], + 'date_added' => date($this->language->get('datetime_format'), strtotime($result['date_added'])), + 'filter_ip' => $this->url->link('customer/customer', 'user_token=' . $this->session->data['user_token'] . '&filter_ip=' . $result['ip']) + ]; + } + + $report_total = $this->model_marketing_affiliate->getTotalReports($customer_id); + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $report_total, + 'page' => $page, + 'limit' => $limit, + 'url' => $this->url->link('marketing/affiliate.report', 'user_token=' . $this->session->data['user_token'] . '&customer_id=' . $customer_id . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($report_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($report_total - $limit)) ? $report_total : ((($page - 1) * $limit) + $limit), $report_total, ceil($report_total / $limit)); + + return $this->load->view('marketing/affiliate_report', $data); + } + + /** + * @return void + */ + public function autocomplete(): void { + $json = []; + + if (isset($this->request->get['filter_name'])) { + $filter_name = $this->request->get['filter_name']; + } else { + $filter_name = ''; + } + + if (isset($this->request->get['filter_email'])) { + $filter_email = $this->request->get['filter_email']; + } else { + $filter_email = ''; + } + + $filter_data = [ + 'filter_name' => $filter_name, + 'filter_email' => $filter_email, + 'start' => 0, + 'limit' => 5 + ]; + + $this->load->model('marketing/affiliate'); + + $results = $this->model_marketing_affiliate->getAffiliates($filter_data); + + foreach ($results as $result) { + $json[] = [ + 'customer_id' => $result['customer_id'], + 'name' => strip_tags(html_entity_decode($result['name'], ENT_QUOTES, 'UTF-8')), + 'email' => $result['email'] + ]; + } + + $sort_order = []; + + foreach ($json as $key => $value) { + $sort_order[$key] = $value['name']; + } + + array_multisort($sort_order, SORT_ASC, $json); + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/marketing/contact.php b/admininistrator/controller/marketing/contact.php new file mode 100644 index 0000000..ea04ccc --- /dev/null +++ b/admininistrator/controller/marketing/contact.php @@ -0,0 +1,256 @@ +load->language('marketing/contact'); + + $this->document->setTitle($this->language->get('heading_title')); + + $this->document->addScript('view/javascript/ckeditor/ckeditor.js'); + $this->document->addScript('view/javascript/ckeditor/adapters/jquery.js'); + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('marketing/contact', 'user_token=' . $this->session->data['user_token']) + ]; + + $this->load->model('setting/store'); + + $data['stores'] = $this->model_setting_store->getStores(); + + $this->load->model('customer/customer_group'); + + $data['customer_groups'] = $this->model_customer_customer_group->getCustomerGroups(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('marketing/contact', $data)); + } + + /** + * @return void + * @throws \Exception + */ + public function send(): void { + $this->load->language('marketing/contact'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'marketing/contact')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if (!$this->request->post['subject']) { + $json['error']['subject'] = $this->language->get('error_subject'); + } + + if (!$this->request->post['message']) { + $json['error']['message'] = $this->language->get('error_message'); + } + + if (!$json) { + $this->load->model('setting/store'); + $this->load->model('setting/setting'); + $this->load->model('customer/customer'); + $this->load->model('sale/order'); + + $store_info = $this->model_setting_store->getStore($this->request->post['store_id']); + + if ($store_info) { + $store_name = $store_info['name']; + } else { + $store_name = $this->config->get('config_name'); + } + + $setting = $this->model_setting_setting->getSetting('config', $this->request->post['store_id']); + + $store_email = isset($setting['config_email']) ? $setting['config_email'] : $this->config->get('config_email'); + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $limit = 10; + + $email_total = 0; + + $emails = []; + + switch ($this->request->post['to']) { + case 'newsletter': + $customer_data = [ + 'filter_newsletter' => 1, + 'start' => ($page - 1) * $limit, + 'limit' => $limit + ]; + + $email_total = $this->model_customer_customer->getTotalCustomers($customer_data); + + $results = $this->model_customer_customer->getCustomers($customer_data); + + foreach ($results as $result) { + $emails[] = $result['email']; + } + break; + case 'customer_all': + $customer_data = [ + 'start' => ($page - 1) * $limit, + 'limit' => $limit + ]; + + $email_total = $this->model_customer_customer->getTotalCustomers($customer_data); + + $results = $this->model_customer_customer->getCustomers($customer_data); + + foreach ($results as $result) { + $emails[] = $result['email']; + } + break; + case 'customer_group': + $customer_data = [ + 'filter_customer_group_id' => $this->request->post['customer_group_id'], + 'start' => ($page - 1) * $limit, + 'limit' => $limit + ]; + + $email_total = $this->model_customer_customer->getTotalCustomers($customer_data); + + $results = $this->model_customer_customer->getCustomers($customer_data); + + foreach ($results as $result) { + $emails[$result['customer_id']] = $result['email']; + } + break; + case 'customer': + if (!empty($this->request->post['customer'])) { + $email_total = count($this->request->post['customer']); + + $customers = array_slice($this->request->post['customer'], ($page - 1) * $limit, $limit); + + foreach ($customers as $customer_id) { + $customer_info = $this->model_customer_customer->getCustomer($customer_id); + + if ($customer_info) { + $emails[] = $customer_info['email']; + } + } + } + break; + case 'affiliate_all': + $affiliate_data = [ + 'filter_affiliate' => 1, + 'start' => ($page - 1) * $limit, + 'limit' => $limit + ]; + + $email_total = $this->model_customer_customer->getTotalCustomers($affiliate_data); + + $results = $this->model_customer_customer->getCustomers($affiliate_data); + + foreach ($results as $result) { + $emails[] = $result['email']; + } + break; + case 'affiliate': + if (!empty($this->request->post['affiliate'])) { + $affiliates = array_slice($this->request->post['affiliate'], ($page - 1) * $limit, $limit); + + foreach ($affiliates as $affiliate_id) { + $affiliate_info = $this->model_customer_customer->getCustomer($affiliate_id); + + if ($affiliate_info) { + $emails[] = $affiliate_info['email']; + } + } + + $email_total = count($this->request->post['affiliate']); + } + break; + case 'product': + if (isset($this->request->post['product'])) { + $email_total = $this->model_sale_order->getTotalEmailsByProductsOrdered($this->request->post['product']); + + $results = $this->model_sale_order->getEmailsByProductsOrdered($this->request->post['product'], ($page - 1) * $limit, $limit); + + foreach ($results as $result) { + $emails[] = $result['email']; + } + } + break; + } + + if ($emails) { + $start = ($page - 1) * $limit; + $end = $start + $limit; + + if ($end < $email_total) { + $json['text'] = sprintf($this->language->get('text_sent'), $start ? $start : 1, $email_total); + + $json['next'] = $this->url->link('marketing/contact.send', 'user_token=' . $this->session->data['user_token'] . '&page=' . ($page + 1), true); + } else { + $json['success'] = $this->language->get('text_success'); + + $json['next'] = ''; + } + + $message = '' . "\n"; + $message .= ' ' . "\n"; + $message .= ' ' . $this->request->post['subject'] . '' . "\n"; + $message .= ' ' . "\n"; + $message .= ' ' . "\n"; + $message .= ' ' . html_entity_decode($this->request->post['message'], ENT_QUOTES, 'UTF-8') . '' . "\n"; + $message .= '' . "\n"; + + if ($this->config->get('config_mail_engine')) { + $mail_option = [ + 'parameter' => $this->config->get('config_mail_parameter'), + 'smtp_hostname' => $this->config->get('config_mail_smtp_hostname'), + 'smtp_username' => $this->config->get('config_mail_smtp_username'), + 'smtp_password' => html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8'), + 'smtp_port' => $this->config->get('config_mail_smtp_port'), + 'smtp_timeout' => $this->config->get('config_mail_smtp_timeout') + ]; + + $mail = new \Opencart\System\Library\Mail($this->config->get('config_mail_engine'), $mail_option); + + foreach ($emails as $email) { + if (filter_var($email, FILTER_VALIDATE_EMAIL)) { + $mail->setTo(trim($email)); + $mail->setFrom($store_email); + $mail->setSender(html_entity_decode($store_name, ENT_QUOTES, 'UTF-8')); + $mail->setSubject(html_entity_decode($this->request->post['subject'], ENT_QUOTES, 'UTF-8')); + $mail->setHtml($message); + $mail->send(); + } + } + } + } else { + $json['error']['warning'] = $this->language->get('error_email'); + } + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/marketing/coupon.php b/admininistrator/controller/marketing/coupon.php new file mode 100644 index 0000000..9a2c12d --- /dev/null +++ b/admininistrator/controller/marketing/coupon.php @@ -0,0 +1,481 @@ +load->language('marketing/coupon'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('marketing/coupon', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('marketing/coupon.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('marketing/coupon.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('marketing/coupon', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('marketing/coupon'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('marketing/coupon.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['coupons'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('marketing/coupon'); + + $coupon_total = $this->model_marketing_coupon->getTotalCoupons(); + + $results = $this->model_marketing_coupon->getCoupons($filter_data); + + foreach ($results as $result) { + $data['coupons'][] = [ + 'coupon_id' => $result['coupon_id'], + 'name' => $result['name'], + 'code' => $result['code'], + 'discount' => $result['discount'], + 'date_start' => date($this->language->get('date_format_short'), strtotime($result['date_start'])), + 'date_end' => date($this->language->get('date_format_short'), strtotime($result['date_end'])), + 'status' => $result['status'], + 'edit' => $this->url->link('marketing/coupon.form', 'user_token=' . $this->session->data['user_token'] . '&coupon_id=' . $result['coupon_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('marketing/coupon.list', 'user_token=' . $this->session->data['user_token'] . '&sort=name' . $url); + $data['sort_code'] = $this->url->link('marketing/coupon.list', 'user_token=' . $this->session->data['user_token'] . '&sort=code' . $url); + $data['sort_discount'] = $this->url->link('marketing/coupon.list', 'user_token=' . $this->session->data['user_token'] . '&sort=discount' . $url); + $data['sort_date_start'] = $this->url->link('marketing/coupon.list', 'user_token=' . $this->session->data['user_token'] . '&sort=date_start' . $url); + $data['sort_date_end'] = $this->url->link('marketing/coupon.list', 'user_token=' . $this->session->data['user_token'] . '&sort=date_end' . $url); + $data['sort_status'] = $this->url->link('marketing/coupon.list', 'user_token=' . $this->session->data['user_token'] . '&sort=status' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $coupon_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('marketing/coupon.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($coupon_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($coupon_total - $this->config->get('config_pagination_admin'))) ? $coupon_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $coupon_total, ceil($coupon_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('marketing/coupon_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('marketing/coupon'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['coupon_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('marketing/coupon', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('marketing/coupon.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('marketing/coupon', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['coupon_id'])) { + $this->load->model('marketing/coupon'); + + $coupon_info = $this->model_marketing_coupon->getCoupon($this->request->get['coupon_id']); + } + + if (isset($this->request->get['coupon_id'])) { + $data['coupon_id'] = (int)$this->request->get['coupon_id']; + } else { + $data['coupon_id'] = 0; + } + + if (!empty($coupon_info)) { + $data['name'] = $coupon_info['name']; + } else { + $data['name'] = ''; + } + + if (!empty($coupon_info)) { + $data['code'] = $coupon_info['code']; + } else { + $data['code'] = ''; + } + + if (!empty($coupon_info)) { + $data['type'] = $coupon_info['type']; + } else { + $data['type'] = ''; + } + + if (!empty($coupon_info)) { + $data['discount'] = $coupon_info['discount']; + } else { + $data['discount'] = ''; + } + + if (!empty($coupon_info)) { + $data['logged'] = $coupon_info['logged']; + } else { + $data['logged'] = ''; + } + + if (!empty($coupon_info)) { + $data['shipping'] = $coupon_info['shipping']; + } else { + $data['shipping'] = ''; + } + + if (!empty($coupon_info)) { + $data['total'] = $coupon_info['total']; + } else { + $data['total'] = ''; + } + + if (!empty($coupon_info)) { + $products = $this->model_marketing_coupon->getProducts($this->request->get['coupon_id']); + } else { + $products = []; + } + + $this->load->model('catalog/product'); + + $data['coupon_products'] = []; + + foreach ($products as $product_id) { + $product_info = $this->model_catalog_product->getProduct($product_id); + + if ($product_info) { + $data['coupon_products'][] = [ + 'product_id' => $product_info['product_id'], + 'name' => $product_info['name'] + ]; + } + } + + if (!empty($coupon_info)) { + $categories = $this->model_marketing_coupon->getCategories($this->request->get['coupon_id']); + } else { + $categories = []; + } + + $this->load->model('catalog/category'); + + $data['coupon_categories'] = []; + + foreach ($categories as $category_id) { + $category_info = $this->model_catalog_category->getCategory($category_id); + + if ($category_info) { + $data['coupon_categories'][] = [ + 'category_id' => $category_info['category_id'], + 'name' => ($category_info['path'] ? $category_info['path'] . ' > ' : '') . $category_info['name'] + ]; + } + } + + if (!empty($coupon_info)) { + $data['date_start'] = ($coupon_info['date_start'] != '0000-00-00' ? $coupon_info['date_start'] : ''); + } else { + $data['date_start'] = date('Y-m-d', time()); + } + + if (!empty($coupon_info)) { + $data['date_end'] = ($coupon_info['date_end'] != '0000-00-00' ? $coupon_info['date_end'] : ''); + } else { + $data['date_end'] = date('Y-m-d', strtotime('+1 month')); + } + + if (!empty($coupon_info)) { + $data['uses_total'] = $coupon_info['uses_total']; + } else { + $data['uses_total'] = 1; + } + + if (!empty($coupon_info)) { + $data['uses_customer'] = $coupon_info['uses_customer']; + } else { + $data['uses_customer'] = 1; + } + + if (!empty($coupon_info)) { + $data['status'] = $coupon_info['status']; + } else { + $data['status'] = true; + } + + $data['history'] = $this->getHistory(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('marketing/coupon_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('marketing/coupon'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'marketing/coupon')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if ((oc_strlen($this->request->post['name']) < 3) || (oc_strlen($this->request->post['name']) > 128)) { + $json['error']['name'] = $this->language->get('error_name'); + } + + if ((oc_strlen($this->request->post['code']) < 3) || (oc_strlen($this->request->post['code']) > 20)) { + $json['error']['code'] = $this->language->get('error_code'); + } + + $this->load->model('marketing/coupon'); + + $coupon_info = $this->model_marketing_coupon->getCouponByCode($this->request->post['code']); + + if ($coupon_info) { + if (!isset($this->request->post['coupon_id'])) { + $json['error']['warning'] = $this->language->get('error_exists'); + } elseif ($coupon_info['coupon_id'] != (int)$this->request->post['coupon_id']) { + $json['error']['warning'] = $this->language->get('error_exists'); + } + } + + if (!$json) { + if (!$this->request->post['coupon_id']) { + $json['coupon_id'] = $this->model_marketing_coupon->addCoupon($this->request->post); + } else { + $this->model_marketing_coupon->editCoupon($this->request->post['coupon_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('marketing/coupon'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'marketing/coupon')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('marketing/coupon'); + + foreach ($selected as $coupon_id) { + $this->model_marketing_coupon->deleteCoupon($coupon_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function history(): void { + $this->load->language('marketing/coupon'); + + $this->response->setOutput($this->getHistory()); + } + + /** + * @return string + */ + public function getHistory(): string { + if (isset($this->request->get['coupon_id'])) { + $coupon_id = (int)$this->request->get['coupon_id']; + } else { + $coupon_id = 0; + } + + if (isset($this->request->get['page']) && $this->request->get['route'] == 'marketing/coupon.history') { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $limit = 10; + + $this->load->model('marketing/coupon'); + + $data['histories'] = []; + + $results = $this->model_marketing_coupon->getHistories($coupon_id, ($page - 1) * $limit, $limit); + + foreach ($results as $result) { + $data['histories'][] = [ + 'order_id' => $result['order_id'], + 'customer' => $result['customer'], + 'amount' => $result['amount'], + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])) + ]; + } + + $history_total = $this->model_marketing_coupon->getTotalHistories($coupon_id); + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $history_total, + 'page' => $page, + 'limit' => $limit, + 'url' => $this->url->link('marketing/coupon.history', 'user_token=' . $this->session->data['user_token'] . '&coupon_id=' . $coupon_id . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($history_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($history_total - $limit)) ? $history_total : ((($page - 1) * $limit) + $limit), $history_total, ceil($history_total / $limit)); + + return $this->load->view('marketing/coupon_history', $data); + } +} diff --git a/admininistrator/controller/marketing/marketing.php b/admininistrator/controller/marketing/marketing.php new file mode 100644 index 0000000..58579d6 --- /dev/null +++ b/admininistrator/controller/marketing/marketing.php @@ -0,0 +1,530 @@ +load->language('marketing/marketing'); + + $this->document->setTitle($this->language->get('heading_title')); + + if (isset($this->request->get['filter_name'])) { + $filter_name = $this->request->get['filter_name']; + } else { + $filter_name = ''; + } + + if (isset($this->request->get['filter_code'])) { + $filter_code = $this->request->get['filter_code']; + } else { + $filter_code = ''; + } + + if (isset($this->request->get['filter_date_from'])) { + $filter_date_from = $this->request->get['filter_date_from']; + } else { + $filter_date_from = ''; + } + + if (isset($this->request->get['filter_date_to'])) { + $filter_date_to = $this->request->get['filter_date_to']; + } else { + $filter_date_to = ''; + } + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_code'])) { + $url .= '&filter_code=' . $this->request->get['filter_code']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('marketing/marketing', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('marketing/marketing.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('marketing/marketing.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['filter_name'] = $filter_name; + $data['filter_code'] = $filter_code; + $data['filter_date_from'] = $filter_date_from; + $data['filter_date_to'] = $filter_date_to; + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('marketing/marketing', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('marketing/marketing'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['filter_name'])) { + $filter_name = $this->request->get['filter_name']; + } else { + $filter_name = ''; + } + + if (isset($this->request->get['filter_code'])) { + $filter_code = $this->request->get['filter_code']; + } else { + $filter_code = ''; + } + + if (isset($this->request->get['filter_date_from'])) { + $filter_date_from = (string)$this->request->get['filter_date_from']; + } else { + $filter_date_from = ''; + } + + if (isset($this->request->get['filter_date_to'])) { + $filter_date_to = (string)$this->request->get['filter_date_to']; + } else { + $filter_date_to = ''; + } + + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'm.name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_code'])) { + $url .= '&filter_code=' . $this->request->get['filter_code']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('marketing/marketing.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['marketings'] = []; + + $filter_data = [ + 'filter_name' => $filter_name, + 'filter_code' => $filter_code, + 'filter_date_from' => $filter_date_from, + 'filter_date_to' => $filter_date_to, + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('marketing/marketing'); + + $marketing_total = $this->model_marketing_marketing->getTotalMarketings($filter_data); + + $results = $this->model_marketing_marketing->getMarketings($filter_data); + + foreach ($results as $result) { + $data['marketings'][] = [ + 'marketing_id' => $result['marketing_id'], + 'name' => $result['name'], + 'code' => $result['code'], + 'clicks' => $result['clicks'], + 'orders' => $result['orders'], + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])), + 'edit' => $this->url->link('marketing/marketing.form', 'user_token=' . $this->session->data['user_token'] . '&marketing_id=' . $result['marketing_id'] . $url) + ]; + } + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_code'])) { + $url .= '&filter_code=' . $this->request->get['filter_code']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('marketing/marketing.list', 'user_token=' . $this->session->data['user_token'] . '&sort=m.name' . $url); + $data['sort_code'] = $this->url->link('marketing/marketing.list', 'user_token=' . $this->session->data['user_token'] . '&sort=m.code' . $url); + $data['sort_date_added'] = $this->url->link('marketing/marketing.list', 'user_token=' . $this->session->data['user_token'] . '&sort=m.date_added' . $url); + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_code'])) { + $url .= '&filter_code=' . $this->request->get['filter_code']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $marketing_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('marketing/marketing.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($marketing_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($marketing_total - $this->config->get('config_pagination_admin'))) ? $marketing_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $marketing_total, ceil($marketing_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('marketing/marketing_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('marketing/marketing'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['marketing_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_code'])) { + $url .= '&filter_code=' . $this->request->get['filter_code']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('marketing/marketing', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('marketing/marketing.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('marketing/marketing', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['marketing_id'])) { + $this->load->model('marketing/marketing'); + + $marketing_info = $this->model_marketing_marketing->getMarketing($this->request->get['marketing_id']); + } + + if (isset($this->request->get['marketing_id'])) { + $data['marketing_id'] = (int)$this->request->get['marketing_id']; + } else { + $data['marketing_id'] = 0; + } + + $data['store'] = HTTP_CATALOG; + + if (!empty($marketing_info)) { + $data['name'] = $marketing_info['name']; + } else { + $data['name'] = ''; + } + + if (!empty($marketing_info)) { + $data['description'] = $marketing_info['description']; + } else { + $data['description'] = ''; + } + + if (!empty($marketing_info)) { + $data['code'] = $marketing_info['code']; + } else { + $data['code'] = uniqid(); + } + + $data['report'] = $this->getReport(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('marketing/marketing_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('marketing/marketing'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'marketing/marketing')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if ((oc_strlen($this->request->post['name']) < 1) || (oc_strlen($this->request->post['name']) > 32)) { + $json['error']['name'] = $this->language->get('error_name'); + } + + if (!$this->request->post['code']) { + $json['error']['code'] = $this->language->get('error_code'); + } + + $this->load->model('marketing/marketing'); + + $marketing_info = $this->model_marketing_marketing->getMarketingByCode($this->request->post['code']); + + if ($marketing_info && (!isset($this->request->post['marketing_id']) || ($this->request->post['marketing_id'] != $marketing_info['marketing_id']))) { + $json['error']['code'] = $this->language->get('error_exists'); + } + + if (!$json) { + if (!$this->request->post['marketing_id']) { + $json['marketing_id'] = $this->model_marketing_marketing->addMarketing($this->request->post); + } else { + $this->model_marketing_marketing->editMarketing($this->request->post['marketing_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('marketing/marketing'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'marketing/marketing')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('marketing/marketing'); + + foreach ($selected as $marketing_id) { + $this->model_marketing_marketing->deleteMarketing($marketing_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function report(): void { + $this->load->language('marketing/marketing'); + + $this->response->setOutput($this->getReport()); + } + + /** + * @return string + */ + public function getReport(): string { + if (isset($this->request->get['marketing_id'])) { + $marketing_id = (int)$this->request->get['marketing_id']; + } else { + $marketing_id = 0; + } + + if (isset($this->request->get['page']) && $this->request->get['route'] == 'marketing/marketing.report') { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $limit = 10; + + $data['reports'] = []; + + $this->load->model('marketing/marketing'); + $this->load->model('customer/customer'); + $this->load->model('setting/store'); + + $results = $this->model_marketing_marketing->getReports($marketing_id, ($page - 1) * $limit, $limit); + + foreach ($results as $result) { + $store_info = $this->model_setting_store->getStore($result['store_id']); + + if ($store_info) { + $store = $store_info['name']; + } elseif (!$result['store_id']) { + $store = $this->config->get('config_name'); + } else { + $store = ''; + } + + $data['reports'][] = [ + 'ip' => $result['ip'], + 'account' => $this->model_customer_customer->getTotalCustomersByIp($result['ip']), + 'store' => $store, + 'country' => $result['country'], + 'date_added' => date($this->language->get('datetime_format'), strtotime($result['date_added'])), + 'filter_ip' => $this->url->link('customer/customer', 'user_token=' . $this->session->data['user_token'] . '&filter_ip=' . $result['ip']) + ]; + } + + $report_total = $this->model_marketing_marketing->getTotalReports($marketing_id); + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $report_total, + 'page' => $page, + 'limit' => $limit, + 'url' => $this->url->link('marketing/marketing.report', 'user_token=' . $this->session->data['user_token'] . '&marketing_id=' . $marketing_id . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($report_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($report_total - $limit)) ? $report_total : ((($page - 1) * $limit) + $limit), $report_total, ceil($report_total / $limit)); + + return $this->load->view('marketing/marketing_report', $data); + } +} diff --git a/admininistrator/controller/marketplace/api.php b/admininistrator/controller/marketplace/api.php new file mode 100644 index 0000000..78bdc7f --- /dev/null +++ b/admininistrator/controller/marketplace/api.php @@ -0,0 +1,51 @@ +load->language('marketplace/api'); + + $data['user_token'] = $this->session->data['user_token']; + + $this->response->setOutput($this->load->view('marketplace/api', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('marketplace/api'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'marketplace/api')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if (!$this->request->post['opencart_username']) { + $json['error']['username'] = $this->language->get('error_username'); + } + + if (!$this->request->post['opencart_secret']) { + $json['error']['secret'] = $this->language->get('error_secret'); + } + + if (!$json) { + $this->load->model('setting/setting'); + + $this->model_setting_setting->editSetting('opencart', $this->request->post); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/marketplace/cron.php b/admininistrator/controller/marketplace/cron.php new file mode 100644 index 0000000..3d4b2a2 --- /dev/null +++ b/admininistrator/controller/marketplace/cron.php @@ -0,0 +1,310 @@ +load->language('marketplace/cron'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('marketplace/cron', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['delete'] = $this->url->link('marketplace/cron.delete', 'user_token=' . $this->session->data['user_token']); + + // Example cron URL + $data['cron'] = HTTP_CATALOG . 'index.php?route=cron/cron'; + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('marketplace/cron', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('marketplace/cron'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'code'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('marketplace/cron.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['crons'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('setting/cron'); + + $cron_total = $this->model_setting_cron->getTotalCrons(); + + $results = $this->model_setting_cron->getCrons($filter_data); + + foreach ($results as $result) { + $data['crons'][] = [ + 'cron_id' => $result['cron_id'], + 'code' => $result['code'], + 'description' => $result['description'], + 'cycle' => $this->language->get('text_' . $result['cycle']), + 'action' => $result['action'], + 'status' => $result['status'], + 'date_added' => date($this->language->get('datetime_format'), strtotime($result['date_added'])), + 'date_modified' => date($this->language->get('datetime_format'), strtotime($result['date_modified'])), + 'run' => $this->url->link('marketplace/cron.run', 'user_token=' . $this->session->data['user_token'] . '&cron_id=' . $result['cron_id']), + 'enable' => $this->url->link('marketplace/cron.enable', 'user_token=' . $this->session->data['user_token'] . '&cron_id=' . $result['cron_id']), + 'disable' => $this->url->link('marketplace/cron.disable', 'user_token=' . $this->session->data['user_token'] . '&cron_id=' . $result['cron_id']) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_code'] = $this->url->link('marketplace/cron.list', 'user_token=' . $this->session->data['user_token'] . '&sort=code' . $url); + $data['sort_cycle'] = $this->url->link('marketplace/cron.list', 'user_token=' . $this->session->data['user_token'] . '&sort=cycle' . $url); + $data['sort_action'] = $this->url->link('marketplace/cron.list', 'user_token=' . $this->session->data['user_token'] . '&sort=action' . $url); + $data['sort_date_added'] = $this->url->link('marketplace/cron.list', 'user_token=' . $this->session->data['user_token'] . '&sort=date_added' . $url); + $data['sort_date_modified'] = $this->url->link('marketplace/cron.list', 'user_token=' . $this->session->data['user_token'] . '&sort=date_modified' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $cron_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('marketplace/cron.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($cron_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($cron_total - $this->config->get('config_pagination_admin'))) ? $cron_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $cron_total, ceil($cron_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('marketplace/cron_list', $data); + } + + /** + * @return void + */ + public function run(): void { + $this->load->language('marketplace/cron'); + + $json = []; + + if (isset($this->request->get['cron_id'])) { + $cron_id = (int)$this->request->get['cron_id']; + } else { + $cron_id = 0; + } + + if (!$this->user->hasPermission('modify', 'marketplace/cron')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/cron'); + + $cron_info = $this->model_setting_cron->getCron($cron_id); + + if ($cron_info) { + // Create a store instance using loader class to call controllers, models, views, libraries + $this->load->model('setting/store'); + + $store = $this->model_setting_store->createStoreInstance(0, $this->config->get('config_language')); + + $store->load->controller($cron_info['action'], $cron_id, $cron_info['code'], $cron_info['cycle'], $cron_info['date_added'], $cron_info['date_modified']); + + $store->session->destroy($store->session->getId()); + + $this->model_setting_cron->editCron($cron_info['cron_id']); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function enable(): void { + $this->load->language('marketplace/cron'); + + $json = []; + + if (isset($this->request->get['cron_id'])) { + $cron_id = (int)$this->request->get['cron_id']; + } else { + $cron_id = 0; + } + + if (!$this->user->hasPermission('modify', 'marketplace/cron')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/cron'); + + $this->model_setting_cron->editStatus($cron_id, 1); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function disable(): void { + $this->load->language('marketplace/cron'); + + $json = []; + + if (isset($this->request->get['cron_id'])) { + $cron_id = (int)$this->request->get['cron_id']; + } else { + $cron_id = 0; + } + + if (!$this->user->hasPermission('modify', 'marketplace/cron')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/cron'); + + $this->model_setting_cron->editStatus($cron_id, 0); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('marketplace/cron'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = (array)$this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'marketplace/event')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/cron'); + + foreach ($selected as $cron_id) { + $this->model_setting_cron->deleteCron($cron_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/marketplace/event.php b/admininistrator/controller/marketplace/event.php new file mode 100644 index 0000000..cf6de32 --- /dev/null +++ b/admininistrator/controller/marketplace/event.php @@ -0,0 +1,259 @@ +load->language('marketplace/event'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('marketplace/event', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['delete'] = $this->url->link('marketplace/event.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('marketplace/event', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('marketplace/event'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'code'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('marketplace/event.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['events'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('setting/event'); + + $event_total = $this->model_setting_event->getTotalEvents(); + + $results = $this->model_setting_event->getEvents($filter_data); + + foreach ($results as $result) { + $data['events'][] = [ + 'event_id' => $result['event_id'], + 'code' => $result['code'], + 'description' => $result['description'], + 'trigger' => $result['trigger'], + 'action' => $result['action'], + 'status' => $result['status'], + 'sort_order' => $result['sort_order'], + 'enable' => $this->url->link('marketplace/event.enable', 'user_token=' . $this->session->data['user_token'] . '&event_id=' . $result['event_id']), + 'disable' => $this->url->link('marketplace/event.disable', 'user_token=' . $this->session->data['user_token'] . '&event_id=' . $result['event_id']) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_code'] = $this->url->link('marketplace/event.list', 'user_token=' . $this->session->data['user_token'] . '&sort=code' . $url); + $data['sort_sort_order'] = $this->url->link('marketplace/event.list', 'user_token=' . $this->session->data['user_token'] . '&sort=sort_order' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $event_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('marketplace/event.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($event_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($event_total - $this->config->get('config_pagination_admin'))) ? $event_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $event_total, ceil($event_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('marketplace/event_list', $data); + } + + /** + * @return void + */ + public function enable(): void { + $this->load->language('marketplace/event'); + + $json = []; + + if (isset($this->request->get['event_id'])) { + $event_id = (int)$this->request->get['event_id']; + } else { + $event_id = 0; + } + + if (!$this->user->hasPermission('modify', 'marketplace/event')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/event'); + + $this->model_setting_event->editStatus($event_id, 1); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function disable(): void { + $this->load->language('marketplace/event'); + + $json = []; + + if (isset($this->request->get['event_id'])) { + $event_id = (int)$this->request->get['event_id']; + } else { + $event_id = 0; + } + + if (!$this->user->hasPermission('modify', 'marketplace/event')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/event'); + + $this->model_setting_event->editStatus($event_id, 0); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('marketplace/event'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = (array)$this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'marketplace/event')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/event'); + + foreach ($selected as $event_id) { + $this->model_setting_event->deleteEvent($event_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/marketplace/extension.php b/admininistrator/controller/marketplace/extension.php new file mode 100644 index 0000000..1bbc886 --- /dev/null +++ b/admininistrator/controller/marketplace/extension.php @@ -0,0 +1,73 @@ +load->language('marketplace/extension'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('marketplace/extension', 'user_token=' . $this->session->data['user_token']) + ]; + + if (isset($this->request->get['type'])) { + $data['type'] = $this->request->get['type']; + } else { + $data['type'] = ''; + } + + $data['categories'] = []; + + $this->load->model('setting/extension'); + + $files = glob(DIR_APPLICATION . 'controller/extension/*.php'); + + foreach ($files as $file) { + $extension = basename($file, '.php'); + + $this->load->language('extension/' . $extension, $extension); + + if ($this->user->hasPermission('access', 'extension/' . $extension)) { + $extensions = $this->model_setting_extension->getPaths('%/admin/controller/' . $extension . '/%.php'); + + $data['categories'][] = [ + 'code' => $extension, + 'text' => $this->language->get($extension . '_heading_title') . ' (' . count($extensions) . ')', + 'href' => $this->url->link('extension/' . $extension, 'user_token=' . $this->session->data['user_token']) + ]; + } + } + + if (isset($this->request->get['type'])) { + $data['extension'] = $this->load->controller('extension/' . basename($this->request->get['type']) . '.getList'); + } elseif ($data['categories']) { + $data['extension'] = $this->load->controller('extension/' . $data['categories'][0]['code'] . '.getList'); + } else { + $data['extension'] = ''; + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('marketplace/extension', $data)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/marketplace/installer.php b/admininistrator/controller/marketplace/installer.php new file mode 100644 index 0000000..268584f --- /dev/null +++ b/admininistrator/controller/marketplace/installer.php @@ -0,0 +1,715 @@ +load->language('marketplace/installer'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('marketplace/installer', 'user_token=' . $this->session->data['user_token']) + ]; + + // Use the for the max file size + $data['error_upload_size'] = sprintf($this->language->get('error_file_size'), ini_get('upload_max_filesize')); + + $data['config_file_max_size'] = ((int)preg_filter('/[^0-9]/', '', ini_get('upload_max_filesize')) * 1024 * 1024); + + $data['upload'] = $this->url->link('tool/installer.upload', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + if (isset($this->request->get['filter_extension_id'])) { + $data['filter_extension_download_id'] = (int)$this->request->get['filter_extension_download_id']; + } else { + $data['filter_extension_download_id'] = ''; + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('marketplace/installer', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('marketplace/cron'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + $this->load->language('marketplace/installer'); + + if (isset($this->request->get['filter_extension_download_id'])) { + $filter_extension_download_id = (int)$this->request->get['filter_extension_download_id']; + } else { + $filter_extension_download_id = ''; + } + + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $this->load->model('setting/extension'); + + // Look for any new extensions + $files = glob(DIR_STORAGE . 'marketplace/*.ocmod.zip'); + + foreach ($files as $file) { + $code = basename($file, '.ocmod.zip'); + + $install_info = $this->model_setting_extension->getInstallByCode($code); + + if (!$install_info) { + // Unzip the files + $zip = new \ZipArchive(); + + if ($zip->open($file, \ZipArchive::RDONLY)) { + $install_info = json_decode($zip->getFromName('install.json'), true); + + if ($install_info) { + $extension_data = [ + 'extension_id' => 0, + 'extension_download_id' => 0, + 'name' => $install_info['name'], + 'code' => $code, + 'version' => $install_info['version'], + 'author' => $install_info['author'], + 'link' => $install_info['link'] + ]; + + $this->model_setting_extension->addInstall($extension_data); + } + + $zip->close(); + } + } + } + + $data['extensions'] = []; + + $filter_data = [ + 'filter_extension_download_id' => $filter_extension_download_id, + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $extension_total = $this->model_setting_extension->getTotalInstalls($filter_data); + + $results = $this->model_setting_extension->getInstalls($filter_data); + + foreach ($results as $result) { + if ($result['extension_id']) { + $link = $this->url->link('marketplace/marketplace.info', 'user_token=' . $this->session->data['user_token'] . '&extension_id=' . $result['extension_id']); + } elseif ($result['link']) { + $link = $result['link']; + } else { + $link = ''; + } + + $data['extensions'][] = [ + 'name' => $result['name'], + 'version' => $result['version'], + 'author' => $result['author'], + 'status' => $result['status'], + 'link' => $link, + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])), + 'install' => $this->url->link('marketplace/installer.install', 'user_token=' . $this->session->data['user_token'] . '&extension_install_id=' . $result['extension_install_id']), + 'uninstall' => $this->url->link('marketplace/installer.uninstall', 'user_token=' . $this->session->data['user_token'] . '&extension_install_id=' . $result['extension_install_id']), + 'delete' => $this->url->link('marketplace/installer.delete', 'user_token=' . $this->session->data['user_token'] . '&extension_install_id=' . $result['extension_install_id']) + ]; + } + + $data['results'] = sprintf($this->language->get('text_pagination'), ($extension_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($extension_total - $this->config->get('config_pagination_admin'))) ? $extension_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $extension_total, ceil($extension_total / $this->config->get('config_pagination_admin'))); + + $url = ''; + + if (isset($this->request->get['filter_extension_id'])) { + $url .= '&filter_extension_id=' . $this->request->get['filter_extension_id']; + } + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('marketplace/installer.list', 'user_token=' . $this->session->data['user_token'] . '&sort=name' . $url); + $data['sort_version'] = $this->url->link('marketplace/installer.list', 'user_token=' . $this->session->data['user_token'] . '&sort=version' . $url); + $data['sort_date_added'] = $this->url->link('marketplace/installer.list', 'user_token=' . $this->session->data['user_token'] . '&sort=date_added' . $url); + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $extension_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('marketplace/installer.list', 'user_token=' . $this->session->data['user_token'] . '&page={page}') + ]); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('marketplace/installer_extension', $data); + } + + /** + * @return void + */ + public function upload(): void { + $this->load->language('marketplace/installer'); + + $json = []; + + // 1. Validate the file uploaded. + if (isset($this->request->files['file']['name'])) { + $filename = basename($this->request->files['file']['name']); + + // 2. Validate the filename. + if ((oc_strlen($filename) < 1) || (oc_strlen($filename) > 128)) { + $json['error'] = $this->language->get('error_filename'); + } + + // 3. Validate is ocmod file. + if (substr($filename, -10) != '.ocmod.zip') { + $json['error'] = $this->language->get('error_file_type'); + } + + // 4. check if there is already a file + $file = DIR_STORAGE . 'marketplace/' . $filename; + + if (is_file($file)) { + $json['error'] = $this->language->get('error_file_exists'); + + unlink($this->request->files['file']['tmp_name']); + } + + if ($this->request->files['file']['error'] != UPLOAD_ERR_OK) { + $json['error'] = $this->language->get('error_upload_' . $this->request->files['file']['error']); + } + + if ($this->model_setting_extension->getInstallByCode(basename($filename, '.ocmod.zip'))) { + $json['error'] = $this->language->get('error_installed'); + } + } else { + $json['error'] = $this->language->get('error_upload'); + } + + // 5. Validate if the file can be opened and there is install.json that can be read. + if (!$json) { + move_uploaded_file($this->request->files['file']['tmp_name'], $file); + + // Unzip the files + $zip = new \ZipArchive(); + + if ($zip->open($file, \ZipArchive::RDONLY)) { + $install_info = json_decode($zip->getFromName('install.json'), true); + + if ($install_info) { + if (!$install_info['name']) { + $json['error'] = $this->language->get('error_name'); + } + + if (!$install_info['version']) { + $json['error'] = $this->language->get('error_version'); + } + + if (!$install_info['author']) { + $json['error'] = $this->language->get('error_author'); + } + + if (!$install_info['link']) { + $json['error'] = $this->language->get('error_link'); + } + } else { + $json['error'] = $this->language->get('error_install'); + } + + $zip->close(); + } else { + $json['error'] = $this->language->get('error_unzip'); + } + } + + if (!$json) { + $extension_data = [ + 'extension_id' => 0, + 'extension_download_id' => 0, + 'name' => $install_info['name'], + 'code' => basename($filename, '.ocmod.zip'), + 'version' => $install_info['version'], + 'author' => $install_info['author'], + 'link' => $install_info['link'] + ]; + + $this->load->model('setting/extension'); + + $this->model_setting_extension->addInstall($extension_data); + + $json['success'] = $this->language->get('text_upload'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function install(): void { + $this->load->language('marketplace/installer'); + + $json = []; + + if (isset($this->request->get['extension_install_id'])) { + $extension_install_id = (int)$this->request->get['extension_install_id']; + } else { + $extension_install_id = 0; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + if (!$this->user->hasPermission('modify', 'marketplace/installer')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('setting/extension'); + + $extension_install_info = $this->model_setting_extension->getInstall($extension_install_id); + + if ($extension_install_info) { + $file = DIR_STORAGE . 'marketplace/' . $extension_install_info['code'] . '.ocmod.zip'; + + if (!is_file($file)) { + $json['error'] = sprintf($this->language->get('error_file'), $extension_install_info['code'] . '.ocmod.zip'); + } + + if ($page == 1 && is_dir(DIR_EXTENSION . $extension_install_info['code'] . '/')) { + $json['error'] = sprintf($this->language->get('error_directory_exists'), $extension_install_info['code'] . '/'); + } + + if ($page > 1 && !is_dir(DIR_EXTENSION . $extension_install_info['code'] . '/')) { + $json['error'] = sprintf($this->language->get('error_directory'), $extension_install_info['code'] . '/'); + } + } else { + $json['error'] = $this->language->get('error_extension'); + } + + if (!$json) { + // Unzip the files + $zip = new \ZipArchive(); + + if ($zip->open($file)) { + $total = $zip->numFiles; + $limit = 200; + + $start = ($page - 1) * $limit; + $end = $start > ($total - $limit) ? $total : ($start + $limit); + + // Check if any of the files already exist. + for ($i = $start; $i < $end; $i++) { + $source = $zip->getNameIndex($i); + + $destination = str_replace('\\', '/', $source); + + // Only extract the contents of the upload folder + $path = $extension_install_info['code'] . '/' . $destination; + $base = DIR_EXTENSION; + $prefix = ''; + + // image > image + if (substr($destination, 0, 6) == 'image/') { + $path = $destination; + $base = substr(DIR_IMAGE, 0, -6); + } + + // We need to store the path differently for vendor folders. + if (substr($destination, 0, 15) == 'system/storage/') { + $path = substr($destination, 15); + $base = DIR_STORAGE; + $prefix = 'system/storage/'; + } + + // Must not have a path before files and directories can be moved + $path_new = ''; + + $directories = explode('/', dirname($path)); + + foreach ($directories as $directory) { + if (!$path_new) { + $path_new = $directory; + } else { + $path_new = $path_new . '/' . $directory; + } + + // To fix storage location + if (!is_dir($base . $path_new . '/') && mkdir($base . $path_new . '/', 0777)) { + $this->model_setting_extension->addPath($extension_install_id, $prefix . $path_new); + } + } + + // If check if the path is not directory and check there is no existing file + if (substr($source, -1) != '/') { + if (!is_file($base . $path) && copy('zip://' . $file . '#' . $source, $base . $path)) { + $this->model_setting_extension->addPath($extension_install_id, $prefix . $path); + } + } + } + + $zip->close(); + + $this->model_setting_extension->editStatus($extension_install_id, 1); + } else { + $json['error'] = $this->language->get('error_unzip'); + } + } + + if (!$json) { + $json['text'] = sprintf($this->language->get('text_progress'), 2, $total); + + $url = ''; + + if (isset($this->request->get['extension_install_id'])) { + $url .= '&extension_install_id=' . $this->request->get['extension_install_id']; + } + + if ($end < $total) { + $json['next'] = $this->url->link('marketplace/installer.install', 'user_token=' . $this->session->data['user_token'] . $url . '&page=' . ($page + 1), true); + } else { + $json['next'] = $this->url->link('marketplace/installer.vendor', 'user_token=' . $this->session->data['user_token'] . $url, true); + } + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function uninstall(): void { + $this->load->language('marketplace/installer'); + + $json = []; + + if (isset($this->request->get['extension_install_id'])) { + $extension_install_id = (int)$this->request->get['extension_install_id']; + } else { + $extension_install_id = 0; + } + + if (!$this->user->hasPermission('modify', 'marketplace/installer')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('setting/extension'); + + $extension_install_info = $this->model_setting_extension->getInstall($extension_install_id); + + if ($extension_install_info) { + if ($extension_install_info['code'] == 'opencart') { + $json['error'] = $this->language->get('error_default'); + } + + // Validate if extension being uninstalled + $extension_total = $this->model_setting_extension->getTotalExtensionsByExtension($extension_install_info['code']); + + if ($extension_total) { + $json['error'] = sprintf($this->language->get('error_uninstall'), $extension_total); + } + } else { + $json['error'] = $this->language->get('error_extension'); + } + + if (!$json) { + $files = []; + + // Make path into an array + $directory = [DIR_EXTENSION . $extension_install_info['code'] . '/']; + + // While the path array is still populated keep looping through + while (count($directory) != 0) { + $next = array_shift($directory); + + if (is_dir($next)) { + foreach (glob(rtrim($next, '/') . '/{*,.[!.]*,..?*}', GLOB_BRACE) as $file) { + // If directory add to path array + $directory[] = $file; + } + } + + // Add the file to the files to be deleted array + $files[] = $next; + } + + // Reverse sort the file array + rsort($files); + + foreach ($files as $file) { + // If file just delete + if (is_file($file)) { + unlink($file); + } + + // If directory use the remove directory function + if (is_dir($file)) { + rmdir($file); + } + } + + // Remove extension directory and files + $results = $this->model_setting_extension->getPathsByExtensionInstallId($extension_install_id); + + rsort($results); + + foreach ($results as $result) { + $path = ''; + + // Remove images + if (substr($result['path'], 0, 6) == 'image/') { + $path = DIR_IMAGE . substr($result['path'], 6); + } + + // Remove vendor files or any connected extensions that was also installed. + if (substr($result['path'], 0, 15) == 'system/storage/') { + $path = DIR_STORAGE . substr($result['path'], 15); + } + + // Check if the location exists or not + $path_total = $this->model_setting_extension->getTotalPaths($result['path']); + + if ($path_total < 2) { + if (is_file($path)) { + unlink($path); + } + + if (is_dir($path)) { + rmdir($path); + } + } + + $this->model_setting_extension->deletePath($result['extension_path_id']); + } + + // Remove extension directory + $this->model_setting_extension->editStatus($extension_install_id, 0); + + $url = ''; + + if (isset($this->request->get['extension_install_id'])) { + $url .= '&extension_install_id=' . $this->request->get['extension_install_id']; + } + + $json['next'] = $this->url->link('marketplace/installer.vendor', 'user_token=' . $this->session->data['user_token'] . $url, true); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /* Generate new autoloader file */ + /** + * @return void + */ + public function vendor(): void { + $this->load->language('marketplace/installer'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'marketplace/installer')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + // Generate php autoload file + $code = ' $path) { + if (!is_array($path)) { + $code .= '$autoloader->register(\'' . rtrim($namespace, '\\') . '\', DIR_STORAGE . \'vendor/' . $directory . '/' . rtrim($path, '/') . '/' . '\', true);' . "\n"; + } else { + foreach ($path as $value) { + $code .= '$autoloader->register(\'' . rtrim($namespace, '\\') . '\', DIR_STORAGE . \'vendor/' . $directory . '/' . rtrim($value, '/') . '/' . '\', true);' . "\n"; + } + } + } + } + + // Autoload psr-0 files + if (isset($output['autoload']['psr-0'])) { + $autoload = $output['autoload']['psr-0']; + + foreach ($autoload as $namespace => $path) { + if (!is_array($path)) { + $code .= '$autoloader->register(\'' . rtrim($namespace, '\\') . '\', DIR_STORAGE . \'vendor/' . $directory . '/' . rtrim($path, '/') . '/' . '\', true);' . "\n"; + } else { + foreach ($path as $value) { + $code .= '$autoloader->register(\'' . rtrim($namespace, '\\') . '\', DIR_STORAGE . \'vendor/' . $directory . '/' . rtrim($value, '/') . '/' . '\', true);' . "\n"; + } + } + } + } + + // Autoload classmap + if (isset($output['autoload']['classmap'])) { + $autoload = []; + + $classmaps = $output['autoload']['classmap']; + + foreach ($classmaps as $classmap) { + $directories = [dirname($file) . '/' . $classmap]; + + while (count($directories) != 0) { + $next = array_shift($directories); + + if (is_dir($next)) { + foreach (glob(trim($next, '/') . '/{*,.[!.]*,..?*}', GLOB_BRACE) as $file) { + if (is_dir($file)) { + $directories[] = $file . '/'; + } + + if (is_file($file)) { + $namespace = substr(dirname($file), strlen(DIR_STORAGE . 'vendor/' . $directory . $classmap) + 1); + + if ($namespace) { + $autoload[$namespace] = substr(dirname($file), strlen(DIR_STORAGE . 'vendor/')); + } + } + } + } + } + } + + foreach ($autoload as $namespace => $path) { + $code .= '$autoloader->register(\'' . rtrim($namespace, '\\') . '\', DIR_STORAGE . \'vendor/' . rtrim($path, '/') . '/' . '\', true);' . "\n"; + } + } + + // Autoload files + if (isset($output['autoload']['files'])) { + $files = $output['autoload']['files']; + + foreach ($files as $file) { + $code .= 'require_once(DIR_STORAGE . \'vendor/' . $directory . '/' . $file . '\');' . "\n"; + } + } + } + + $code .= "\n"; + } + + file_put_contents(DIR_SYSTEM . 'vendor.php', trim($code)); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('marketplace/installer'); + + $json = []; + + if (isset($this->request->get['extension_install_id'])) { + $extension_install_id = (int)$this->request->get['extension_install_id']; + } else { + $extension_install_id = 0; + } + + if (!$this->user->hasPermission('modify', 'marketplace/installer')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('setting/extension'); + + $extension_install_info = $this->model_setting_extension->getInstall($extension_install_id); + + if ($extension_install_info && $extension_install_info['code'] == 'opencart') { + $json['error'] = $this->language->get('error_default'); + } + + if (!$extension_install_info) { + $json['error'] = $this->language->get('error_extension'); + } + + $extension_install_info = $this->model_setting_extension->getInstall($extension_install_id); + + if (!$json) { + $file = DIR_STORAGE . 'marketplace/' . $extension_install_info['code'] . '.ocmod.zip'; + + // Remove file + if (is_file($file)) { + unlink($file); + } + + $this->model_setting_extension->deleteInstall($extension_install_id); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/marketplace/marketplace.php b/admininistrator/controller/marketplace/marketplace.php new file mode 100644 index 0000000..52ff4e0 --- /dev/null +++ b/admininistrator/controller/marketplace/marketplace.php @@ -0,0 +1,1168 @@ +load->language('marketplace/marketplace'); + + $this->document->setTitle($this->language->get('heading_title')); + + if (isset($this->request->get['filter_search'])) { + $filter_search = (string)$this->request->get['filter_search']; + } else { + $filter_search = ''; + } + + if (isset($this->request->get['filter_category'])) { + $filter_category = (string)$this->request->get['filter_category']; + } else { + $filter_category = ''; + } + + if (isset($this->request->get['filter_license'])) { + $filter_license = (string)$this->request->get['filter_license']; + } else { + $filter_license = ''; + } + + if (isset($this->request->get['filter_rating'])) { + $filter_rating = (int)$this->request->get['filter_rating']; + } else { + $filter_rating = ''; + } + + if (isset($this->request->get['filter_member_type'])) { + $filter_member_type = (string)$this->request->get['filter_member_type']; + } else { + $filter_member_type = ''; + } + + if (isset($this->request->get['filter_member'])) { + $filter_member = (string)$this->request->get['filter_member']; + } else { + $filter_member = ''; + } + + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'date_modified'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['filter_search'])) { + $url .= '&filter_search=' . $this->request->get['filter_search']; + } + + if (isset($this->request->get['filter_category'])) { + $url .= '&filter_category=' . $this->request->get['filter_category']; + } + + if (isset($this->request->get['filter_license'])) { + $url .= '&filter_license=' . $this->request->get['filter_license']; + } + + if (isset($this->request->get['filter_rating'])) { + $url .= '&filter_rating=' . $this->request->get['filter_rating']; + } + + if (isset($this->request->get['filter_member_type'])) { + $url .= '&filter_member_type=' . $this->request->get['filter_member_type']; + } + + if (isset($this->request->get['filter_member'])) { + $url .= '&filter_member=' . $this->request->get['filter_member']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $time = time(); + + // We create a hash from the data in a similar method to how amazon does things. + $string = 'api/marketplace/list' . "\n"; + $string .= $this->config->get('opencart_username') . "\n"; + $string .= $this->request->server['HTTP_HOST'] . "\n"; + $string .= VERSION . "\n"; + $string .= $time . "\n"; + + $signature = base64_encode(hash_hmac('sha1', $string, $this->config->get('opencart_secret'), 1)); + + $url = '&username=' . urlencode($this->config->get('opencart_username')); + $url .= '&domain=' . $this->request->server['HTTP_HOST']; + $url .= '&version=' . VERSION; + $url .= '&time=' . $time; + $url .= '&signature=' . rawurlencode($signature); + + if (isset($this->request->get['filter_search'])) { + $url .= '&filter_search=' . urlencode($this->request->get['filter_search']); + } + + if (isset($this->request->get['filter_category'])) { + $url .= '&filter_category=' . $this->request->get['filter_category']; + } + + if (isset($this->request->get['filter_license'])) { + $url .= '&filter_license=' . $this->request->get['filter_license']; + } + + if (isset($this->request->get['filter_rating'])) { + $url .= '&filter_rating=' . $this->request->get['filter_rating']; + } + + if (isset($this->request->get['filter_member_type'])) { + $url .= '&filter_member_type=' . $this->request->get['filter_member_type']; + } + + if (isset($this->request->get['filter_member'])) { + $url .= '&filter_member=' . urlencode($this->request->get['filter_member']); + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $curl = curl_init(OPENCART_SERVER . 'index.php?route=api/marketplace' . $url); + + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); + curl_setopt($curl, CURLOPT_FORBID_REUSE, 1); + curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1); + curl_setopt($curl, CURLOPT_POST, 1); + + $response = curl_exec($curl); + + $status = curl_getinfo($curl, CURLINFO_HTTP_CODE); + + curl_close($curl); + + $response_info = json_decode($response, true); + + if (isset($response_info['extension_total'])) { + $extension_total = (int)$response_info['extension_total']; + } else { + $extension_total = 0; + } + + $url = ''; + + if (isset($this->request->get['filter_search'])) { + $url .= '&filter_search=' . $this->request->get['filter_search']; + } + + if (isset($this->request->get['filter_category'])) { + $url .= '&filter_category=' . $this->request->get['filter_category']; + } + + if (isset($this->request->get['filter_license'])) { + $url .= '&filter_license=' . $this->request->get['filter_license']; + } + + if (isset($this->request->get['filter_rating'])) { + $url .= '&filter_rating=' . $this->request->get['filter_rating']; + } + + if (isset($this->request->get['filter_member_type'])) { + $url .= '&filter_member_type=' . $this->request->get['filter_member_type']; + } + + if (isset($this->request->get['filter_member'])) { + $url .= '&filter_member=' . $this->request->get['filter_member']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['promotions'] = []; + + if (isset($response_info['promotions']) && $page == 1) { + foreach ($response_info['promotions'] as $result) { + $data['promotions'][] = [ + 'name' => $result['name'], + 'description' => $result['description'], + 'image' => $result['image'], + 'license' => $result['license'], + 'price' => $result['price'], + 'rating' => $result['rating'], + 'rating_total' => $result['rating_total'], + 'href' => $this->url->link('marketplace/marketplace.info', 'user_token=' . $this->session->data['user_token'] . '&extension_id=' . $result['extension_id'] . $url) + ]; + } + } + + $data['extensions'] = []; + + if (isset($response_info['extensions'])) { + foreach ($response_info['extensions'] as $result) { + $data['extensions'][] = [ + 'name' => $result['name'], + 'description' => $result['description'], + 'image' => $result['image'], + 'license' => $result['license'], + 'price' => $result['price'], + 'rating' => $result['rating'], + 'rating_total' => $result['rating_total'], + 'href' => $this->url->link('marketplace/marketplace.info', 'user_token=' . $this->session->data['user_token'] . '&extension_id=' . $result['extension_id'] . $url) + ]; + } + } + + $data['signature'] = $this->config->get('opencart_username') && $this->config->get('opencart_secret'); + + if (!$this->config->get('opencart_username') || !$this->config->get('opencart_secret')) { + $data['error_warning'] = $this->language->get('error_api'); + } elseif (isset($response_info['error'])) { + $data['error_warning'] = $response_info['error']; + } else { + $data['error_warning'] = ''; + } + + // Categories + $url = ''; + + if (isset($this->request->get['filter_search'])) { + $url .= '&filter_search=' . $this->request->get['filter_search']; + } + + if (isset($this->request->get['filter_license'])) { + $url .= '&filter_license=' . $this->request->get['filter_license']; + } + + if (isset($this->request->get['filter_rating'])) { + $url .= '&filter_rating=' . $this->request->get['filter_rating']; + } + + if (isset($this->request->get['filter_member_type'])) { + $url .= '&filter_member_type=' . $this->request->get['filter_member_type']; + } + + if (isset($this->request->get['filter_member'])) { + $url .= '&filter_member=' . $this->request->get['filter_member']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + $data['categories'] = []; + + $data['categories'][] = [ + 'text' => $this->language->get('text_all'), + 'value' => '', + 'href' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['categories'][] = [ + 'text' => $this->language->get('text_theme'), + 'value' => 'theme', + 'href' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . '&filter_category=theme' . $url) + ]; + + $data['categories'][] = [ + 'text' => $this->language->get('text_marketplace'), + 'value' => 'marketplace', + 'href' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . '&filter_category=marketplace' . $url) + ]; + + $data['categories'][] = [ + 'text' => $this->language->get('text_language'), + 'value' => 'language', + 'href' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . '&filter_category=language' . $url) + ]; + + $data['categories'][] = [ + 'text' => $this->language->get('text_payment'), + 'value' => 'payment', + 'href' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . '&filter_category=payment' . $url) + ]; + + $data['categories'][] = [ + 'text' => $this->language->get('text_shipping'), + 'value' => 'shipping', + 'href' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . '&filter_category=shipping' . $url) + ]; + + $data['categories'][] = [ + 'text' => $this->language->get('text_module'), + 'value' => 'module', + 'href' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . '&filter_category=module' . $url) + ]; + + $data['categories'][] = [ + 'text' => $this->language->get('text_total'), + 'value' => 'total', + 'href' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . '&filter_category=total' . $url) + ]; + + $data['categories'][] = [ + 'text' => $this->language->get('text_feed'), + 'value' => 'feed', + 'href' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . '&filter_category=feed' . $url) + ]; + + $data['categories'][] = [ + 'text' => $this->language->get('text_report'), + 'value' => 'report', + 'href' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . '&filter_category=report' . $url) + ]; + + $data['categories'][] = [ + 'text' => $this->language->get('text_other'), + 'value' => 'other', + 'href' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . '&filter_category=other' . $url) + ]; + + // Licenses + $url = ''; + + if (isset($this->request->get['filter_search'])) { + $url .= '&filter_search=' . $this->request->get['filter_search']; + } + + if (isset($this->request->get['filter_category'])) { + $url .= '&filter_category=' . $this->request->get['filter_category']; + } + + if (isset($this->request->get['filter_rating'])) { + $url .= '&filter_rating=' . $this->request->get['filter_rating']; + } + + if (isset($this->request->get['filter_member_type'])) { + $url .= '&filter_member_type=' . $this->request->get['filter_member_type']; + } + + if (isset($this->request->get['filter_member'])) { + $url .= '&filter_member=' . $this->request->get['filter_member']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['licenses'] = []; + + $data['licenses'][] = [ + 'text' => $this->language->get('text_all'), + 'value' => '', + 'href' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['licenses'][] = [ + 'text' => $this->language->get('text_recommended'), + 'value' => 'recommended', + 'href' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . '&filter_license=recommended' . $url) + ]; + + $data['licenses'][] = [ + 'text' => $this->language->get('text_free'), + 'value' => 'free', + 'href' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . '&filter_license=free' . $url) + ]; + + $data['licenses'][] = [ + 'text' => $this->language->get('text_paid'), + 'value' => 'paid', + 'href' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . '&filter_license=paid' . $url) + ]; + + $data['licenses'][] = [ + 'text' => $this->language->get('text_purchased'), + 'value' => 'purchased', + 'href' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . '&filter_license=purchased' . $url) + ]; + + // Sort + $url = ''; + + if (isset($this->request->get['filter_search'])) { + $url .= '&filter_search=' . $this->request->get['filter_search']; + } + + if (isset($this->request->get['filter_category'])) { + $url .= '&filter_category=' . $this->request->get['filter_category']; + } + + if (isset($this->request->get['filter_license'])) { + $url .= '&filter_license=' . $this->request->get['filter_license']; + } + + if (isset($this->request->get['filter_rating'])) { + $url .= '&filter_rating=' . $this->request->get['filter_rating']; + } + + if (isset($this->request->get['filter_member_type'])) { + $url .= '&filter_member_type=' . $this->request->get['filter_member_type']; + } + + if (isset($this->request->get['filter_member'])) { + $url .= '&filter_member=' . $this->request->get['filter_member']; + } + + $data['sorts'] = []; + + $data['sorts'][] = [ + 'text' => $this->language->get('text_date_modified'), + 'value' => 'date_modified', + 'href' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . $url . '&sort=date_modified') + ]; + + $data['sorts'][] = [ + 'text' => $this->language->get('text_date_added'), + 'value' => 'date_added', + 'href' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . $url . '&sort=date_added') + ]; + + $data['sorts'][] = [ + 'text' => $this->language->get('text_rating'), + 'value' => 'rating', + 'href' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . $url . '&sort=rating') + ]; + + $data['sorts'][] = [ + 'text' => $this->language->get('text_name'), + 'value' => 'name', + 'href' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . $url . '&sort=name') + ]; + + $data['sorts'][] = [ + 'text' => $this->language->get('text_price'), + 'value' => 'price', + 'href' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . $url . '&sort=price') + ]; + + // Pagination + $url = ''; + + if (isset($this->request->get['filter_search'])) { + $url .= '&filter_search=' . $this->request->get['filter_search']; + } + + if (isset($this->request->get['filter_category'])) { + $url .= '&filter_category=' . $this->request->get['filter_category']; + } + + if (isset($this->request->get['filter_license'])) { + $url .= '&filter_license=' . $this->request->get['filter_license']; + } + + if (isset($this->request->get['filter_rating'])) { + $url .= '&filter_rating=' . $this->request->get['filter_rating']; + } + + if (isset($this->request->get['filter_member_type'])) { + $url .= '&filter_member_type=' . $this->request->get['filter_member_type']; + } + + if (isset($this->request->get['filter_member'])) { + $url .= '&filter_member=' . $this->request->get['filter_member']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $extension_total, + 'page' => $page, + 'limit' => 12, + 'url' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['filter_search'] = $filter_search; + $data['filter_category'] = $filter_category; + $data['filter_license'] = $filter_license; + $data['filter_member_type'] = $filter_member_type; + $data['filter_rating'] = $filter_rating; + $data['sort'] = $sort; + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('marketplace/marketplace_list', $data)); + } + + /** + * @return object|\Opencart\System\Engine\Action|null + */ + public function info(): object|null { + if (isset($this->request->get['extension_id'])) { + $extension_id = (int)$this->request->get['extension_id']; + } else { + $extension_id = 0; + } + + $time = time(); + + // We create a hash from the data in a similar method to how amazon does things. + $string = 'api/marketplace/info' . "\n"; + $string .= $this->config->get('opencart_username') . "\n"; + $string .= $this->request->server['HTTP_HOST'] . "\n"; + $string .= VERSION . "\n"; + $string .= $extension_id . "\n"; + $string .= $time . "\n"; + + $signature = base64_encode(hash_hmac('sha1', $string, $this->config->get('opencart_secret'), 1)); + + $url = '&username=' . urlencode($this->config->get('opencart_username')); + $url .= '&domain=' . $this->request->server['HTTP_HOST']; + $url .= '&version=' . VERSION; + $url .= '&extension_id=' . $extension_id; + $url .= '&time=' . $time; + $url .= '&signature=' . rawurlencode($signature); + + $curl = curl_init(OPENCART_SERVER . 'index.php?route=api/marketplace/info' . $url); + + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); + curl_setopt($curl, CURLOPT_FORBID_REUSE, 1); + curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1); + curl_setopt($curl, CURLOPT_POST, 1); + + $response = curl_exec($curl); + + $status = curl_getinfo($curl, CURLINFO_HTTP_CODE); + + curl_close($curl); + + $response_info = json_decode($response, true); + + if ($response_info) { + $this->load->language('marketplace/marketplace'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['signature'] = $this->config->get('opencart_username') && $this->config->get('opencart_secret'); + + if (!$this->config->get('opencart_username') || !$this->config->get('opencart_secret')) { + $data['error_warning'] = $this->language->get('error_api'); + } elseif (isset($response_info['error'])) { + $data['error_warning'] = $response_info['error']; + } else { + $data['error_warning'] = ''; + } + + $url = ''; + + if (isset($this->request->get['filter_search'])) { + $url .= '&filter_search=' . $this->request->get['filter_search']; + } + + if (isset($this->request->get['filter_category'])) { + $url .= '&filter_category=' . $this->request->get['filter_category']; + } + + if (isset($this->request->get['filter_license'])) { + $url .= '&filter_license=' . $this->request->get['filter_license']; + } + + if (isset($this->request->get['filter_username'])) { + $url .= '&filter_username=' . $this->request->get['filter_username']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['back'] = $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['banner'] = $response_info['banner']; + + $data['extension_id'] = (int)$this->request->get['extension_id']; + $data['name'] = $response_info['name']; + $data['description'] = $response_info['description']; + $data['documentation'] = $response_info['documentation']; + $data['price'] = $response_info['price']; + $data['license'] = $response_info['license']; + $data['license_period'] = $response_info['license_period']; + $data['purchased'] = $response_info['purchased']; + $data['compatibility'] = $response_info['compatibility']; + + $data['rating'] = $response_info['rating']; + $data['rating_total'] = $response_info['rating_total']; + + $data['downloaded'] = $response_info['downloaded']; + $data['sales'] = $response_info['sales']; + + $data['date_added'] = date($this->language->get('date_format_short'), strtotime($response_info['date_added'])); + $data['date_modified'] = date($this->language->get('date_format_short'), strtotime($response_info['date_modified'])); + + $data['member_username'] = $response_info['member_username']; + $data['member_image'] = $response_info['member_image']; + $data['member_date_added'] = $response_info['member_date_added']; + $data['filter_member'] = $this->url->link('marketplace/marketplace', 'user_token=' . $this->session->data['user_token'] . '&filter_member=' . $response_info['member_username']); + + if (isset($response_info['comment_total'])) { + $data['comment_total'] = $response_info['comment_total']; + } else { + $data['comment_total'] = 0; + } + + $data['images'] = []; + + foreach ($response_info['images'] as $result) { + $data['images'][] = [ + 'thumb' => $result['thumb'], + 'popup' => $result['popup'] + ]; + } + + $this->load->model('setting/extension'); + + $data['downloads'] = []; + + if ($response_info['downloads']) { + $this->session->data['extension_download'][$extension_id] = $response_info['downloads']; + } else { + $this->session->data['extension_download'][$extension_id] = []; + $this->session->data['extension_download'][$extension_id] = []; + } + + $this->document->addStyle('view/javascript/jquery/magnific/magnific-popup.css'); + $this->document->addScript('view/javascript/jquery/magnific/jquery.magnific-popup.min.js'); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('marketplace/marketplace_info', $data)); + + return null; + } else { + return new \Opencart\System\Engine\Action('error/not_found'); + } + } + + /** + * @return void + */ + public function extension(): void { + $this->load->language('marketplace/marketplace'); + + if (isset($this->request->get['extension_id'])) { + $extension_id = (int)$this->request->get['extension_id']; + } else { + $extension_id = 0; + } + + $this->load->model('setting/extension'); + + $data['downloads'] = []; + + if (isset($this->session->data['extension_download'][$extension_id])) { + $results = $this->session->data['extension_download'][$extension_id]; + + foreach ($results as $result) { + if (substr($result['filename'], -10) == '.ocmod.zip') { + $code = basename($result['filename'], '.ocmod.zip'); + + $install_info = $this->model_setting_extension->getInstallByCode($code); + + // Download + if (!$install_info) { + $download = $this->url->link('marketplace/marketplace.download', 'user_token=' . $this->session->data['user_token'] . '&extension_id=' . $extension_id . '&extension_download_id=' . $result['extension_download_id']); + } else { + $download = ''; + } + + // Install + if ($install_info && !$install_info['status']) { + $install = $this->url->link('marketplace/installer.install', 'user_token=' . $this->session->data['user_token'] . '&extension_install_id=' . $install_info['extension_install_id']); + } else { + $install = ''; + } + + // Uninstall + if ($install_info && $install_info['status']) { + $uninstall = $this->url->link('marketplace/installer.uninstall', 'user_token=' . $this->session->data['user_token'] . '&extension_install_id=' . $install_info['extension_install_id']); + } else { + $uninstall = ''; + } + + // Delete + if ($install_info && !$install_info['status']) { + $delete = $this->url->link('marketplace/installer.delete', 'user_token=' . $this->session->data['user_token'] . '&extension_install_id=' . $install_info['extension_install_id']); + } else { + $delete = ''; + } + + $data['downloads'][] = [ + 'name' => $result['name'], + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])), + 'download' => $download, + 'install' => $install, + 'uninstall' => $uninstall, + 'delete' => $delete + ]; + } + } + } + + $this->response->setOutput($this->load->view('marketplace/marketplace_extension', $data)); + } + + /** + * @return void + */ + public function purchase(): void { + $this->load->language('marketplace/marketplace'); + + $json = []; + + if (isset($this->request->get['extension_id'])) { + $extension_id = (int)$this->request->get['extension_id']; + } else { + $extension_id = 0; + } + + if (!$this->user->hasPermission('modify', 'marketplace/marketplace')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$this->config->get('opencart_username') || !$this->config->get('opencart_secret')) { + $json['error'] = $this->language->get('error_api'); + } + + if (!$this->request->post['pin']) { + $json['error'] = $this->language->get('error_pin'); + } + + if (!$json) { + $time = time(); + + // We create a hash from the data in a similar method to how amazon does things. + $string = 'api/marketplace/purchase' . "\n"; + $string .= $this->config->get('opencart_username') . "\n"; + $string .= $this->request->server['HTTP_HOST'] . "\n"; + $string .= VERSION . "\n"; + $string .= $extension_id . "\n"; + $string .= $this->request->post['pin'] . "\n"; + $string .= $time . "\n"; + + $signature = base64_encode(hash_hmac('sha1', $string, $this->config->get('opencart_secret'), 1)); + + $url = '&username=' . urlencode($this->config->get('opencart_username')); + $url .= '&domain=' . $this->request->server['HTTP_HOST']; + $url .= '&version=' . urlencode(VERSION); + $url .= '&extension_id=' . $extension_id; + $url .= '&time=' . $time; + $url .= '&signature=' . rawurlencode($signature); + + $curl = curl_init(OPENCART_SERVER . 'index.php?route=api/marketplace/purchase' . $url); + + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_FORBID_REUSE, 1); + curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1); + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); + + $response = curl_exec($curl); + + curl_close($curl); + + $response_info = json_decode($response, true); + + if (isset($response_info['success'])) { + // If purchase complete we update the status for all downloads to be available. + if (isset($this->session->data['extension_download'][$extension_id])) { + $results = $this->session->data['extension_download'][$extension_id]; + + foreach (array_keys($results) as $key) { + $this->session->data['extension_download'][$extension_id][$key]['status'] = 1; + } + } + + $json['success'] = $response_info['success']; + } elseif (isset($response_info['error'])) { + $json['error'] = $response_info['error']; + } else { + $json['error'] = $this->language->get('error_purchase'); + } + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function download(): void { + $this->load->language('marketplace/marketplace'); + + $json = []; + + if (isset($this->request->get['extension_id'])) { + $extension_id = (int)$this->request->get['extension_id']; + } else { + $extension_id = 0; + } + + if (isset($this->request->get['extension_download_id'])) { + $extension_download_id = (int)$this->request->get['extension_download_id']; + } else { + $extension_download_id = 0; + } + + if (!$this->user->hasPermission('modify', 'marketplace/marketplace')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $time = time(); + + // We create a hash from the data in a similar method to how amazon does things. + $string = 'api/marketplace/download' . "\n"; + $string .= $this->config->get('opencart_username') . "\n"; + $string .= $this->request->server['HTTP_HOST'] . "\n"; + $string .= VERSION . "\n"; + $string .= $extension_id . "\n"; + $string .= $extension_download_id . "\n"; + $string .= $time . "\n"; + + $signature = base64_encode(hash_hmac('sha1', $string, $this->config->get('opencart_secret'), 1)); + + $url = '&username=' . urlencode($this->config->get('opencart_username')); + $url .= '&domain=' . $this->request->server['HTTP_HOST']; + $url .= '&version=' . urlencode(VERSION); + $url .= '&extension_id=' . $extension_id; + $url .= '&extension_download_id=' . $extension_download_id; + $url .= '&time=' . $time; + $url .= '&signature=' . rawurlencode($signature); + + $curl = curl_init(OPENCART_SERVER . 'index.php?route=api/marketplace/download&extension_download_id=' . $extension_download_id . $url); + + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_FORBID_REUSE, 1); + curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1); + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); + + $response = curl_exec($curl); + + $response_info = json_decode($response, true); + + curl_close($curl); + + if (isset($response_info['download'])) { + if (substr($response_info['filename'], -10) == '.ocmod.zip') { + $handle = fopen(DIR_STORAGE . 'marketplace/' . $response_info['filename'], 'w'); + + $download = file_get_contents($response_info['download']); + + fwrite($handle, $download); + + fclose($handle); + + $extension_data = [ + 'extension_id' => $extension_id, + 'extension_download_id' => $extension_download_id, + 'name' => $response_info['name'], + 'code' => basename($response_info['filename'], '.ocmod.zip'), + 'author' => $response_info['author'], + 'version' => $response_info['version'], + 'link' => OPENCART_SERVER . 'index.php?route=marketplace/extension.info&extension_id=' . $extension_id + ]; + + $this->load->model('setting/extension'); + + $json['extension_install_id'] = $this->model_setting_extension->addInstall($extension_data); + + $json['success'] = $this->language->get('text_success'); + } else { + $json['redirect'] = $response_info['download']; + } + } elseif (isset($response_info['error'])) { + $json['error'] = $response_info['error']; + } else { + $json['error'] = $this->language->get('error_download'); + } + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function addComment(): void { + $this->load->language('marketplace/marketplace'); + + $json = []; + + if (isset($this->request->get['extension_id'])) { + $extension_id = (int)$this->request->get['extension_id']; + } else { + $extension_id = 0; + } + + if (isset($this->request->get['parent_id'])) { + $parent_id = (int)$this->request->get['parent_id']; + } else { + $parent_id = 0; + } + + if (!$this->user->hasPermission('modify', 'marketplace/marketplace')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$this->config->get('opencart_username') || !$this->config->get('opencart_secret')) { + $json['error'] = $this->language->get('error_opencart'); + } + + if (!$json) { + $time = time(); + + // We create a hash from the data in a similar method to how amazon does things. + $string = 'api/marketplace/addcomment' . "\n"; + $string .= urlencode($this->config->get('opencart_username')) . "\n"; + $string .= $this->request->server['HTTP_HOST'] . "\n"; + $string .= urlencode(VERSION) . "\n"; + $string .= $extension_id . "\n"; + $string .= $parent_id . "\n"; + $string .= urlencode(base64_encode($this->request->post['comment'])) . "\n"; + $string .= $time . "\n"; + + $signature = base64_encode(hash_hmac('sha1', $string, $this->config->get('opencart_secret'), 1)); + + $url = '&username=' . $this->config->get('opencart_username'); + $url .= '&domain=' . $this->request->server['HTTP_HOST']; + $url .= '&version=' . VERSION; + $url .= '&extension_id=' . $extension_id; + $url .= '&parent_id=' . $parent_id; + $url .= '&time=' . $time; + $url .= '&signature=' . rawurlencode($signature); + + $curl = curl_init(OPENCART_SERVER . 'index.php?route=api/marketplace/addcomment&extension_id=' . $extension_id . $url); + + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_FORBID_REUSE, 1); + curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1); + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); + curl_setopt($curl, CURLOPT_POST, 1); + curl_setopt($curl, CURLOPT_POSTFIELDS, ['comment' => $this->request->post['comment']]); + + $response = curl_exec($curl); + + curl_close($curl); + + $response_info = json_decode($response, true); + + if (isset($response_info['success'])) { + $json['success'] = $response_info['success']; + } elseif (isset($response_info['error'])) { + $json['error'] = $response_info['error']; + } else { + $json['error'] = $this->language->get('error_comment'); + } + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function comment(): void { + $this->load->language('marketplace/marketplace'); + + if (isset($this->request->get['extension_id'])) { + $extension_id = (int)$this->request->get['extension_id']; + } else { + $extension_id = 0; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $data['button_more'] = $this->language->get('button_more'); + $data['button_reply'] = $this->language->get('button_reply'); + + $curl = curl_init(OPENCART_SERVER . 'index.php?route=api/marketplace/comment&extension_id=' . $extension_id . '&page=' . $page); + + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_FORBID_REUSE, 1); + curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1); + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); + + $response = curl_exec($curl); + + curl_close($curl); + + $json = json_decode($response, true); + + $data['comments'] = []; + + $comment_total = $json['comment_total']; + + if ($json['comments']) { + $results = $json['comments']; + + foreach ($results as $result) { + if ($result['reply_total'] > 5) { + $next = $this->url->link('marketplace/marketplace.reply', 'user_token=' . $this->session->data['user_token'] . '&extension_id=' . $extension_id . '&parent_id=' . $result['extension_comment_id'] . '&page=2'); + } else { + $next = ''; + } + + $data['comments'][] = [ + 'extension_comment_id' => $result['extension_comment_id'], + 'member' => $result['member'], + 'image' => $result['image'], + 'comment' => $result['comment'], + 'date_added' => $result['date_added'], + 'reply' => $result['reply'], + 'add' => $this->url->link('marketplace/marketplace.addcomment', 'user_token=' . $this->session->data['user_token'] . '&extension_id=' . $extension_id . '&parent_id=' . $result['extension_comment_id']), + 'refresh' => $this->url->link('marketplace/marketplace.reply', 'user_token=' . $this->session->data['user_token'] . '&extension_id=' . $extension_id . '&parent_id=' . $result['extension_comment_id'] . '&page=1'), + 'next' => $next + ]; + } + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $comment_total, + 'page' => $page, + 'limit' => 20, + 'url' => $this->url->link('marketplace/marketplace.comment', 'user_token=' . $this->session->data['user_token'] . '&extension_id=' . $extension_id . '&page={page}') + ]); + + $data['refresh'] = $this->url->link('marketplace/marketplace.comment', 'user_token=' . $this->session->data['user_token'] . '&extension_id=' . $extension_id . '&page=' . $page); + + $this->response->setOutput($this->load->view('marketplace/marketplace_comment', $data)); + } + + /** + * @return void + */ + public function reply(): void { + $this->load->language('marketplace/marketplace'); + + if (isset($this->request->get['extension_id'])) { + $extension_id = (int)$this->request->get['extension_id']; + } else { + $extension_id = 0; + } + + if (isset($this->request->get['parent_id'])) { + $parent_id = (int)$this->request->get['parent_id']; + } else { + $parent_id = 0; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $curl = curl_init(OPENCART_SERVER . 'index.php?route=api/marketplace/comment&extension_id=' . $extension_id . '&parent_id=' . $parent_id . '&page=' . $page); + + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_FORBID_REUSE, 1); + curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1); + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); + + $response = curl_exec($curl); + + $json = json_decode($response, true); + + $data['replies'] = []; + + if (isset($json['reply_total'])) { + $reply_total = $json['reply_total']; + } else { + $reply_total = 0; + } + + if (isset($json['replies'])) { + $results = $json['replies']; + + foreach ($results as $result) { + $data['replies'][] = [ + 'extension_comment_id' => $result['extension_comment_id'], + 'member' => $result['member'], + 'image' => $result['image'], + 'comment' => $result['comment'], + 'date_added' => $result['date_added'] + ]; + } + } + + $data['refresh'] = $this->url->link('marketplace/marketplace.reply', 'user_token=' . $this->session->data['user_token'] . '&extension_id=' . $extension_id . '&parent_id=' . $parent_id . '&page=' . $page); + + if (($page * 5) < $reply_total) { + $data['next'] = $this->url->link('marketplace/marketplace.reply', 'user_token=' . $this->session->data['user_token'] . '&extension_id=' . $extension_id . '&parent_id=' . $parent_id . '&page=' . ($page + 1)); + } else { + $data['next'] = ''; + } + + $this->response->setOutput($this->load->view('marketplace/marketplace_reply', $data)); + } +} diff --git a/admininistrator/controller/marketplace/promotion.php b/admininistrator/controller/marketplace/promotion.php new file mode 100644 index 0000000..ef3a7dc --- /dev/null +++ b/admininistrator/controller/marketplace/promotion.php @@ -0,0 +1,104 @@ +load->language('marketplace/promotion'); + + if (isset($this->request->get['type'])) { + $type = $this->request->get['type']; + } else { + // Just in case there are any direct calls to methods we need to remove them to get the extension type + $pos = strrpos($this->request->get['route'], '.'); + + if ($pos !== false) { + $route = substr($this->request->get['route'], 0, $pos); + } else { + $route = $this->request->get['route']; + } + + $type = substr($route, strrpos($route, '/') + 1); + } + + $promotion = $this->cache->get('promotion.' . $type); + + if (!$promotion) { + $curl = curl_init(); + + curl_setopt($curl, CURLOPT_URL, OPENCART_SERVER . 'index.php?route=api/recommended&type=' . $type . '&version=' . VERSION); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_HEADER, false); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 30); + curl_setopt($curl, CURLOPT_TIMEOUT, 30); + + $response = curl_exec($curl); + + curl_close($curl); + + if ($response) { + $promotion = json_decode($response, true); + } else { + $promotion = ''; + } + + $this->cache->set('promotion.' . $type, $promotion, 3600 * 24); + } + + if (isset($promotion['banner'])) { + $data['banner'] = $promotion['banner']; + } else { + $data['banner'] = ''; + } + + $data['extensions'] = []; + + if (isset($promotion['extensions'])) { + $this->load->model('setting/extension'); + + foreach ($promotion['extensions'] as $result) { + $extension_install_info = $this->model_setting_extension->getInstallByExtensionDownloadId($result['extension_download_id']); + + // Download + if (!$extension_install_info) { + $download = $this->url->link('marketplace/marketplace.download', 'user_token=' . $this->session->data['user_token'] . '&extension_id=' . $result['extension_id'] . '&extension_download_id=' . $result['extension_download_id']); + } else { + $download = ''; + } + + // Install + if ($extension_install_info && !$extension_install_info['status']) { + $install = $this->url->link('marketplace/installer.install', 'user_token=' . $this->session->data['user_token'] . '&extension_install_id=' . $extension_install_info['extension_install_id']); + } else { + $install = ''; + } + + // Delete + if ($extension_install_info && !$extension_install_info['status']) { + $delete = $this->url->link('marketplace/installer.delete', 'user_token=' . $this->session->data['user_token'] . '&extension_install_id=' . $extension_install_info['extension_install_id']); + } else { + $delete = ''; + } + + if (!$extension_install_info || !$extension_install_info['status']) { + $data['extensions'][] = [ + 'name' => $result['name'], + 'href' => $this->url->link('marketplace/marketplace.info', 'user_token=' . $this->session->data['user_token'] . '&extension_id=' . $result['extension_id']), + 'download' => $download, + 'install' => $install, + 'delete' => $delete + ]; + } + } + } + + return $this->load->view('marketplace/promotion', $data); + } +} \ No newline at end of file diff --git a/admininistrator/controller/marketplace/startup.php b/admininistrator/controller/marketplace/startup.php new file mode 100644 index 0000000..a29dafc --- /dev/null +++ b/admininistrator/controller/marketplace/startup.php @@ -0,0 +1,258 @@ +load->language('marketplace/startup'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('marketplace/startup', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['delete'] = $this->url->link('marketplace/startup.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('marketplace/startup', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('marketplace/startup'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'code'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('marketplace/startup.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['startups'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('setting/startup'); + + $startup_total = $this->model_setting_startup->getTotalStartups(); + + $results = $this->model_setting_startup->getStartups($filter_data); + + foreach ($results as $result) { + $data['startups'][] = [ + 'startup_id' => $result['startup_id'], + 'code' => $result['code'], + 'action' => $result['action'], + 'status' => $result['status'], + 'sort_order' => $result['sort_order'], + 'enable' => $this->url->link('marketplace/startup.enable', 'user_token=' . $this->session->data['user_token'] . '&startup_id=' . $result['startup_id']), + 'disable' => $this->url->link('marketplace/startup.disable', 'user_token=' . $this->session->data['user_token'] . '&startup_id=' . $result['startup_id']) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_code'] = $this->url->link('marketplace/startup.list', 'user_token=' . $this->session->data['user_token'] . '&sort=code' . $url); + $data['sort_action'] = $this->url->link('marketplace/startup.list', 'user_token=' . $this->session->data['user_token'] . '&sort=action' . $url); + $data['sort_sort_order'] = $this->url->link('marketplace/startup.list', 'user_token=' . $this->session->data['user_token'] . '&sort=sort_order' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $startup_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('marketplace/startup.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($startup_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($startup_total - $this->config->get('config_pagination_admin'))) ? $startup_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $startup_total, ceil($startup_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('marketplace/startup_list', $data); + } + + /** + * @return void + */ + public function enable(): void { + $this->load->language('marketplace/startup'); + + $json = []; + + if (isset($this->request->get['startup_id'])) { + $startup_id = (int)$this->request->get['startup_id']; + } else { + $startup_id = 0; + } + + if (!$this->user->hasPermission('modify', 'marketplace/startup')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/startup'); + + $this->model_setting_startup->editStatus($startup_id, 1); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function disable(): void { + $this->load->language('marketplace/startup'); + + $json = []; + + if (isset($this->request->get['startup_id'])) { + $startup_id = (int)$this->request->get['startup_id']; + } else { + $startup_id = 0; + } + + if (!$this->user->hasPermission('modify', 'marketplace/startup')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/startup'); + + $this->model_setting_startup->editStatus($startup_id, 0); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('marketplace/startup'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = (array)$this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'marketplace/startup')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('setting/startup'); + + foreach ($selected as $startup_id) { + $this->model_setting_startup->deleteStartup($startup_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/report/online.php b/admininistrator/controller/report/online.php new file mode 100644 index 0000000..bc77040 --- /dev/null +++ b/admininistrator/controller/report/online.php @@ -0,0 +1,142 @@ +load->language('report/online'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode((string)$this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_ip'])) { + $url .= '&filter_ip=' . $this->request->get['filter_ip']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('report/online', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('report/online', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('report/online'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['filter_customer'])) { + $filter_customer = $this->request->get['filter_customer']; + } else { + $filter_customer = ''; + } + + if (isset($this->request->get['filter_ip'])) { + $filter_ip = $this->request->get['filter_ip']; + } else { + $filter_ip = ''; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $data['customers'] = []; + + $filter_data = [ + 'filter_customer' => $filter_customer, + 'filter_ip' => $filter_ip, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('report/online'); + $this->load->model('customer/customer'); + + $customer_total = $this->model_report_online->getTotalOnline($filter_data); + + $results = $this->model_report_online->getOnline($filter_data); + + foreach ($results as $result) { + $customer_info = $this->model_customer_customer->getCustomer($result['customer_id']); + + if ($customer_info) { + $customer = $customer_info['firstname'] . ' ' . $customer_info['lastname']; + } else { + $customer = $this->language->get('text_guest'); + } + + $data['customers'][] = [ + 'customer_id' => $result['customer_id'], + 'ip' => $result['ip'], + 'customer' => $customer, + 'url' => $result['url'], + 'referer' => $result['referer'], + 'date_added' => date($this->language->get('datetime_format'), strtotime($result['date_added'])), + 'edit' => $this->url->link('customer/customer.form', 'user_token=' . $this->session->data['user_token'] . '&customer_id=' . $result['customer_id']) + ]; + } + + $url = ''; + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode($this->request->get['filter_customer']); + } + + if (isset($this->request->get['filter_ip'])) { + $url .= '&filter_ip=' . $this->request->get['filter_ip']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $customer_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('report/online.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($customer_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($customer_total - $this->config->get('config_pagination_admin'))) ? $customer_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $customer_total, ceil($customer_total / $this->config->get('config_pagination_admin'))); + + return $this->load->view('report/online_list', $data); + } +} \ No newline at end of file diff --git a/admininistrator/controller/report/report.php b/admininistrator/controller/report/report.php new file mode 100644 index 0000000..a7aafcc --- /dev/null +++ b/admininistrator/controller/report/report.php @@ -0,0 +1,73 @@ +load->language('report/report'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('report/report', 'user_token=' . $this->session->data['user_token']) + ]; + + if (isset($this->request->get['code'])) { + $data['code'] = $this->request->get['code']; + } else { + $data['code'] = ''; + } + + // Reports + $data['reports'] = []; + + $this->load->model('setting/extension'); + + // Get a list of installed modules + $results = $this->model_setting_extension->getExtensionsByType('report'); + + // Add all the modules which have multiple settings for each module + foreach ($results as $result) { + if ($this->config->get('report_' . $result['code'] . '_status') && $this->user->hasPermission('access', 'extension/' . $result['extension'] . '/report/' . $result['code'])) { + $this->load->language('extension/' . $result['extension'] . '/report/' . $result['code'], $result['code']); + + $data['reports'][] = [ + 'text' => $this->language->get($result['code'] . '_heading_title'), + 'code' => $result['code'], + 'sort_order' => $this->config->get('report_' . $result['code'] . '_sort_order'), + 'href' => $this->url->link('extension/' . $result['extension'] . '/report/' . $result['code'] . '.report', 'user_token=' . $this->session->data['user_token']) + ]; + } + } + + $sort_order = []; + + foreach ($data['reports'] as $key => $value) { + $sort_order[$key] = $value['sort_order']; + } + + array_multisort($sort_order, SORT_ASC, $data['reports']); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('report/report', $data)); + } +} diff --git a/admininistrator/controller/report/statistics.php b/admininistrator/controller/report/statistics.php new file mode 100644 index 0000000..19e9274 --- /dev/null +++ b/admininistrator/controller/report/statistics.php @@ -0,0 +1,256 @@ +load->language('report/statistics'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('report/statistics', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('report/statistics', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('report/statistics'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + $data['statistics'] = []; + + $this->load->model('report/statistics'); + + $results = $this->model_report_statistics->getStatistics(); + + foreach ($results as $result) { + $data['statistics'][] = [ + 'name' => $this->language->get('text_' . $result['code']), + 'value' => $result['value'], + 'href' => $this->url->link('report/statistics.' . str_replace('_', '', $result['code']), 'user_token=' . $this->session->data['user_token']) + ]; + } + + return $this->load->view('report/statistics_list', $data); + } + + /** + * @return void + */ + public function orderSale(): void { + $this->load->language('report/statistics'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'report/statistics')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('report/statistics'); + $this->load->model('sale/order'); + + $this->model_report_statistics->editValue('order_sale', $this->model_sale_order->getTotalSales(['filter_order_status' => implode(',', array_merge($this->config->get('config_complete_status'), $this->config->get('config_processing_status')))])); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function orderProcessing(): void { + $this->load->language('report/statistics'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'report/statistics')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('report/statistics'); + $this->load->model('sale/order'); + + $this->model_report_statistics->editValue('order_processing', $this->model_sale_order->getTotalOrders(['filter_order_status' => implode(',', $this->config->get('config_processing_status'))])); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function orderComplete(): void { + $this->load->language('report/statistics'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'report/statistics')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('report/statistics'); + $this->load->model('sale/order'); + + $this->model_report_statistics->editValue('order_complete', $this->model_sale_order->getTotalOrders(['filter_order_status' => implode(',', $this->config->get('config_complete_status'))])); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function orderOther(): void { + $this->load->language('report/statistics'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'report/statistics')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('report/statistics'); + $this->load->model('localisation/order_status'); + + $order_status_data = []; + + $results = $this->model_localisation_order_status->getOrderStatuses(); + + foreach ($results as $result) { + if (!in_array($result['order_status_id'], array_merge($this->config->get('config_complete_status'), $this->config->get('config_processing_status')))) { + $order_status_data[] = $result['order_status_id']; + } + } + + $this->load->model('sale/order'); + + $this->model_report_statistics->editValue('order_other', $this->model_sale_order->getTotalOrders(['filter_order_status' => implode(',', $order_status_data)])); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function returns(): void { + $this->load->language('report/statistics'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'report/statistics')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('report/statistics'); + $this->load->model('sale/returns'); + + $this->model_report_statistics->editValue('return', $this->model_sale_returns->getTotalReturns(['filter_return_status_id' => $this->config->get('config_return_status_id')])); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function product(): void { + $this->load->language('report/statistics'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'report/statistics')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('report/statistics'); + $this->load->model('catalog/product'); + + $this->model_report_statistics->editValue('product', $this->model_catalog_product->getTotalProducts(['filter_quantity' => 0])); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function review(): void { + $this->load->language('report/statistics'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'report/statistics')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('report/statistics'); + $this->load->model('catalog/review'); + + $this->model_report_statistics->editValue('review', $this->model_catalog_review->getTotalReviewsAwaitingApproval()); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/sale/order.php b/admininistrator/controller/sale/order.php new file mode 100644 index 0000000..23d8743 --- /dev/null +++ b/admininistrator/controller/sale/order.php @@ -0,0 +1,1999 @@ +load->language('sale/order'); + + $this->document->setTitle($this->language->get('heading_title')); + + if (isset($this->request->get['filter_order_id'])) { + $filter_order_id = (int)$this->request->get['filter_order_id']; + } else { + $filter_order_id = ''; + } + + if (isset($this->request->get['filter_customer_id'])) { + $filter_customer_id = $this->request->get['filter_customer_id']; + } else { + $filter_customer_id = ''; + } + + if (isset($this->request->get['filter_customer'])) { + $filter_customer = $this->request->get['filter_customer']; + } else { + $filter_customer = ''; + } + + if (isset($this->request->get['filter_store_id'])) { + $filter_store_id = (int)$this->request->get['filter_store_id']; + } else { + $filter_store_id = ''; + } + + if (isset($this->request->get['filter_order_status'])) { + $filter_order_status = $this->request->get['filter_order_status']; + } else { + $filter_order_status = ''; + } + + if (isset($this->request->get['filter_order_status_id'])) { + $filter_order_status_id = (int)$this->request->get['filter_order_status_id']; + } else { + $filter_order_status_id = ''; + } + + if (isset($this->request->get['filter_total'])) { + $filter_total = $this->request->get['filter_total']; + } else { + $filter_total = ''; + } + + if (isset($this->request->get['filter_date_from'])) { + $filter_date_from = $this->request->get['filter_date_from']; + } else { + $filter_date_from = ''; + } + + if (isset($this->request->get['filter_date_to'])) { + $filter_date_to = $this->request->get['filter_date_to']; + } else { + $filter_date_to = ''; + } + + $url = ''; + + if (isset($this->request->get['filter_order_id'])) { + $url .= '&filter_order_id=' . $this->request->get['filter_order_id']; + } + + if (isset($this->request->get['filter_customer_id'])) { + $url .= '&filter_customer_id=' . (int)$this->request->get['filter_customer_id']; + } + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_store_id'])) { + $url .= '&filter_store_id=' . (int)$this->request->get['filter_store_id']; + } + + if (isset($this->request->get['filter_order_status'])) { + $url .= '&filter_order_status=' . $this->request->get['filter_order_status']; + } + + if (isset($this->request->get['filter_order_status_id'])) { + $url .= '&filter_order_status_id=' . (int)$this->request->get['filter_order_status_id']; + } + + if (isset($this->request->get['filter_total'])) { + $url .= '&filter_total=' . $this->request->get['filter_total']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('sale/order', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('sale/order.info', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('sale/order.delete', 'user_token=' . $this->session->data['user_token']); + $data['invoice'] = $this->url->link('sale/order.invoice', 'user_token=' . $this->session->data['user_token']); + $data['shipping'] = $this->url->link('sale/order.shipping', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['stores'] = []; + + $data['stores'][] = [ + 'store_id' => 0, + 'name' => $this->language->get('text_default') + ]; + + $this->load->model('setting/store'); + + $stores = $this->model_setting_store->getStores(); + + foreach ($stores as $store) { + $data['stores'][] = [ + 'store_id' => $store['store_id'], + 'name' => $store['name'] + ]; + } + + $this->load->model('localisation/order_status'); + + $data['order_statuses'] = $this->model_localisation_order_status->getOrderStatuses(); + + $data['filter_order_id'] = $filter_order_id; + $data['filter_customer_id'] = $filter_customer_id; + $data['filter_customer'] = $filter_customer; + $data['filter_store_id'] = $filter_store_id; + $data['filter_order_status'] = $filter_order_status; + $data['filter_order_status_id'] = $filter_order_status_id; + $data['filter_total'] = $filter_total; + $data['filter_date_from'] = $filter_date_from; + $data['filter_date_to'] = $filter_date_to; + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('sale/order', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('sale/order'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['filter_order_id'])) { + $filter_order_id = (int)$this->request->get['filter_order_id']; + } else { + $filter_order_id = ''; + } + + if (isset($this->request->get['filter_customer_id'])) { + $filter_customer_id = $this->request->get['filter_customer_id']; + } else { + $filter_customer_id = ''; + } + + if (isset($this->request->get['filter_customer'])) { + $filter_customer = $this->request->get['filter_customer']; + } else { + $filter_customer = ''; + } + + if (isset($this->request->get['filter_store_id'])) { + $filter_store_id = (int)$this->request->get['filter_store_id']; + } else { + $filter_store_id = ''; + } + + if (isset($this->request->get['filter_order_status'])) { + $filter_order_status = $this->request->get['filter_order_status']; + } else { + $filter_order_status = ''; + } + + if (isset($this->request->get['filter_order_status_id'])) { + $filter_order_status_id = (int)$this->request->get['filter_order_status_id']; + } else { + $filter_order_status_id = ''; + } + + if (isset($this->request->get['filter_total'])) { + $filter_total = $this->request->get['filter_total']; + } else { + $filter_total = ''; + } + + if (isset($this->request->get['filter_date_from'])) { + $filter_date_from = $this->request->get['filter_date_from']; + } else { + $filter_date_from = ''; + } + + if (isset($this->request->get['filter_date_to'])) { + $filter_date_to = $this->request->get['filter_date_to']; + } else { + $filter_date_to = ''; + } + + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'o.order_id'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'DESC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['filter_order_id'])) { + $url .= '&filter_order_id=' . $this->request->get['filter_order_id']; + } + + if (isset($this->request->get['filter_customer_id'])) { + $url .= '&filter_customer_id=' . (int)$this->request->get['filter_customer_id']; + } + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_store_id'])) { + $url .= '&filter_store_id=' . (int)$this->request->get['filter_store_id']; + } + + if (isset($this->request->get['filter_order_status'])) { + $url .= '&filter_order_status=' . $this->request->get['filter_order_status']; + } + + if (isset($this->request->get['filter_order_status_id'])) { + $url .= '&filter_order_status_id=' . (int)$this->request->get['filter_order_status_id']; + } + + if (isset($this->request->get['filter_total'])) { + $url .= '&filter_total=' . $this->request->get['filter_total']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('sale/order.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['orders'] = []; + + $filter_data = [ + 'filter_order_id' => $filter_order_id, + 'filter_customer_id' => $filter_customer_id, + 'filter_customer' => $filter_customer, + 'filter_store_id' => $filter_store_id, + 'filter_order_status' => $filter_order_status, + 'filter_order_status_id' => $filter_order_status_id, + 'filter_total' => $filter_total, + 'filter_date_from' => $filter_date_from, + 'filter_date_to' => $filter_date_to, + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * (int)$this->config->get('config_pagination_admin'), + 'limit' => (int)$this->config->get('config_pagination_admin') + ]; + + $this->load->model('sale/order'); + + $order_total = $this->model_sale_order->getTotalOrders($filter_data); + + $results = $this->model_sale_order->getOrders($filter_data); + + foreach ($results as $result) { + $data['orders'][] = [ + 'order_id' => $result['order_id'], + 'store_name' => $result['store_name'], + 'customer' => $result['customer'], + 'order_status' => $result['order_status'] ? $result['order_status'] : $this->language->get('text_missing'), + 'total' => $this->currency->format($result['total'], $result['currency_code'], $result['currency_value']), + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])), + 'date_modified' => date($this->language->get('date_format_short'), strtotime($result['date_modified'])), + 'shipping_method' => $result['shipping_method'], + 'view' => $this->url->link('sale/order.info', 'user_token=' . $this->session->data['user_token'] . '&order_id=' . $result['order_id'] . $url) + ]; + } + + $url = ''; + + if (isset($this->request->get['filter_order_id'])) { + $url .= '&filter_order_id=' . $this->request->get['filter_order_id']; + } + + if (isset($this->request->get['filter_customer_id'])) { + $url .= '&filter_customer_id=' . (int)$this->request->get['filter_customer_id']; + } + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_store_id'])) { + $url .= '&filter_store_id=' . (int)$this->request->get['filter_store_id']; + } + + if (isset($this->request->get['filter_order_status'])) { + $url .= '&filter_order_status=' . $this->request->get['filter_order_status']; + } + + if (isset($this->request->get['filter_order_status_id'])) { + $url .= '&filter_order_status_id=' . (int)$this->request->get['filter_order_status_id']; + } + + if (isset($this->request->get['filter_total'])) { + $url .= '&filter_total=' . $this->request->get['filter_total']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_order'] = $this->url->link('sale/order.list', 'user_token=' . $this->session->data['user_token'] . '&sort=o.order_id' . $url); + $data['sort_store_name'] = $this->url->link('sale/order.list', 'user_token=' . $this->session->data['user_token'] . '&sort=o.store_name' . $url); + $data['sort_customer'] = $this->url->link('sale/order.list', 'user_token=' . $this->session->data['user_token'] . '&sort=customer' . $url); + $data['sort_status'] = $this->url->link('sale/order.list', 'user_token=' . $this->session->data['user_token'] . '&sort=order_status' . $url); + $data['sort_total'] = $this->url->link('sale/order.list', 'user_token=' . $this->session->data['user_token'] . '&sort=o.total' . $url); + $data['sort_date_added'] = $this->url->link('sale/order.list', 'user_token=' . $this->session->data['user_token'] . '&sort=o.date_added' . $url); + $data['sort_date_modified'] = $this->url->link('sale/order.list', 'user_token=' . $this->session->data['user_token'] . '&sort=o.date_modified' . $url); + + $url = ''; + + if (isset($this->request->get['filter_order_id'])) { + $url .= '&filter_order_id=' . $this->request->get['filter_order_id']; + } + + if (isset($this->request->get['filter_customer_id'])) { + $url .= '&filter_customer_id=' . (int)$this->request->get['filter_customer_id']; + } + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_store_id'])) { + $url .= '&filter_store_id=' . (int)$this->request->get['filter_store_id']; + } + + if (isset($this->request->get['filter_order_status'])) { + $url .= '&filter_order_status=' . $this->request->get['filter_order_status']; + } + + if (isset($this->request->get['filter_order_status_id'])) { + $url .= '&filter_order_status_id=' . (int)$this->request->get['filter_order_status_id']; + } + + if (isset($this->request->get['filter_total'])) { + $url .= '&filter_total=' . $this->request->get['filter_total']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $order_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('sale/order.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($order_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($order_total - $this->config->get('config_pagination_admin'))) ? $order_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $order_total, ceil($order_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('sale/order_list', $data); + } + + /** + * @return void + * @throws \Exception + */ + public function info(): void { + $this->load->language('sale/order'); + + if (isset($this->request->get['order_id'])) { + $order_id = (int)$this->request->get['order_id']; + } else { + $order_id = 0; + } + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !$order_id ? $this->language->get('text_add') : sprintf($this->language->get('text_edit'), $order_id); + + $data['error_upload_size'] = sprintf($this->language->get('error_upload_size'), $this->config->get('config_file_max_size')); + + $data['config_file_max_size'] = ((int)$this->config->get('config_file_max_size') * 1024 * 1024); + $data['config_telephone_required'] = $this->config->get('config_telephone_required'); + + $url = ''; + + if (isset($this->request->get['filter_order_id'])) { + $url .= '&filter_order_id=' . $this->request->get['filter_order_id']; + } + + if (isset($this->request->get['filter_customer_id'])) { + $url .= '&filter_customer_id=' . (int)$this->request->get['filter_customer_id']; + } + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_store_id'])) { + $url .= '&filter_store_id=' . (int)$this->request->get['filter_store_id']; + } + + if (isset($this->request->get['filter_order_status'])) { + $url .= '&filter_order_status=' . $this->request->get['filter_order_status']; + } + + if (isset($this->request->get['filter_order_status_id'])) { + $url .= '&filter_order_status_id=' . (int)$this->request->get['filter_order_status_id']; + } + + if (isset($this->request->get['filter_total'])) { + $url .= '&filter_total=' . $this->request->get['filter_total']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('sale/order', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['shipping'] = $this->url->link('sale/order.shipping', 'user_token=' . $this->session->data['user_token'] . '&order_id=' . $order_id); + $data['invoice'] = $this->url->link('sale/order.invoice', 'user_token=' . $this->session->data['user_token'] . '&order_id=' . $order_id); + $data['back'] = $this->url->link('sale/order', 'user_token=' . $this->session->data['user_token'] . $url); + $data['upload'] = $this->url->link('tool/upload.upload', 'user_token=' . $this->session->data['user_token']); + $data['customer_add'] = $this->url->link('customer/customer.form', 'user_token=' . $this->session->data['user_token']); + + if ($order_id) { + $this->load->model('sale/order'); + + $order_info = $this->model_sale_order->getOrder($order_id); + } + + if (!empty($order_info)) { + $data['order_id'] = $order_info['order_id']; + } else { + $data['order_id'] = ''; + } + + // Invoice + if (!empty($order_info)) { + $data['invoice_no'] = $order_info['invoice_no']; + } else { + $data['invoice_no'] = ''; + } + + if (!empty($order_info)) { + $data['invoice_prefix'] = $order_info['invoice_prefix']; + } else { + $data['invoice_prefix'] = ''; + } + + // Customer + if (!empty($order_info)) { + $data['customer_id'] = $order_info['customer_id']; + } else { + $data['customer_id'] = 0; + } + + $this->load->model('customer/customer_group'); + + $data['customer_groups'] = $this->model_customer_customer_group->getCustomerGroups(); + + if (!empty($order_info)) { + $data['customer_group_id'] = $order_info['customer_group_id']; + } else { + $data['customer_group_id'] = $this->config->get('config_customer_group_id'); + } + + $customer_group_info = $this->model_customer_customer_group->getCustomerGroup($data['customer_group_id']); + + if ($customer_group_info) { + $data['customer_group'] = $customer_group_info['name']; + } else { + $data['customer_group'] = ''; + } + + if (!empty($order_info)) { + $data['firstname'] = $order_info['firstname']; + } else { + $data['firstname'] = ''; + } + + if (!empty($order_info)) { + $data['lastname'] = $order_info['lastname']; + } else { + $data['lastname'] = ''; + } + + if (!empty($order_info)) { + $data['email'] = $order_info['email']; + } else { + $data['email'] = ''; + } + + if (!empty($order_info)) { + $data['telephone'] = $order_info['telephone']; + } else { + $data['telephone'] = ''; + } + + if (!empty($order_info)) { + $data['account_custom_field'] = $order_info['custom_field']; + } else { + $data['account_custom_field'] = []; + } + + // Custom Fields + $data['custom_fields'] = []; + + $filter_data = [ + 'filter_status' => 1, + 'sort' => 'cf.sort_order', + 'order' => 'ASC' + ]; + + $this->load->model('customer/custom_field'); + + $custom_fields = $this->model_customer_custom_field->getCustomFields($filter_data); + + foreach ($custom_fields as $custom_field) { + $data['custom_fields'][] = [ + 'custom_field_id' => $custom_field['custom_field_id'], + 'custom_field_value' => $this->model_customer_custom_field->getValues($custom_field['custom_field_id']), + 'name' => $custom_field['name'], + 'value' => $custom_field['value'], + 'type' => $custom_field['type'], + 'location' => $custom_field['location'], + 'sort_order' => $custom_field['sort_order'] + ]; + } + + // Products + $data['order_products'] = []; + + $this->load->model('sale/order'); + $this->load->model('sale/subscription'); + $this->load->model('tool/upload'); + + $products = $this->model_sale_order->getProducts($order_id); + + foreach ($products as $product) { + $option_data = []; + + $options = $this->model_sale_order->getOptions($order_id, $product['order_product_id']); + + foreach ($options as $option) { + if ($option['type'] != 'file') { + $option_data[] = [ + 'name' => $option['name'], + 'value' => $option['value'], + 'type' => $option['type'] + ]; + } else { + $upload_info = $this->model_tool_upload->getUploadByCode($option['value']); + + if ($upload_info) { + $option_data[] = [ + 'name' => $option['name'], + 'value' => $upload_info['name'], + 'type' => $option['type'], + 'href' => $this->url->link('tool/upload.download', 'user_token=' . $this->session->data['user_token'] . '&code=' . $upload_info['code']) + ]; + } + } + } + + $description = ''; + + $subscription_info = $this->model_sale_order->getSubscription($order_id, $product['order_product_id']); + + if ($subscription_info) { + if ($subscription_info['trial_status']) { + $trial_price = $this->currency->format($subscription_info['trial_price'], $this->config->get('config_currency')); + $trial_cycle = $subscription_info['trial_cycle']; + $trial_frequency = $this->language->get('text_' . $subscription_info['trial_frequency']); + $trial_duration = $subscription_info['trial_duration']; + + $description .= sprintf($this->language->get('text_subscription_trial'), $trial_price, $trial_cycle, $trial_frequency, $trial_duration); + } + + $price = $this->currency->format($subscription_info['price'], $this->config->get('config_currency')); + $cycle = $subscription_info['cycle']; + $frequency = $this->language->get('text_' . $subscription_info['frequency']); + $duration = $subscription_info['duration']; + + if ($subscription_info['duration']) { + $description .= sprintf($this->language->get('text_subscription_duration'), $price, $cycle, $frequency, $duration); + } else { + $description .= sprintf($this->language->get('text_subscription_cancel'), $price, $cycle, $frequency); + } + } + + $subscription_info = $this->model_sale_subscription->getSubscriptionByOrderProductId($order_id, $product['order_product_id']); + + if ($subscription_info) { + $subscription = $this->url->link('sale/subscription.info', 'user_token=' . $this->session->data['user_token'] . '&subscription_id=' . $subscription_info['subscription_id']); + } else { + $subscription = ''; + } + + $data['order_products'][] = [ + 'order_product_id' => $product['order_product_id'], + 'product_id' => $product['product_id'], + 'name' => $product['name'], + 'model' => $product['model'], + 'option' => $option_data, + 'subscription' => $subscription, + 'subscription_description' => $description, + 'quantity' => $product['quantity'], + 'price' => $this->currency->format($product['price'] + ($this->config->get('config_tax') ? $product['tax'] : 0), $order_info['currency_code'], $order_info['currency_value']), + 'total' => $this->currency->format($product['total'] + ($this->config->get('config_tax') ? ($product['tax'] * $product['quantity']) : 0), $order_info['currency_code'], $order_info['currency_value']), + 'reward' => $product['reward'] + ]; + } + + // Vouchers + $data['order_vouchers'] = []; + + $vouchers = $this->model_sale_order->getVouchers($order_id); + + foreach ($vouchers as $voucher) { + $data['order_vouchers'][] = [ + 'description' => $voucher['description'], + 'amount' => $this->currency->format($voucher['amount'], $order_info['currency_code'], $order_info['currency_value']), + 'href' => $this->url->link('sale/voucher.form', 'user_token=' . $this->session->data['user_token'] . '&voucher_id=' . $voucher['voucher_id']) + ]; + } + + // Totals + $data['order_totals'] = []; + + $totals = $this->model_sale_order->getTotals($order_id); + + foreach ($totals as $total) { + $data['order_totals'][] = [ + 'title' => $total['title'], + 'text' => $this->currency->format($total['value'], $order_info['currency_code'], $order_info['currency_value']) + ]; + } + + // Delete any old session + if (isset($this->session->data['api_session'])) { + $session = new \Opencart\System\Library\Session($this->config->get('session_engine'), $this->registry); + $session->start($this->session->data['api_session']); + $session->destroy(); + } + + if (!empty($order_info)) { + $store_id = $order_info['store_id']; + } else { + $store_id = 0; + } + + if (!empty($order_info)) { + $language = $order_info['language_code']; + } else { + $language = $this->config->get('config_language'); + } + + // Create a store instance using loader class to call controllers, models, views, libraries + $this->load->model('setting/store'); + + $store = $this->model_setting_store->createStoreInstance($store_id, $language); + + // 2. Store the new session ID so we're not creating new session on every page load + $this->session->data['api_session'] = $store->session->getId(); + + // 3. To use the order API it requires an API ID. + $store->session->data['api_id'] = (int)$this->config->get('config_api_id'); + + if (!empty($order_info)) { + // 4. Add the request vars and remove the unneeded ones + $store->request->get = $this->request->get; + $store->request->post = $this->request->post; + + // 5. Load the order data + $store->request->get['route'] = 'api/sale/order.load'; + $store->request->get['language'] = $language; + + unset($store->request->get['user_token']); + unset($store->request->get['action']); + + $store->load->controller($store->request->get['route']); + } + + // Store + $data['stores'] = []; + + $data['stores'][] = [ + 'store_id' => 0, + 'name' => $this->config->get('config_name') + ]; + + $this->load->model('setting/store'); + + $results = $this->model_setting_store->getStores(); + + foreach ($results as $result) { + $data['stores'][] = [ + 'store_id' => $result['store_id'], + 'name' => $result['name'] + ]; + } + + if (!empty($order_info)) { + $data['store_id'] = $order_info['store_id']; + } else { + $data['store_id'] = $this->config->get('config_store_id'); + } + + // Language + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (!empty($order_info)) { + $data['language_code'] = $order_info['language_code']; + } else { + $data['language_code'] = $this->config->get('config_language'); + } + + // Voucher themes + $this->load->model('sale/voucher_theme'); + + $data['voucher_themes'] = $this->model_sale_voucher_theme->getVoucherThemes(); + + // Currency + $this->load->model('localisation/currency'); + + $data['currencies'] = $this->model_localisation_currency->getCurrencies(); + + if (!empty($order_info)) { + $data['currency_code'] = $order_info['currency_code']; + } else { + $data['currency_code'] = $this->config->get('config_currency'); + } + + // Coupon, Voucher, Reward + $data['total_coupon'] = ''; + $data['total_voucher'] = ''; + $data['total_reward'] = 0; + + if ($order_id) { + $order_totals = $this->model_sale_order->getTotals($order_id); + + foreach ($order_totals as $order_total) { + // If coupon, voucher or reward points + $start = strpos($order_total['title'], '(') + 1; + $end = strrpos($order_total['title'], ')'); + + if ($start && $end) { + $data['total_' . $order_total['code']] = substr($order_total['title'], $start, $end - $start); + } + } + } + + // Reward Points + if (!empty($order_info)) { + $data['points'] = $this->model_sale_order->getRewardTotal($order_id); + } else { + $data['points'] = 0; + } + + // Reward Points + if (!empty($order_info)) { + $data['reward_total'] = $this->model_customer_customer->getTotalRewardsByOrderId($order_id); + } else { + $data['reward_total'] = 0; + } + + // Affiliate + if (!empty($order_info)) { + $data['affiliate_id'] = $order_info['affiliate_id']; + } else { + $data['affiliate_id'] = 0; + } + + if (!empty($order_info)) { + $data['affiliate'] = $order_info['affiliate']; + } else { + $data['affiliate'] = ''; + } + + // Commission + if (!empty($order_info) && (float)$order_info['commission']) { + $data['commission'] = $this->currency->format($order_info['commission'], $this->config->get('config_currency')); + } else { + $data['commission'] = ''; + } + + if (!empty($order_info)) { + $data['commission_total'] = $this->model_customer_customer->getTotalTransactionsByOrderId($order_id); + } else { + $data['commission_total'] = ''; + } + + // Addresses + if (!empty($order_info)) { + $this->load->model('customer/customer'); + + $data['addresses'] = $this->model_customer_customer->getAddresses($order_info['customer_id']); + } else { + $data['addresses'] = []; + } + + // Payment Address + if (!empty($order_info)) { + $data['payment_address_id'] = $order_info['payment_address_id']; + } else { + $data['payment_address_id'] = 0; + } + + if (!empty($order_info)) { + $data['payment_firstname'] = $order_info['payment_firstname']; + } else { + $data['payment_firstname'] = ''; + } + + if (!empty($order_info)) { + $data['payment_lastname'] = $order_info['payment_lastname']; + } else { + $data['payment_lastname'] = ''; + } + + if (!empty($order_info)) { + $data['payment_company'] = $order_info['payment_company']; + } else { + $data['payment_company'] = ''; + } + + if (!empty($order_info)) { + $data['payment_address_1'] = $order_info['payment_address_1']; + } else { + $data['payment_address_1'] = ''; + } + + if (!empty($order_info)) { + $data['payment_address_2'] = $order_info['payment_address_2']; + } else { + $data['payment_address_2'] = ''; + } + + if (!empty($order_info)) { + $data['payment_city'] = $order_info['payment_city']; + } else { + $data['payment_city'] = ''; + } + + if (!empty($order_info)) { + $data['payment_postcode'] = $order_info['payment_postcode']; + } else { + $data['payment_postcode'] = ''; + } + + // Countries + $this->load->model('localisation/country'); + + $data['countries'] = $this->model_localisation_country->getCountries(); + + if (!empty($order_info)) { + $data['payment_country_id'] = $order_info['payment_country_id']; + } else { + $data['payment_country_id'] = 0; + } + + if (!empty($order_info)) { + $data['payment_country'] = $order_info['payment_country']; + } else { + $data['payment_country'] = ''; + } + + if (!empty($order_info)) { + $data['payment_zone_id'] = $order_info['payment_zone_id']; + } else { + $data['payment_zone_id'] = 0; + } + + if (!empty($order_info)) { + $data['payment_zone'] = $order_info['payment_zone']; + } else { + $data['payment_zone'] = ''; + } + + if (!empty($order_info)) { + $data['payment_custom_field'] = $order_info['payment_custom_field']; + } else { + $data['payment_custom_field'] = []; + } + + // Payment Method + if (isset($order_info['payment_method']['name'])) { + $data['payment_method'] = $order_info['payment_method']['name']; + } else { + $data['payment_method'] = ''; + } + + if (isset($order_info['payment_method']['code'])) { + $data['payment_code'] = $order_info['payment_method']['code']; + } else { + $data['payment_code'] = ''; + } + + // Shipping Address + if (!empty($order_info)) { + $data['shipping_address_id'] = $order_info['shipping_address_id']; + } else { + $data['shipping_address_id'] = 0; + } + + if (!empty($order_info)) { + $data['shipping_firstname'] = $order_info['shipping_firstname']; + } else { + $data['shipping_firstname'] = ''; + } + + if (!empty($order_info)) { + $data['shipping_lastname'] = $order_info['shipping_lastname']; + } else { + $data['shipping_lastname'] = ''; + } + + if (!empty($order_info)) { + $data['shipping_company'] = $order_info['shipping_company']; + } else { + $data['shipping_company'] = ''; + } + + if (!empty($order_info)) { + $data['shipping_address_1'] = $order_info['shipping_address_1']; + } else { + $data['shipping_address_1'] = ''; + } + + if (!empty($order_info)) { + $data['shipping_address_2'] = $order_info['shipping_address_2']; + } else { + $data['shipping_address_2'] = ''; + } + + if (!empty($order_info)) { + $data['shipping_city'] = $order_info['shipping_city']; + } else { + $data['shipping_city'] = ''; + } + + if (!empty($order_info)) { + $data['shipping_postcode'] = $order_info['shipping_postcode']; + } else { + $data['shipping_postcode'] = ''; + } + + if (!empty($order_info)) { + $data['shipping_country_id'] = $order_info['shipping_country_id']; + } else { + $data['shipping_country_id'] = 0; + } + + if (!empty($order_info)) { + $data['shipping_country'] = $order_info['shipping_country']; + } else { + $data['shipping_country'] = ''; + } + + if (!empty($order_info)) { + $data['shipping_zone_id'] = $order_info['shipping_zone_id']; + } else { + $data['shipping_zone_id'] = 0; + } + + if (!empty($order_info)) { + $data['shipping_zone'] = $order_info['shipping_zone']; + } else { + $data['shipping_zone'] = ''; + } + + if (!empty($order_info)) { + $data['shipping_custom_field'] = $order_info['shipping_custom_field']; + } else { + $data['shipping_custom_field'] = []; + } + + // Shipping method + if (isset($order_info['shipping_method']['name'])) { + $data['shipping_method'] = $order_info['shipping_method']['name']; + } else { + $data['shipping_method'] = ''; + } + + if (isset($order_info['shipping_method']['code'])) { + $data['shipping_code'] = $order_info['shipping_method']['code']; + } else { + $data['shipping_code'] = ''; + } + + // Comment + if (!empty($order_info)) { + $data['comment'] = nl2br($order_info['comment']); + } else { + $data['comment'] = ''; + } + + // Totals + $data['order_totals'] = []; + + if (!empty($order_info)) { + $totals = $this->model_sale_order->getTotals($order_id); + + foreach ($totals as $total) { + $data['order_totals'][] = [ + 'title' => $total['title'], + 'text' => $this->currency->format($total['value'], $order_info['currency_code'], $order_info['currency_value']) + ]; + } + } + + // Order Status + $this->load->model('localisation/order_status'); + + $data['order_statuses'] = $this->model_localisation_order_status->getOrderStatuses(); + + if (!empty($order_info)) { + $data['order_status_id'] = $order_info['order_status_id']; + } else { + $data['order_status_id'] = $this->config->get('config_order_status_id'); + } + + // Additional tabs that are payment gateway specific + $data['tabs'] = []; + + // Extension Order Tabs can are called here. + $this->load->model('setting/extension'); + + if (!empty($order_info['payment_method']['code'])) { + if (isset($order_info['payment_method']['code'])) { + $code = oc_substr($order_info['payment_method']['code'], 0, strpos($order_info['payment_method']['code'], '.')); + } else { + $code = ''; + } + + $extension_info = $this->model_setting_extension->getExtensionByCode('payment', $code); + + if ($extension_info && $this->user->hasPermission('access', 'extension/' . $extension_info['extension'] . '/payment/' . $extension_info['code'])) { + $output = $this->load->controller('extension/' . $extension_info['extension'] . '/payment/' . $extension_info['code'] . '.order'); + + if (!$output instanceof \Exception) { + $this->load->language('extension/' . $extension_info['extension'] . '/payment/' . $extension_info['code'], 'extension'); + + $data['tabs'][] = [ + 'code' => $extension_info['code'], + 'title' => $this->language->get('extension_heading_title'), + 'content' => $output + ]; + } + } + } + + // Extension Order Tabs can are called here. + $this->load->model('setting/extension'); + + $extensions = $this->model_setting_extension->getExtensionsByType('fraud'); + + foreach ($extensions as $extension) { + if ($this->config->get('fraud_' . $extension['code'] . '_status')) { + $this->load->language('extension/' . $extension['extension'] . '/fraud/' . $extension['code'], 'extension'); + + $output = $this->load->controller('extension/' . $extension['extension'] . '/fraud/' . $extension['code'] . '.order'); + + if (!$output instanceof \Exception) { + $data['tabs'][] = [ + 'code' => $extension['extension'], + 'title' => $this->language->get('extension_heading_title'), + 'content' => $output + ]; + } + } + } + + // Additional information + if (!empty($order_info)) { + $data['ip'] = $order_info['ip']; + $data['forwarded_ip'] = $order_info['forwarded_ip']; + $data['user_agent'] = $order_info['user_agent']; + $data['accept_language'] = $order_info['accept_language']; + $data['date_added'] = date($this->language->get('date_format_short'), strtotime($order_info['date_added'])); + $data['date_modified'] = date($this->language->get('date_format_short'), strtotime($order_info['date_modified'])); + } else { + $data['ip'] = ''; + $data['forwarded_ip'] = ''; + $data['user_agent'] = ''; + $data['accept_language'] = ''; + $data['date_added'] = date($this->language->get('date_format_short'), time()); + $data['date_modified'] = date($this->language->get('date_format_short'), time()); + } + + // Histories + $data['history'] = $this->getHistory(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('sale/order_info', $data)); + } + + // Method to call the store front API and return a response. + + /** + * @return void + */ + public function call(): void { + $this->load->language('sale/order'); + + $json = []; + + if (isset($this->request->get['store_id'])) { + $store_id = (int)$this->request->get['store_id']; + } else { + $store_id = 0; + } + + if (isset($this->request->get['language'])) { + $language = $this->request->get['language']; + } else { + $language = $this->config->get('config_language'); + } + + if (isset($this->request->get['action'])) { + $action = $this->request->get['action']; + } else { + $action = ''; + } + + if (isset($this->session->data['api_session'])) { + $session_id = $this->session->data['api_session']; + } else { + $session_id = ''; + } + + if (!$this->user->hasPermission('modify', 'sale/order')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if (!$json) { + // 1. Create a store instance using loader class to call controllers, models, views, libraries + $this->load->model('setting/store'); + + $store = $this->model_setting_store->createStoreInstance($store_id, $language, $session_id); + + // 2. Add the request vars and remove the unneeded ones + $store->request->get = $this->request->get; + $store->request->post = $this->request->post; + + $store->request->get['route'] = 'api/' . $action; + + // 3. Remove the unneeded keys + unset($store->request->get['action']); + unset($store->request->get['user_token']); + + // Call the required API controller + $store->load->controller($store->request->get['route']); + + $output = $store->response->getOutput(); + } else { + $output = json_encode($json); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput($output); + } + + /** + * @return void + */ + public function invoice(): void { + $this->load->language('sale/order'); + + $data['title'] = $this->language->get('text_invoice'); + + $data['base'] = HTTP_SERVER; + $data['direction'] = $this->language->get('direction'); + $data['lang'] = $this->language->get('code'); + + // Hard coding css so they can be replaced via the events system. + $data['bootstrap_css'] = 'view/stylesheet/bootstrap.css'; + $data['icons'] = 'view/stylesheet/fonts/fontawesome/css/all.min.css'; + $data['stylesheet'] = 'view/stylesheet/stylesheet.css'; + + // Hard coding scripts so they can be replaced via the events system. + $data['jquery'] = 'view/javascript/jquery/jquery-3.7.1.min.js'; + $data['bootstrap_js'] = 'view/javascript/bootstrap/js/bootstrap.bundle.min.js'; + + $this->load->model('sale/order'); + $this->load->model('setting/setting'); + $this->load->model('tool/upload'); + $this->load->model('sale/subscription'); + + $data['orders'] = []; + + $orders = []; + + if (isset($this->request->post['selected'])) { + $orders = $this->request->post['selected']; + } + + if (isset($this->request->get['order_id'])) { + $orders[] = (int)$this->request->get['order_id']; + } + + foreach ($orders as $order_id) { + $order_info = $this->model_sale_order->getOrder($order_id); + + if ($order_info) { + $store_info = $this->model_setting_setting->getSetting('config', $order_info['store_id']); + + if ($store_info) { + $store_address = $store_info['config_address']; + $store_email = $store_info['config_email']; + $store_telephone = $store_info['config_telephone']; + } else { + $store_address = $this->config->get('config_address'); + $store_email = $this->config->get('config_email'); + $store_telephone = $this->config->get('config_telephone'); + } + + if ($order_info['invoice_no']) { + $invoice_no = $order_info['invoice_prefix'] . $order_info['invoice_no']; + } else { + $invoice_no = ''; + } + + // Payment Address + if ($order_info['payment_address_format']) { + $format = $order_info['payment_address_format']; + } else { + $format = '{firstname} {lastname}' . "\n" . '{company}' . "\n" . '{address_1}' . "\n" . '{address_2}' . "\n" . '{city} {postcode}' . "\n" . '{zone}' . "\n" . '{country}'; + } + + $find = [ + '{firstname}', + '{lastname}', + '{company}', + '{address_1}', + '{address_2}', + '{city}', + '{postcode}', + '{zone}', + '{zone_code}', + '{country}' + ]; + + $replace = [ + 'firstname' => $order_info['payment_firstname'], + 'lastname' => $order_info['payment_lastname'], + 'company' => $order_info['payment_company'], + 'address_1' => $order_info['payment_address_1'], + 'address_2' => $order_info['payment_address_2'], + 'city' => $order_info['payment_city'], + 'postcode' => $order_info['payment_postcode'], + 'zone' => $order_info['payment_zone'], + 'zone_code' => $order_info['payment_zone_code'], + 'country' => $order_info['payment_country'] + ]; + + $payment_address = str_replace(["\r\n", "\r", "\n"], '
', preg_replace(["/\s\s+/", "/\r\r+/", "/\n\n+/"], '
', trim(str_replace($find, $replace, $format)))); + + // Shipping Address + if ($order_info['shipping_address_format']) { + $format = $order_info['shipping_address_format']; + } else { + $format = '{firstname} {lastname}' . "\n" . '{company}' . "\n" . '{address_1}' . "\n" . '{address_2}' . "\n" . '{city} {postcode}' . "\n" . '{zone}' . "\n" . '{country}'; + } + + $find = [ + '{firstname}', + '{lastname}', + '{company}', + '{address_1}', + '{address_2}', + '{city}', + '{postcode}', + '{zone}', + '{zone_code}', + '{country}' + ]; + + $replace = [ + 'firstname' => $order_info['shipping_firstname'], + 'lastname' => $order_info['shipping_lastname'], + 'company' => $order_info['shipping_company'], + 'address_1' => $order_info['shipping_address_1'], + 'address_2' => $order_info['shipping_address_2'], + 'city' => $order_info['shipping_city'], + 'postcode' => $order_info['shipping_postcode'], + 'zone' => $order_info['shipping_zone'], + 'zone_code' => $order_info['shipping_zone_code'], + 'country' => $order_info['shipping_country'] + ]; + + $shipping_address = str_replace(["\r\n", "\r", "\n"], '
', preg_replace(["/\s\s+/", "/\r\r+/", "/\n\n+/"], '
', trim(str_replace($find, $replace, $format)))); + + $product_data = []; + + $products = $this->model_sale_order->getProducts($order_id); + + foreach ($products as $product) { + $option_data = []; + + $options = $this->model_sale_order->getOptions($order_id, $product['order_product_id']); + + foreach ($options as $option) { + if ($option['type'] != 'file') { + $value = $option['value']; + } else { + $upload_info = $this->model_tool_upload->getUploadByCode($option['value']); + + if ($upload_info) { + $value = $upload_info['name']; + } else { + $value = ''; + } + } + + $option_data[] = [ + 'name' => $option['name'], + 'value' => $value + ]; + } + + // Subscription + $description = ''; + + $subscription_info = $this->model_sale_order->getSubscription($order_id, $product['order_product_id']); + + if ($subscription_info) { + if ($subscription_info['trial_status']) { + $trial_price = $this->currency->format($subscription_info['trial_price'], $this->config->get('config_currency')); + $trial_cycle = $subscription_info['trial_cycle']; + $trial_frequency = $this->language->get('text_' . $subscription_info['trial_frequency']); + $trial_duration = $subscription_info['trial_duration']; + + $description .= sprintf($this->language->get('text_subscription_trial'), $trial_price, $trial_cycle, $trial_frequency, $trial_duration); + } + + $price = $this->currency->format($subscription_info['price'], $this->config->get('config_currency')); + $cycle = $subscription_info['cycle']; + $frequency = $this->language->get('text_' . $subscription_info['frequency']); + $duration = $subscription_info['duration']; + + if ($subscription_info['duration']) { + $description .= sprintf($this->language->get('text_subscription_duration'), $price, $cycle, $frequency, $duration); + } else { + $description .= sprintf($this->language->get('text_subscription_cancel'), $price, $cycle, $frequency); + } + } + + $product_data[] = [ + 'name' => $product['name'], + 'model' => $product['model'], + 'option' => $option_data, + 'subscription' => $description, + 'quantity' => $product['quantity'], + 'price' => $this->currency->format($product['price'] + ($this->config->get('config_tax') ? $product['tax'] : 0), $order_info['currency_code'], $order_info['currency_value']), + 'total' => $this->currency->format($product['total'] + ($this->config->get('config_tax') ? ($product['tax'] * $product['quantity']) : 0), $order_info['currency_code'], $order_info['currency_value']) + ]; + } + + $voucher_data = []; + + $vouchers = $this->model_sale_order->getVouchers($order_id); + + foreach ($vouchers as $voucher) { + $voucher_data[] = [ + 'description' => $voucher['description'], + 'amount' => $this->currency->format($voucher['amount'], $order_info['currency_code'], $order_info['currency_value']) + ]; + } + + $total_data = []; + + $totals = $this->model_sale_order->getTotals($order_id); + + foreach ($totals as $total) { + $total_data[] = [ + 'title' => $total['title'], + 'text' => $this->currency->format($total['value'], $order_info['currency_code'], $order_info['currency_value']) + ]; + } + + $data['orders'][] = [ + 'order_id' => $order_id, + 'invoice_no' => $invoice_no, + 'date_added' => date($this->language->get('date_format_short'), strtotime($order_info['date_added'])), + 'store_name' => $order_info['store_name'], + 'store_url' => rtrim($order_info['store_url'], '/'), + 'store_address' => nl2br($store_address), + 'store_email' => $store_email, + 'store_telephone' => $store_telephone, + 'email' => $order_info['email'], + 'telephone' => $order_info['telephone'], + 'shipping_address' => $shipping_address, + 'shipping_method' => ($order_info['shipping_method'] ? $order_info['shipping_method']['name'] : ''), + 'payment_address' => $payment_address, + 'payment_method' => $order_info['payment_method']['name'], + 'product' => $product_data, + 'voucher' => $voucher_data, + 'total' => $total_data, + 'comment' => nl2br($order_info['comment']) + ]; + } + } + + $this->response->setOutput($this->load->view('sale/order_invoice', $data)); + } + + /** + * @return void + */ + public function shipping(): void { + $this->load->language('sale/order'); + + $data['title'] = $this->language->get('text_shipping'); + + $data['base'] = HTTP_SERVER; + $data['direction'] = $this->language->get('direction'); + $data['lang'] = $this->language->get('code'); + + // Hard coding CSS so they can be replaced via the events system. + $data['bootstrap_css'] = 'view/stylesheet/bootstrap.css'; + $data['icons'] = 'view/stylesheet/fonts/fontawesome/css/all.min.css'; + $data['stylesheet'] = 'view/stylesheet/stylesheet.css'; + + // Hard coding scripts so they can be replaced via the events system. + $data['jquery'] = 'view/javascript/jquery/jquery-3.7.1.min.js'; + $data['bootstrap_js'] = 'view/javascript/bootstrap/js/bootstrap.bundle.min.js'; + + $this->load->model('sale/order'); + $this->load->model('catalog/product'); + $this->load->model('setting/setting'); + $this->load->model('tool/upload'); + $this->load->model('sale/subscription'); + + $data['orders'] = []; + + $orders = []; + + if (isset($this->request->post['selected'])) { + $orders = $this->request->post['selected']; + } + + if (isset($this->request->get['order_id'])) { + $orders[] = (int)$this->request->get['order_id']; + } + + foreach ($orders as $order_id) { + $order_info = $this->model_sale_order->getOrder($order_id); + + // Make sure there is a shipping method + if ($order_info && $order_info['shipping_method']) { + $store_info = $this->model_setting_setting->getSetting('config', $order_info['store_id']); + + if ($store_info) { + $store_address = $store_info['config_address']; + $store_email = $store_info['config_email']; + $store_telephone = $store_info['config_telephone']; + } else { + $store_address = $this->config->get('config_address'); + $store_email = $this->config->get('config_email'); + $store_telephone = $this->config->get('config_telephone'); + } + + if ($order_info['invoice_no']) { + $invoice_no = $order_info['invoice_prefix'] . $order_info['invoice_no']; + } else { + $invoice_no = ''; + } + + // Shipping Address + if ($order_info['shipping_address_format']) { + $format = $order_info['shipping_address_format']; + } else { + $format = '{firstname} {lastname}' . "\n" . '{company}' . "\n" . '{address_1}' . "\n" . '{address_2}' . "\n" . '{city} {postcode}' . "\n" . '{zone}' . "\n" . '{country}'; + } + + $find = [ + '{firstname}', + '{lastname}', + '{company}', + '{address_1}', + '{address_2}', + '{city}', + '{postcode}', + '{zone}', + '{zone_code}', + '{country}' + ]; + + $replace = [ + 'firstname' => $order_info['shipping_firstname'], + 'lastname' => $order_info['shipping_lastname'], + 'company' => $order_info['shipping_company'], + 'address_1' => $order_info['shipping_address_1'], + 'address_2' => $order_info['shipping_address_2'], + 'city' => $order_info['shipping_city'], + 'postcode' => $order_info['shipping_postcode'], + 'zone' => $order_info['shipping_zone'], + 'zone_code' => $order_info['shipping_zone_code'], + 'country' => $order_info['shipping_country'] + ]; + + $shipping_address = str_replace(["\r\n", "\r", "\n"], '
', preg_replace(["/\s\s+/", "/\r\r+/", "/\n\n+/"], '
', trim(str_replace($find, $replace, $format)))); + + $product_data = []; + + $products = $this->model_sale_order->getProducts($order_id); + + foreach ($products as $product) { + $option_weight = 0; + + $product_info = $this->model_catalog_product->getProduct($product['product_id']); + + if ($product_info) { + $option_data = []; + + $options = $this->model_sale_order->getOptions($order_id, $product['order_product_id']); + + foreach ($options as $option) { + if ($option['type'] != 'file') { + $value = $option['value']; + } else { + $upload_info = $this->model_tool_upload->getUploadByCode($option['value']); + + if ($upload_info) { + $value = $upload_info['name']; + } else { + $value = ''; + } + } + + $option_data[] = [ + 'name' => $option['name'], + 'value' => $value + ]; + + $product_option_value_info = $this->model_catalog_product->getOptionValue($product['product_id'], $option['product_option_value_id']); + + if (!empty($product_option_value_info['weight'])) { + if ($product_option_value_info['weight_prefix'] == '+') { + $option_weight += $product_option_value_info['weight']; + } elseif ($product_option_value_info['weight_prefix'] == '-') { + $option_weight -= $product_option_value_info['weight']; + } + } + } + + $product_data[] = [ + 'name' => $product_info['name'], + 'model' => $product_info['model'], + 'option' => $option_data, + 'quantity' => $product['quantity'], + 'location' => $product_info['location'], + 'sku' => $product_info['sku'], + 'upc' => $product_info['upc'], + 'ean' => $product_info['ean'], + 'jan' => $product_info['jan'], + 'isbn' => $product_info['isbn'], + 'mpn' => $product_info['mpn'], + 'weight' => $this->weight->format(($product_info['weight'] + (float)$option_weight) * $product['quantity'], $product_info['weight_class_id'], $this->language->get('decimal_point'), $this->language->get('thousand_point')) + ]; + } + } + + $data['orders'][] = [ + 'order_id' => $order_id, + 'invoice_no' => $invoice_no, + 'date_added' => date($this->language->get('date_format_short'), strtotime($order_info['date_added'])), + 'store_name' => $order_info['store_name'], + 'store_url' => rtrim($order_info['store_url'], '/'), + 'store_address' => nl2br($store_address), + 'store_email' => $store_email, + 'store_telephone' => $store_telephone, + 'email' => $order_info['email'], + 'telephone' => $order_info['telephone'], + 'shipping_address' => $shipping_address, + 'shipping_method' => $order_info['shipping_method']['name'], + 'product' => $product_data, + 'comment' => nl2br($order_info['comment']) + ]; + } + } + + $this->response->setOutput($this->load->view('sale/order_shipping', $data)); + } + + /** + * @return void + */ + public function history(): void { + $this->load->language('sale/order'); + + $this->response->setOutput($this->getHistory()); + } + + /** + * @return string + */ + public function getHistory(): string { + if (isset($this->request->get['order_id'])) { + $order_id = (int)$this->request->get['order_id']; + } else { + $order_id = 0; + } + + if (isset($this->request->get['page']) && $this->request->get['route'] == 'sale/order.history') { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $limit = 10; + + $data['histories'] = []; + + $this->load->model('sale/order'); + + $results = $this->model_sale_order->getHistories($order_id, ($page - 1) * $limit, $limit); + + foreach ($results as $result) { + $data['histories'][] = [ + 'status' => $result['status'], + 'comment' => nl2br($result['comment']), + 'notify' => $result['notify'] ? $this->language->get('text_yes') : $this->language->get('text_no'), + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])) + ]; + } + + $history_total = $this->model_sale_order->getTotalHistories($order_id); + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $history_total, + 'page' => $page, + 'limit' => $limit, + 'url' => $this->url->link('sale/order.history', 'user_token=' . $this->session->data['user_token'] . '&order_id=' . $order_id . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($history_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($history_total - $limit)) ? $history_total : ((($page - 1) * $limit) + $limit), $history_total, ceil($history_total / $limit)); + + return $this->load->view('sale/order_history', $data); + } + + /** + * @return void + */ + public function createInvoiceNo(): void { + $this->load->language('sale/order'); + + $json = []; + + if (isset($this->request->get['order_id'])) { + $order_id = (int)$this->request->get['order_id']; + } else { + $order_id = 0; + } + + if (!$this->user->hasPermission('modify', 'sale/order')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('sale/order'); + + $order_info = $this->model_sale_order->getOrder($order_id); + + if ($order_info) { + if ($order_info['invoice_no']) { + $json['error'] = $this->language->get('error_invoice_no'); + } + } else { + $json['error'] = $this->language->get('error_order'); + } + + if (!$json) { + $json['success'] = $this->language->get('text_success'); + + $this->load->model('sale/order'); + + $json['invoice_no'] = $this->model_sale_order->createInvoiceNo($order_id); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function addReward(): void { + $this->load->language('sale/order'); + + $json = []; + + if (isset($this->request->get['order_id'])) { + $order_id = (int)$this->request->get['order_id']; + } else { + $order_id = 0; + } + + if (!$this->user->hasPermission('modify', 'sale/order')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('sale/order'); + + $order_info = $this->model_sale_order->getOrder($order_id); + + if ($order_info) { + if (!$order_info['customer_id']) { + $json['error'] = $this->language->get('error_customer'); + } + } else { + $json['error'] = $this->language->get('error_order'); + } + + $this->load->model('customer/customer'); + + $reward_total = $this->model_customer_customer->getTotalRewardsByOrderId($order_id); + + if ($reward_total) { + $json['error'] = $this->language->get('error_reward_add'); + } + + if (!$json) { + $this->model_customer_customer->addReward($order_info['customer_id'], $this->language->get('text_order_id') . ' #' . $order_id, $order_info['reward'], $order_id); + + $json['success'] = $this->language->get('text_reward_add'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function removeReward(): void { + $this->load->language('sale/order'); + + $json = []; + + if (isset($this->request->get['order_id'])) { + $order_id = (int)$this->request->get['order_id']; + } else { + $order_id = 0; + } + + if (!$this->user->hasPermission('modify', 'sale/order')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('sale/order'); + + $order_info = $this->model_sale_order->getOrder($order_id); + + if (!$order_info) { + $json['error'] = $this->language->get('error_order'); + } + + if (!$json) { + $this->load->model('customer/customer'); + + $this->model_customer_customer->deleteReward($order_id); + + $json['success'] = $this->language->get('text_reward_remove'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function addCommission(): void { + $this->load->language('sale/order'); + + $json = []; + + if (isset($this->request->get['order_id'])) { + $order_id = (int)$this->request->get['order_id']; + } else { + $order_id = 0; + } + + if (!$this->user->hasPermission('modify', 'sale/order')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('sale/order'); + + $order_info = $this->model_sale_order->getOrder($order_id); + + if ($order_info) { + $this->load->model('customer/customer'); + + $customer_info = $this->model_customer_customer->getCustomer($order_info['affiliate_id']); + + if (!$customer_info) { + $json['error'] = $this->language->get('error_affiliate'); + } + + $affiliate_total = $this->model_customer_customer->getTotalTransactionsByOrderId($order_id); + + if ($affiliate_total) { + $json['error'] = $this->language->get('error_commission_add'); + } + } else { + $json['error'] = $this->language->get('error_order'); + } + + if (!$json) { + $this->model_customer_customer->addTransaction($order_info['affiliate_id'], $this->language->get('text_order_id') . ' #' . $order_id, $order_info['commission'], $order_id); + + $json['success'] = $this->language->get('text_commission_add'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function removeCommission(): void { + $this->load->language('sale/order'); + + $json = []; + + if (isset($this->request->get['order_id'])) { + $order_id = (int)$this->request->get['order_id']; + } else { + $order_id = 0; + } + + if (!$this->user->hasPermission('modify', 'sale/order')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('sale/order'); + + $order_info = $this->model_sale_order->getOrder($order_id); + + if (!$order_info) { + $json['error'] = $this->language->get('error_order'); + } + + if (!$json) { + $this->load->model('customer/customer'); + + $this->model_customer_customer->deleteTransactionByOrderId($order_id); + + $json['success'] = $this->language->get('text_commission_remove'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/sale/returns.php b/admininistrator/controller/sale/returns.php new file mode 100644 index 0000000..a67490b --- /dev/null +++ b/admininistrator/controller/sale/returns.php @@ -0,0 +1,815 @@ +load->language('sale/returns'); + + $this->document->setTitle($this->language->get('heading_title')); + + if (isset($this->request->get['filter_return_id'])) { + $filter_return_id = (int)$this->request->get['filter_return_id']; + } else { + $filter_return_id = ''; + } + + if (isset($this->request->get['filter_order_id'])) { + $filter_order_id = (int)$this->request->get['filter_order_id']; + } else { + $filter_order_id = ''; + } + + if (isset($this->request->get['filter_customer'])) { + $filter_customer = $this->request->get['filter_customer']; + } else { + $filter_customer = ''; + } + + if (isset($this->request->get['filter_product'])) { + $filter_product = $this->request->get['filter_product']; + } else { + $filter_product = ''; + } + + if (isset($this->request->get['filter_model'])) { + $filter_model = $this->request->get['filter_model']; + } else { + $filter_model = ''; + } + + if (isset($this->request->get['filter_return_status_id'])) { + $filter_return_status_id = (int)$this->request->get['filter_return_status_id']; + } else { + $filter_return_status_id = ''; + } + + if (isset($this->request->get['filter_date_from'])) { + $filter_date_from = $this->request->get['filter_date_from']; + } else { + $filter_date_from = ''; + } + + if (isset($this->request->get['filter_date_to'])) { + $filter_date_to = $this->request->get['filter_date_to']; + } else { + $filter_date_to = ''; + } + + $url = ''; + + if (isset($this->request->get['filter_return_id'])) { + $url .= '&filter_return_id=' . $this->request->get['filter_return_id']; + } + + if (isset($this->request->get['filter_order_id'])) { + $url .= '&filter_order_id=' . $this->request->get['filter_order_id']; + } + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_product'])) { + $url .= '&filter_product=' . urlencode(html_entity_decode($this->request->get['filter_product'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_model'])) { + $url .= '&filter_model=' . urlencode(html_entity_decode($this->request->get['filter_model'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_return_status_id'])) { + $url .= '&filter_return_status_id=' . $this->request->get['filter_return_status_id']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('sale/returns', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('sale/returns.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('sale/returns.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $this->load->model('localisation/return_status'); + + $data['return_statuses'] = $this->model_localisation_return_status->getReturnStatuses(); + + $data['filter_return_id'] = $filter_return_id; + $data['filter_order_id'] = $filter_order_id; + $data['filter_customer'] = $filter_customer; + $data['filter_product'] = $filter_product; + $data['filter_model'] = $filter_model; + $data['filter_return_status_id'] = $filter_return_status_id; + $data['filter_date_from'] = $filter_date_from; + $data['filter_date_to'] = $filter_date_to; + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('sale/returns', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('sale/returns'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['filter_return_id'])) { + $filter_return_id = (int)$this->request->get['filter_return_id']; + } else { + $filter_return_id = ''; + } + + if (isset($this->request->get['filter_order_id'])) { + $filter_order_id = (int)$this->request->get['filter_order_id']; + } else { + $filter_order_id = ''; + } + + if (isset($this->request->get['filter_customer'])) { + $filter_customer = $this->request->get['filter_customer']; + } else { + $filter_customer = ''; + } + + if (isset($this->request->get['filter_product'])) { + $filter_product = $this->request->get['filter_product']; + } else { + $filter_product = ''; + } + + if (isset($this->request->get['filter_model'])) { + $filter_model = $this->request->get['filter_model']; + } else { + $filter_model = ''; + } + + if (isset($this->request->get['filter_return_status_id'])) { + $filter_return_status_id = (int)$this->request->get['filter_return_status_id']; + } else { + $filter_return_status_id = ''; + } + + if (isset($this->request->get['filter_date_from'])) { + $filter_date_from = $this->request->get['filter_date_from']; + } else { + $filter_date_from = ''; + } + + if (isset($this->request->get['filter_date_to'])) { + $filter_date_to = $this->request->get['filter_date_to']; + } else { + $filter_date_to = ''; + } + + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'r.return_id'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'DESC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['filter_return_id'])) { + $url .= '&filter_return_id=' . $this->request->get['filter_return_id']; + } + + if (isset($this->request->get['filter_order_id'])) { + $url .= '&filter_order_id=' . $this->request->get['filter_order_id']; + } + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_product'])) { + $url .= '&filter_product=' . urlencode(html_entity_decode($this->request->get['filter_product'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_model'])) { + $url .= '&filter_model=' . urlencode(html_entity_decode($this->request->get['filter_model'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_return_status_id'])) { + $url .= '&filter_return_status_id=' . $this->request->get['filter_return_status_id']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('sale/returns.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['returns'] = []; + + $filter_data = [ + 'filter_return_id' => $filter_return_id, + 'filter_order_id' => $filter_order_id, + 'filter_customer' => $filter_customer, + 'filter_product' => $filter_product, + 'filter_model' => $filter_model, + 'filter_return_status_id' => $filter_return_status_id, + 'filter_date_from' => $filter_date_from, + 'filter_date_to' => $filter_date_to, + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('sale/returns'); + + $return_total = $this->model_sale_returns->getTotalReturns($filter_data); + + $results = $this->model_sale_returns->getReturns($filter_data); + + foreach ($results as $result) { + $data['returns'][] = [ + 'return_id' => $result['return_id'], + 'order_id' => $result['order_id'], + 'customer' => $result['customer'], + 'product' => $result['product'], + 'model' => $result['model'], + 'return_status' => $result['return_status'], + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])), + 'date_modified' => date($this->language->get('date_format_short'), strtotime($result['date_modified'])), + 'edit' => $this->url->link('sale/returns.form', 'user_token=' . $this->session->data['user_token'] . '&return_id=' . $result['return_id'] . $url) + ]; + } + + $url = ''; + + if (isset($this->request->get['filter_return_id'])) { + $url .= '&filter_return_id=' . $this->request->get['filter_return_id']; + } + + if (isset($this->request->get['filter_order_id'])) { + $url .= '&filter_order_id=' . $this->request->get['filter_order_id']; + } + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_product'])) { + $url .= '&filter_product=' . urlencode(html_entity_decode($this->request->get['filter_product'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_model'])) { + $url .= '&filter_model=' . urlencode(html_entity_decode($this->request->get['filter_model'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_return_status_id'])) { + $url .= '&filter_return_status_id=' . $this->request->get['filter_return_status_id']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_return_id'] = $this->url->link('sale/returns.list', 'user_token=' . $this->session->data['user_token'] . '&sort=r.return_id' . $url); + $data['sort_order_id'] = $this->url->link('sale/returns.list', 'user_token=' . $this->session->data['user_token'] . '&sort=r.order_id' . $url); + $data['sort_customer'] = $this->url->link('sale/returns.list', 'user_token=' . $this->session->data['user_token'] . '&sort=customer' . $url); + $data['sort_product'] = $this->url->link('sale/returns.list', 'user_token=' . $this->session->data['user_token'] . '&sort=r.product' . $url); + $data['sort_model'] = $this->url->link('sale/returns.list', 'user_token=' . $this->session->data['user_token'] . '&sort=r.model' . $url); + $data['sort_status'] = $this->url->link('sale/returns.list', 'user_token=' . $this->session->data['user_token'] . '&sort=return_status' . $url); + $data['sort_date_added'] = $this->url->link('sale/returns.list', 'user_token=' . $this->session->data['user_token'] . '&sort=r.date_added' . $url); + $data['sort_date_modified'] = $this->url->link('sale/returns.list', 'user_token=' . $this->session->data['user_token'] . '&sort=r.date_modified' . $url); + + $url = ''; + + if (isset($this->request->get['filter_return_id'])) { + $url .= '&filter_return_id=' . $this->request->get['filter_return_id']; + } + + if (isset($this->request->get['filter_order_id'])) { + $url .= '&filter_order_id=' . $this->request->get['filter_order_id']; + } + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_product'])) { + $url .= '&filter_product=' . urlencode(html_entity_decode($this->request->get['filter_product'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_model'])) { + $url .= '&filter_model=' . urlencode(html_entity_decode($this->request->get['filter_model'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_return_status_id'])) { + $url .= '&filter_return_status_id=' . $this->request->get['filter_return_status_id']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $return_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('sale/returns.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($return_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($return_total - $this->config->get('config_pagination_admin'))) ? $return_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $return_total, ceil($return_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('sale/returns_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('sale/returns'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['return_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['filter_return_id'])) { + $url .= '&filter_return_id=' . $this->request->get['filter_return_id']; + } + + if (isset($this->request->get['filter_order_id'])) { + $url .= '&filter_order_id=' . $this->request->get['filter_order_id']; + } + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_product'])) { + $url .= '&filter_product=' . urlencode(html_entity_decode($this->request->get['filter_product'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_model'])) { + $url .= '&filter_model=' . urlencode(html_entity_decode($this->request->get['filter_model'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_return_status_id'])) { + $url .= '&filter_return_status_id=' . $this->request->get['filter_return_status_id']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('sale/returns', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('sale/returns.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('sale/returns', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['return_id'])) { + $this->load->model('sale/returns'); + + $return_info = $this->model_sale_returns->getReturn($this->request->get['return_id']); + } + + if (isset($this->request->get['return_id'])) { + $data['return_id'] = (int)$this->request->get['return_id']; + } else { + $data['return_id'] = 0; + } + + if (!empty($return_info)) { + $data['order_id'] = $return_info['order_id']; + } else { + $data['order_id'] = ''; + } + + if (!empty($return_info)) { + $data['date_ordered'] = ($return_info['date_ordered'] != '0000-00-00' ? $return_info['date_ordered'] : ''); + } else { + $data['date_ordered'] = ''; + } + + if (!empty($return_info)) { + $data['customer'] = $return_info['customer']; + } else { + $data['customer'] = ''; + } + + if (!empty($return_info)) { + $data['customer_id'] = $return_info['customer_id']; + } else { + $data['customer_id'] = ''; + } + + if (!empty($return_info)) { + $data['firstname'] = $return_info['firstname']; + } else { + $data['firstname'] = ''; + } + + if (!empty($return_info)) { + $data['lastname'] = $return_info['lastname']; + } else { + $data['lastname'] = ''; + } + + if (!empty($return_info)) { + $data['email'] = $return_info['email']; + } else { + $data['email'] = ''; + } + + if (!empty($return_info)) { + $data['telephone'] = $return_info['telephone']; + } else { + $data['telephone'] = ''; + } + + if (!empty($return_info)) { + $data['product'] = $return_info['product']; + } else { + $data['product'] = ''; + } + + if (!empty($return_info)) { + $data['product_id'] = $return_info['product_id']; + } else { + $data['product_id'] = ''; + } + + if (!empty($return_info)) { + $data['model'] = $return_info['model']; + } else { + $data['model'] = ''; + } + + if (!empty($return_info)) { + $data['quantity'] = $return_info['quantity']; + } else { + $data['quantity'] = ''; + } + + if (!empty($return_info)) { + $data['opened'] = $return_info['opened']; + } else { + $data['opened'] = ''; + } + + $this->load->model('localisation/return_reason'); + + $data['return_reasons'] = $this->model_localisation_return_reason->getReturnReasons(); + + if (!empty($return_info)) { + $data['return_reason_id'] = $return_info['return_reason_id']; + } else { + $data['return_reason_id'] = 0; + } + + $this->load->model('localisation/return_action'); + + $data['return_actions'] = $this->model_localisation_return_action->getReturnActions(); + + if (!empty($return_info)) { + $data['return_action_id'] = $return_info['return_action_id']; + } else { + $data['return_action_id'] = 0; + } + + if (!empty($return_info)) { + $data['comment'] = $return_info['comment']; + } else { + $data['comment'] = ''; + } + + $this->load->model('localisation/return_status'); + + $data['return_statuses'] = $this->model_localisation_return_status->getReturnStatuses(); + + if (!empty($return_info)) { + $data['return_status_id'] = $return_info['return_status_id']; + } else { + $data['return_status_id'] = ''; + } + + $data['history'] = $this->getHistory(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('sale/returns_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('sale/returns'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'sale/returns')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if (empty($this->request->post['order_id'])) { + $json['error']['order_id'] = $this->language->get('error_order_id'); + } + + if ((oc_strlen($this->request->post['firstname']) < 1) || (oc_strlen($this->request->post['firstname']) > 32)) { + $json['error']['firstname'] = $this->language->get('error_firstname'); + } + + if ((oc_strlen($this->request->post['lastname']) < 1) || (oc_strlen($this->request->post['lastname']) > 32)) { + $json['error']['lastname'] = $this->language->get('error_lastname'); + } + + if ((oc_strlen($this->request->post['email']) > 96) || !filter_var($this->request->post['email'], FILTER_VALIDATE_EMAIL)) { + $json['error']['email'] = $this->language->get('error_email'); + } + + if ((oc_strlen($this->request->post['telephone']) < 3) || (oc_strlen($this->request->post['telephone']) > 32)) { + $json['error']['telephone'] = $this->language->get('error_telephone'); + } + + if ((oc_strlen($this->request->post['product']) < 1) || (oc_strlen($this->request->post['product']) > 255)) { + $json['error']['product'] = $this->language->get('error_product'); + } + + if ((oc_strlen($this->request->post['model']) < 1) || (oc_strlen($this->request->post['model']) > 64)) { + $json['error']['model'] = $this->language->get('error_model'); + } + + if (empty($this->request->post['return_reason_id'])) { + $json['error']['reason'] = $this->language->get('error_reason'); + } + + if (isset($json['error']) && !isset($json['error']['warning'])) { + $json['error']['warning'] = $this->language->get('error_warning'); + } + + if (!$json) { + $this->load->model('sale/returns'); + + if (!$this->request->post['return_id']) { + $json['return_id'] = $this->model_sale_returns->addReturn($this->request->post); + } else { + $this->model_sale_returns->editReturn($this->request->post['return_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('sale/returns'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'sale/returns')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('sale/returns'); + + foreach ($selected as $return_id) { + $this->model_sale_returns->deleteReturn($return_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function history(): void { + $this->load->language('sale/returns'); + + $this->response->setOutput($this->getHistory()); + } + + /** + * @return string + */ + public function getHistory(): string { + if (isset($this->request->get['return_id'])) { + $return_id = (int)$this->request->get['return_id']; + } else { + $return_id = 0; + } + + if (isset($this->request->get['page']) && $this->request->get['route'] == 'sale/returns.history') { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $limit = 10; + + $data['histories'] = []; + + $this->load->model('sale/returns'); + + $results = $this->model_sale_returns->getHistories($return_id, ($page - 1) * $limit, $limit); + + foreach ($results as $result) { + $data['histories'][] = [ + 'notify' => $result['notify'] ? $this->language->get('text_yes') : $this->language->get('text_no'), + 'status' => $result['status'], + 'comment' => nl2br($result['comment']), + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])) + ]; + } + + $history_total = $this->model_sale_returns->getTotalHistories($return_id); + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $history_total, + 'page' => $page, + 'limit' => $limit, + 'url' => $this->url->link('sale/returns.history', 'user_token=' . $this->session->data['user_token'] . '&return_id=' . $return_id . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($history_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($history_total - $limit)) ? $history_total : ((($page - 1) * $limit) + $limit), $history_total, ceil($history_total / $limit)); + + return $this->load->view('sale/returns_history', $data); + } + + /** + * @return void + */ + public function addHistory(): void { + $this->load->language('sale/returns'); + + $json = []; + + if (isset($this->request->get['return_id'])) { + $return_id = (int)$this->request->get['return_id']; + } else { + $return_id = 0; + } + + if (!$this->user->hasPermission('modify', 'sale/returns')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('sale/returns'); + + $return_info = $this->model_sale_returns->getReturn($return_id); + + if (!$return_info) { + $json['error'] = $this->language->get('error_return'); + } + + if (!$json) { + $this->model_sale_returns->addHistory($return_id, $this->request->post['return_status_id'], $this->request->post['comment'], $this->request->post['notify']); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/sale/subscription.php b/admininistrator/controller/sale/subscription.php new file mode 100644 index 0000000..f2b91ed --- /dev/null +++ b/admininistrator/controller/sale/subscription.php @@ -0,0 +1,980 @@ +load->language('sale/subscription'); + + $this->document->setTitle($this->language->get('heading_title')); + + if (isset($this->request->get['filter_subscription_id'])) { + $filter_subscription_id = (int)$this->request->get['filter_subscription_id']; + } else { + $filter_subscription_id = ''; + } + + if (isset($this->request->get['filter_order_id'])) { + $filter_order_id = $this->request->get['filter_order_id']; + } else { + $filter_order_id = ''; + } + + if (isset($this->request->get['filter_customer'])) { + $filter_customer = $this->request->get['filter_customer']; + } else { + $filter_customer = ''; + } + + if (isset($this->request->get['filter_subscription_status_id'])) { + $filter_subscription_status_id = (int)$this->request->get['filter_subscription_status_id']; + } else { + $filter_subscription_status_id = ''; + } + + if (isset($this->request->get['filter_date_from'])) { + $filter_date_from = $this->request->get['filter_date_from']; + } else { + $filter_date_from = ''; + } + + if (isset($this->request->get['filter_date_to'])) { + $filter_date_to = $this->request->get['filter_date_to']; + } else { + $filter_date_to = ''; + } + + $url = ''; + + if (isset($this->request->get['filter_subscription_id'])) { + $url .= '&filter_subscription_id=' . $this->request->get['filter_subscription_id']; + } + + if (isset($this->request->get['filter_order_id'])) { + $url .= '&filter_order_id=' . $this->request->get['filter_order_id']; + } + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_subscription_status_id'])) { + $url .= '&filter_subscription_status_id=' . $this->request->get['filter_subscription_status_id']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('sale/subscription', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('sale/subscription.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('sale/subscription.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $this->load->model('localisation/subscription_status'); + + $data['subscription_statuses'] = $this->model_localisation_subscription_status->getSubscriptionStatuses(); + + $data['filter_subscription_id'] = $filter_subscription_id; + $data['filter_order_id'] = $filter_order_id; + $data['filter_customer'] = $filter_customer; + $data['filter_subscription_status_id'] = $filter_subscription_status_id; + $data['filter_date_from'] = $filter_date_from; + $data['filter_date_to'] = $filter_date_to; + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('sale/subscription', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('sale/subscription'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['filter_subscription_id'])) { + $filter_subscription_id = (int)$this->request->get['filter_subscription_id']; + } else { + $filter_subscription_id = ''; + } + + if (isset($this->request->get['filter_order_id'])) { + $filter_order_id = $this->request->get['filter_order_id']; + } else { + $filter_order_id = ''; + } + + if (isset($this->request->get['filter_customer'])) { + $filter_customer = $this->request->get['filter_customer']; + } else { + $filter_customer = ''; + } + + if (isset($this->request->get['filter_subscription_status_id'])) { + $filter_subscription_status_id = (int)$this->request->get['filter_subscription_status_id']; + } else { + $filter_subscription_status_id = ''; + } + + if (isset($this->request->get['filter_date_from'])) { + $filter_date_from = $this->request->get['filter_date_from']; + } else { + $filter_date_from = ''; + } + + if (isset($this->request->get['filter_date_to'])) { + $filter_date_to = $this->request->get['filter_date_to']; + } else { + $filter_date_to = ''; + } + + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 's.subscription_id'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'DESC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['filter_subscription_id'])) { + $url .= '&filter_subscription_id=' . $this->request->get['filter_subscription_id']; + } + + if (isset($this->request->get['filter_order_id'])) { + $url .= '&filter_order_id=' . $this->request->get['filter_order_id']; + } + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_subscription_status_id'])) { + $url .= '&filter_subscription_status_id=' . $this->request->get['filter_subscription_status_id']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['subscriptions'] = []; + + $filter_data = [ + 'filter_subscription_id' => $filter_subscription_id, + 'filter_order_id' => $filter_order_id, + 'filter_customer' => $filter_customer, + 'filter_subscription_status_id' => $filter_subscription_status_id, + 'filter_date_from' => $filter_date_from, + 'filter_date_to' => $filter_date_to, + 'order' => $order, + 'sort' => $sort, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('sale/subscription'); + + $subscription_total = $this->model_sale_subscription->getTotalSubscriptions($filter_data); + + $results = $this->model_sale_subscription->getSubscriptions($filter_data); + + foreach ($results as $result) { + $data['subscriptions'][] = [ + 'subscription_id' => $result['subscription_id'], + 'order_id' => $result['order_id'], + 'customer' => $result['customer'], + 'status' => $result['subscription_status'], + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])), + 'view' => $this->url->link('sale/subscription.info', 'user_token=' . $this->session->data['user_token'] . '&subscription_id=' . $result['subscription_id'] . $url), + 'order' => $this->url->link('sale/order.info', 'user_token=' . $this->session->data['user_token'] . '&order_id=' . $result['order_id']) + ]; + } + + $url = ''; + + if (isset($this->request->get['filter_subscription_id'])) { + $url .= '&filter_subscription_id=' . $this->request->get['filter_subscription_id']; + } + + if (isset($this->request->get['filter_order_id'])) { + $url .= '&filter_order_id=' . $this->request->get['filter_order_id']; + } + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_subscription_status_id'])) { + $url .= '&filter_subscription_status_id=' . $this->request->get['filter_subscription_status_id']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_subscription'] = $this->url->link('sale/subscription.list', 'user_token=' . $this->session->data['user_token'] . '&sort=s.subscription_id' . $url); + $data['sort_order'] = $this->url->link('sale/subscription.list', 'user_token=' . $this->session->data['user_token'] . '&sort=s.order_id' . $url); + $data['sort_customer'] = $this->url->link('sale/subscription.list', 'user_token=' . $this->session->data['user_token'] . '&sort=customer' . $url); + $data['sort_status'] = $this->url->link('sale/subscription.list', 'user_token=' . $this->session->data['user_token'] . '&sort=subscription_status' . $url); + $data['sort_date_added'] = $this->url->link('sale/subscription.list', 'user_token=' . $this->session->data['user_token'] . '&sort=s.date_added' . $url); + + $url = ''; + + if (isset($this->request->get['filter_subscription_id'])) { + $url .= '&filter_subscription_id=' . $this->request->get['filter_subscription_id']; + } + + if (isset($this->request->get['filter_order_id'])) { + $url .= '&filter_order_id=' . $this->request->get['filter_order_id']; + } + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_status'])) { + $url .= '&filter_status=' . $this->request->get['filter_status']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $subscription_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('sale/subscription.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($subscription_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($subscription_total - $this->config->get('config_pagination_admin'))) ? $subscription_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $subscription_total, ceil($subscription_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('sale/subscription_list', $data); + } + + /** + * @return void + */ + public function info(): void { + $this->load->language('sale/subscription'); + + if (isset($this->request->get['subscription_id'])) { + $subscription_id = (int)$this->request->get['subscription_id']; + } else { + $subscription_id = 0; + } + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !$subscription_id ? $this->language->get('text_add') : sprintf($this->language->get('text_edit'), $subscription_id); + + $url = ''; + + if (isset($this->request->get['filter_subscription_id'])) { + $url .= '&filter_subscription_id=' . $this->request->get['filter_subscription_id']; + } + + if (isset($this->request->get['filter_order_id'])) { + $url .= '&filter_order_id=' . $this->request->get['filter_order_id']; + } + + if (isset($this->request->get['filter_customer'])) { + $url .= '&filter_customer=' . urlencode(html_entity_decode($this->request->get['filter_customer'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_subscription_status_id'])) { + $url .= '&filter_subscription_status_id=' . $this->request->get['filter_subscription_status_id']; + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('sale/subscription', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['back'] = $this->url->link('sale/subscription', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['subscription_id'] = $subscription_id; + + $this->load->model('sale/subscription'); + + $subscription_info = $this->model_sale_subscription->getSubscription($data['subscription_id']); + + if (!empty($subscription_info)) { + $data['subscription_id'] = $subscription_info['subscription_id']; + } else { + $data['subscription_id'] = ''; + } + + // Order + if (!empty($subscription_info)) { + $this->load->model('sale/order'); + + $order_info = $this->model_sale_order->getOrder($subscription_info['order_id']); + } + + if (!empty($subscription_info)) { + $data['order'] = $this->url->link('sale/order.info', 'user_token=' . $this->session->data['user_token'] . '&order_id=' . $subscription_info['order_id']); + } else { + $data['order'] = ''; + } + + if (!empty($subscription_info)) { + $data['order_id'] = $subscription_info['order_id']; + } else { + $data['order_id'] = 0; + } + + // Customer + if (!empty($subscription_info)) { + $this->load->model('customer/customer'); + + $customer_info = $this->model_customer_customer->getCustomer($subscription_info['customer_id']); + } + + if (!empty($customer_info)) { + $data['firstname'] = $customer_info['firstname']; + } else { + $data['firstname'] = ''; + } + + if (!empty($customer_info)) { + $data['lastname'] = $customer_info['lastname']; + } else { + $data['lastname'] = ''; + } + + if (!empty($customer_info)) { + $data['lastname'] = $customer_info['lastname']; + } else { + $data['lastname'] = ''; + } + + // Subscription + $data['subscription_plans'] = []; + + $this->load->model('catalog/subscription_plan'); + + $results = $this->model_catalog_subscription_plan->getSubscriptionPlans(); + + foreach ($results as $result) { + $description = ''; + + if ($result['trial_status']) { + $trial_price = $this->currency->format($subscription_info['trial_price'], $this->config->get('config_currency')); + $trial_cycle = $result['trial_cycle']; + $trial_frequency = $this->language->get('text_' . $result['trial_frequency']); + $trial_duration = $result['trial_duration']; + + $description .= sprintf($this->language->get('text_subscription_trial'), $trial_price, $trial_cycle, $trial_frequency, $trial_duration); + } + + $price = $this->currency->format($subscription_info['price'], $this->config->get('config_currency')); + $cycle = $result['cycle']; + $frequency = $this->language->get('text_' . $result['frequency']); + $duration = $result['duration']; + + if ($result['duration']) { + $description .= sprintf($this->language->get('text_subscription_duration'), $price, $cycle, $frequency, $duration); + } else { + $description .= sprintf($this->language->get('text_subscription_cancel'), $price, $cycle, $frequency); + } + + $data['subscription_plans'][] = [ + 'subscription_plan_id' => $result['subscription_plan_id'], + 'name' => $result['name'], + 'description' => $description + ]; + } + + if (!empty($subscription_info)) { + $data['subscription_plan_id'] = $subscription_info['subscription_plan_id']; + } else { + $data['subscription_plan_id'] = 0; + } + + $subscription_plan_info = $this->model_catalog_subscription_plan->getSubscriptionPlan($data['subscription_plan_id']); + + if (!empty($subscription_plan_info)) { + $data['subscription_plan'] = ''; + + if ($subscription_plan_info['trial_status']) { + $trial_price = $this->currency->format($subscription_info['trial_price'], $this->config->get('config_currency')); + $trial_cycle = $result['trial_cycle']; + $trial_frequency = $this->language->get('text_' . $subscription_plan_info['trial_frequency']); + $trial_duration = $subscription_plan_info['trial_duration']; + + $data['subscription_plan'] .= sprintf($this->language->get('text_subscription_trial'), $trial_price, $trial_cycle, $trial_frequency, $trial_duration); + } + + $price = $this->currency->format($subscription_info['price'], $this->config->get('config_currency')); + $cycle = $result['cycle']; + $frequency = $this->language->get('text_' . $subscription_plan_info['frequency']); + $duration = $subscription_plan_info['duration']; + + if ($subscription_plan_info['duration']) { + $data['subscription_plan'] .= sprintf($this->language->get('text_subscription_duration'), $price, $cycle, $frequency, $duration); + } else { + $data['subscription_plan'] .= sprintf($this->language->get('text_subscription_cancel'), $price, $cycle, $frequency); + } + } else { + $data['subscription_plan'] = ''; + } + + if (!empty($subscription_info)) { + $data['trial_price'] = $subscription_info['trial_price']; + } else { + $data['trial_price'] = 0; + } + + $data['frequencies'] = []; + + $data['frequencies'][] = [ + 'text' => $this->language->get('text_day'), + 'value' => 'day' + ]; + + $data['frequencies'][] = [ + 'text' => $this->language->get('text_week'), + 'value' => 'week' + ]; + + $data['frequencies'][] = [ + 'text' => $this->language->get('text_semi_month'), + 'value' => 'semi_month' + ]; + + $data['frequencies'][] = [ + 'text' => $this->language->get('text_month'), + 'value' => 'month' + ]; + + $data['frequencies'][] = [ + 'text' => $this->language->get('text_year'), + 'value' => 'year' + ]; + + if (!empty($subscription_info)) { + $data['trial_frequency'] = $subscription_info['trial_frequency']; + } else { + $data['trial_frequency'] = ''; + } + + if (!empty($subscription_info)) { + $data['trial_cycle'] = $subscription_info['trial_cycle']; + } else { + $data['trial_cycle'] = 0; + } + + if (!empty($subscription_info)) { + $data['trial_duration'] = $subscription_info['trial_duration']; + } else { + $data['trial_duration'] = 0; + } + + if (!empty($subscription_info)) { + $data['trial_remaining'] = $subscription_info['trial_remaining']; + } else { + $data['trial_remaining'] = 0; + } + + if (!empty($subscription_info)) { + $data['trial_status'] = $subscription_info['trial_status']; + } else { + $data['trial_status'] = 0; + } + + if (!empty($subscription_info)) { + $data['price'] = $subscription_info['price']; + } else { + $data['price'] = 0; + } + + if (!empty($subscription_info)) { + $data['frequency'] = $subscription_info['frequency']; + } else { + $data['frequency'] = ''; + } + + if (!empty($subscription_info)) { + $data['cycle'] = $subscription_info['cycle']; + } else { + $data['cycle'] = 0; + } + + if (!empty($subscription_info)) { + $data['duration'] = $subscription_info['duration']; + } else { + $data['duration'] = 0; + } + + if (!empty($subscription_info)) { + $data['remaining'] = $subscription_info['remaining']; + } else { + $data['remaining'] = 0; + } + + // Date next + if (!empty($subscription_info)) { + $data['date_next'] = date($this->language->get('date_format_short'), strtotime($subscription_info['date_next'])); + } else { + $data['date_next'] = ''; + } + + + + // Payment method + if (!empty($subscription_info)) { + $data['payment_method'] = $subscription_info['payment_method']['name']; + } else { + $data['payment_method'] = ''; + } + + + + + + if (!empty($order_info)) { + $data['date_added'] = date($this->language->get('date_format_short'), strtotime($order_info['date_added'])); + } else { + $data['date_added'] = ''; + } + + // Product data + if (!empty($subscription_info)) { + $this->load->model('sale/order'); + + $product_info = $this->model_sale_order->getProductByOrderProductId($subscription_info['order_id'], $subscription_info['order_product_id']); + } + + if (!empty($product_info['name'])) { + $data['product_name'] = $product_info['name']; + } else { + $data['product_name'] = ''; + } + + if (!empty($product_info)) { + $data['product'] = $this->url->link('catalog/product.form', 'user_token=' . $this->session->data['user_token'] . '&product_id=' . $product_info['product_id']); + } else { + $data['product'] = ''; + } + + $data['options'] = []; + + $options = $this->model_sale_order->getOptions($subscription_info['order_id'], $subscription_info['order_product_id']); + + foreach ($options as $option) { + if ($option['type'] != 'file') { + $data['options'][] = [ + 'name' => $option['name'], + 'value' => $option['value'], + 'type' => $option['type'] + ]; + } else { + $upload_info = $this->model_tool_upload->getUploadByCode($option['value']); + + if ($upload_info) { + $data['options'][] = [ + 'name' => $option['name'], + 'value' => $upload_info['name'], + 'type' => $option['type'], + 'href' => $this->url->link('tool/upload.download', 'user_token=' . $this->session->data['user_token'] . '&code=' . $upload_info['code']) + ]; + } + } + } + + + + if (!empty($product_info)) { + $data['quantity'] = $product_info['quantity']; + } else { + $data['quantity'] = ''; + } + + + + $this->load->model('localisation/subscription_status'); + + $data['subscription_statuses'] = $this->model_localisation_subscription_status->getSubscriptionStatuses(); + + if (!empty($subscription_info)) { + $data['subscription_status_id'] = $subscription_info['subscription_status_id']; + } else { + $data['subscription_status_id'] = ''; + } + + $data['history'] = $this->getHistory(); + $data['orders'] = $this->getOrder(); + + // Additional tabs that are payment gateway specific + $data['tabs'] = []; + + // Extension Order Tabs can are called here. + /* + $this->load->model('setting/extension'); + + if (!empty($order_info)) { + $extension_info = $this->model_setting_extension->getExtensionByCode('payment', $order_info['payment_method']['code']); + + if ($extension_info && $this->user->hasPermission('access', 'extension/' . $extension_info['extension'] . '/payment/' . $extension_info['code'])) { + $output = $this->load->controller('extension/payment/' . $order_info['payment_code'] . '.subscription'); + + if (!$output instanceof \Exception) { + $this->load->language('extension/' . $extension_info['extension'] . '/payment/' . $extension_info['code'], 'extension'); + + $data['tabs'][] = [ + 'code' => $extension_info['code'], + 'title' => $this->language->get('extension_heading_title'), + 'content' => $output + ]; + } + } + } + */ + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('sale/subscription_info', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('sale/subscription'); + + $json = []; + + if (isset($this->request->get['subscription_id'])) { + $subscription_id = (int)$this->request->get['subscription_id']; + } else { + $subscription_id = 0; + } + + if (!$this->user->hasPermission('modify', 'sale/subscription')) { + $json['error'] = $this->language->get('error_permission'); + } elseif ($this->request->post['subscription_plan_id'] == '') { + $json['error'] = $this->language->get('error_subscription_plan'); + } + + $this->load->model('catalog/subscription_plan'); + + $subscription_plan_info = $this->model_catalog_subscription_plan->getSubscriptionPlan($this->request->post['subscription_plan_id']); + + if (!$subscription_plan_info) { + $json['error'] = $this->language->get('error_subscription_plan'); + } + + $this->load->model('sale/subscription'); + + $subscription_info = $this->model_sale_subscription->getSubscription($subscription_id); + + if (!$subscription_info) { + $this->load->model('customer/customer'); + + $payment_method_info = $this->model_customer_customer->getPaymentMethod($subscription_info['customer_id'], $this->request->post['customer_payment_id']); + + if (!$payment_method_info) { + $json['error'] = $this->language->get('error_payment_method'); + } + } else { + $json['error'] = $this->language->get('error_subscription'); + } + + if (!$json) { + $this->model_sale_subscription->editSubscriptionPlan($subscription_id, $this->request->post['subscription_plan_id']); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function history(): void { + $this->load->language('sale/subscription'); + + $this->response->setOutput($this->getHistory()); + } + + /** + * @return string + */ + public function getHistory(): string { + if (isset($this->request->get['subscription_id'])) { + $subscription_id = (int)$this->request->get['subscription_id']; + } else { + $subscription_id = 0; + } + + if (isset($this->request->get['page']) && $this->request->get['route'] == 'sale/subscription.history') { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $limit = 10; + + $data['histories'] = []; + + $this->load->model('sale/subscription'); + + $results = $this->model_sale_subscription->getHistories($subscription_id, ($page - 1) * $limit, $limit); + + foreach ($results as $result) { + $data['histories'][] = [ + 'status' => $result['status'], + 'comment' => nl2br($result['comment']), + 'notify' => $result['notify'] ? $this->language->get('text_yes') : $this->language->get('text_no'), + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])) + ]; + } + + $subscription_total = $this->model_sale_subscription->getTotalHistories($subscription_id); + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $subscription_total, + 'page' => $page, + 'limit' => $limit, + 'url' => $this->url->link('sale/subscription.history', 'user_token=' . $this->session->data['user_token'] . '&subscription_id=' . $subscription_id . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($subscription_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($subscription_total - $limit)) ? $subscription_total : ((($page - 1) * $limit) + $limit), $subscription_total, ceil($subscription_total / $limit)); + + return $this->load->view('sale/subscription_history', $data); + } + + /** + * @return void + */ + public function addHistory(): void { + $this->load->language('sale/subscription'); + + $json = []; + + if (isset($this->request->get['subscription_id'])) { + $subscription_id = (int)$this->request->get['subscription_id']; + } else { + $subscription_id = 0; + } + + if (!$this->user->hasPermission('modify', 'sale/subscription')) { + $json['error'] = $this->language->get('error_permission'); + } + + // Subscription + $this->load->model('sale/subscription'); + + $subscription_info = $this->model_sale_subscription->getSubscription($subscription_id); + + if (!$subscription_info) { + $json['error'] = $this->language->get('error_subscription'); + } + + // Subscription Plan + $this->load->model('localisation/subscription_status'); + + $subscription_status_info = $this->model_localisation_subscription_status->getSubscriptionStatus($this->request->post['subscription_status_id']); + + if (!$subscription_status_info) { + $json['error'] = $this->language->get('error_subscription_status'); + } + + if (!$json) { + $this->model_sale_subscription->addHistory($subscription_id, $this->request->post['subscription_status_id'], $this->request->post['comment'], $this->request->post['notify']); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function order(): void { + $this->load->language('sale/subscription'); + + $this->response->setOutput($this->getOrder()); + } + + /** + * @return string + */ + public function getOrder(): string { + if (isset($this->request->get['subscription_id'])) { + $subscription_id = (int)$this->request->get['subscription_id']; + } else { + $subscription_id = 0; + } + + if (isset($this->request->get['page']) && $this->request->get['route'] == 'sale/subscription.order') { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $limit = 10; + + $data['orders'] = []; + + $this->load->model('sale/order'); + + $results = $this->model_sale_order->getOrdersBySubscriptionId($subscription_id, ($page - 1) * $limit, $limit); + + foreach ($results as $result) { + $data['orders'][] = [ + 'order_id' => $result['order_id'], + 'status' => $result['status'], + 'total' => $this->currency->format($result['total'], $result['currency_code'], $result['currency_value']), + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])), + 'view' => $this->url->link('sale/subscription.order', 'user_token=' . $this->session->data['user_token'] . '&order_id=' . $result['order_id'] . '&page={page}') + ]; + } + + $order_total = $this->model_sale_order->getTotalOrdersBySubscriptionId($subscription_id); + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $order_total, + 'page' => $page, + 'limit' => $limit, + 'url' => $this->url->link('sale/subscription.order', 'user_token=' . $this->session->data['user_token'] . '&subscription_id=' . $subscription_id . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($order_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($order_total - $limit)) ? $order_total : ((($page - 1) * $limit) + $limit), $order_total, ceil($order_total / $limit)); + + return $this->load->view('sale/subscription_order', $data); + } +} diff --git a/admininistrator/controller/sale/voucher.php b/admininistrator/controller/sale/voucher.php new file mode 100644 index 0000000..51d9c2f --- /dev/null +++ b/admininistrator/controller/sale/voucher.php @@ -0,0 +1,500 @@ +load->language('sale/voucher'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('sale/voucher', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('sale/voucher.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('sale/voucher.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('sale/voucher', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('sale/voucher'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'v.date_added'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'DESC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('sale/voucher.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['vouchers'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('sale/voucher'); + + $voucher_total = $this->model_sale_voucher->getTotalVouchers(); + + $results = $this->model_sale_voucher->getVouchers($filter_data); + + foreach ($results as $result) { + if ($result['order_id']) { + $order_href = $this->url->link('sale/order.info', 'user_token=' . $this->session->data['user_token'] . '&order_id=' . $result['order_id'] . $url); + } else { + $order_href = ''; + } + + $data['vouchers'][] = [ + 'voucher_id' => $result['voucher_id'], + 'code' => $result['code'], + 'status' => $result['status'], + 'from' => $result['from_name'], + 'to' => $result['to_name'], + 'theme' => $result['theme'], + 'amount' => $this->currency->format($result['amount'], $this->config->get('config_currency')), + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])), + 'edit' => $this->url->link('sale/voucher.form', 'user_token=' . $this->session->data['user_token'] . '&voucher_id=' . $result['voucher_id'] . $url), + 'order' => $order_href + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_code'] = $this->url->link('sale/voucher.list', 'user_token=' . $this->session->data['user_token'] . '&sort=v.code' . $url); + $data['sort_from'] = $this->url->link('sale/voucher.list', 'user_token=' . $this->session->data['user_token'] . '&sort=v.from_name' . $url); + $data['sort_to'] = $this->url->link('sale/voucher.list', 'user_token=' . $this->session->data['user_token'] . '&sort=v.to_name' . $url); + $data['sort_theme'] = $this->url->link('sale/voucher.list', 'user_token=' . $this->session->data['user_token'] . '&sort=theme' . $url); + $data['sort_amount'] = $this->url->link('sale/voucher.list', 'user_token=' . $this->session->data['user_token'] . '&sort=v.amount' . $url); + $data['sort_status'] = $this->url->link('sale/voucher.list', 'user_token=' . $this->session->data['user_token'] . '&sort=v.status' . $url); + $data['sort_date_added'] = $this->url->link('sale/voucher.list', 'user_token=' . $this->session->data['user_token'] . '&sort=v.date_added' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $voucher_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('sale/voucher.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($voucher_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($voucher_total - $this->config->get('config_pagination_admin'))) ? $voucher_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $voucher_total, ceil($voucher_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('sale/voucher_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('sale/voucher'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['voucher_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('sale/voucher', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('sale/voucher.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('sale/voucher', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['voucher_id'])) { + $this->load->model('sale/voucher'); + + $voucher_info = $this->model_sale_voucher->getVoucher($this->request->get['voucher_id']); + } + + if (isset($this->request->get['voucher_id'])) { + $data['voucher_id'] = (int)$this->request->get['voucher_id']; + } else { + $data['voucher_id'] = 0; + } + + if (!empty($voucher_info)) { + $data['code'] = $voucher_info['code']; + } else { + $data['code'] = ''; + } + + if (!empty($voucher_info)) { + $data['from_name'] = $voucher_info['from_name']; + } else { + $data['from_name'] = ''; + } + + if (!empty($voucher_info)) { + $data['from_email'] = $voucher_info['from_email']; + } else { + $data['from_email'] = ''; + } + + if (!empty($voucher_info)) { + $data['to_name'] = $voucher_info['to_name']; + } else { + $data['to_name'] = ''; + } + + if (!empty($voucher_info)) { + $data['to_email'] = $voucher_info['to_email']; + } else { + $data['to_email'] = ''; + } + + $this->load->model('sale/voucher_theme'); + + $data['voucher_themes'] = $this->model_sale_voucher_theme->getVoucherThemes(); + + if (!empty($voucher_info)) { + $data['voucher_theme_id'] = $voucher_info['voucher_theme_id']; + } else { + $data['voucher_theme_id'] = ''; + } + + if (!empty($voucher_info)) { + $data['message'] = $voucher_info['message']; + } else { + $data['message'] = ''; + } + + if (!empty($voucher_info)) { + $data['amount'] = $voucher_info['amount']; + } else { + $data['amount'] = ''; + } + + if (!empty($voucher_info)) { + $data['status'] = $voucher_info['status']; + } else { + $data['status'] = true; + } + + $data['history'] = $this->getHistory(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('sale/voucher_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('sale/voucher'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'sale/voucher')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if ((oc_strlen($this->request->post['code']) < 3) || (oc_strlen($this->request->post['code']) > 10)) { + $json['error']['code'] = $this->language->get('error_code'); + } + + $this->load->model('sale/voucher'); + + $voucher_info = $this->model_sale_voucher->getVoucherByCode($this->request->post['code']); + + if ($voucher_info) { + if (!isset($this->request->post['voucher_id'])) { + $json['error']['warning'] = $this->language->get('error_exists'); + } elseif ($voucher_info['voucher_id'] != (int)$this->request->post['voucher_id']) { + $json['error']['warning'] = $this->language->get('error_exists'); + } + } + + if ((oc_strlen($this->request->post['to_name']) < 1) || (oc_strlen($this->request->post['to_name']) > 64)) { + $json['error']['to_name'] = $this->language->get('error_to_name'); + } + + if ((oc_strlen($this->request->post['to_email']) > 96) || !filter_var($this->request->post['to_email'], FILTER_VALIDATE_EMAIL)) { + $json['error']['to_email'] = $this->language->get('error_email'); + } + + if ((oc_strlen($this->request->post['from_name']) < 1) || (oc_strlen($this->request->post['from_name']) > 64)) { + $json['error']['from_name'] = $this->language->get('error_from_name'); + } + + if ((oc_strlen($this->request->post['from_email']) > 96) || !filter_var($this->request->post['from_email'], FILTER_VALIDATE_EMAIL)) { + $json['error']['from_email'] = $this->language->get('error_email'); + } + + if ($this->request->post['amount'] < 1) { + $json['error']['amount'] = $this->language->get('error_amount'); + } + + if (!$json) { + if (!$this->request->post['voucher_id']) { + $json['voucher_id'] = $this->model_sale_voucher->addVoucher($this->request->post); + } else { + $this->model_sale_voucher->editVoucher($this->request->post['voucher_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('sale/voucher'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'sale/voucher')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('sale/order'); + + foreach ($selected as $voucher_id) { + $order_voucher_info = $this->model_sale_order->getVoucherByVoucherId($voucher_id); + + if ($order_voucher_info) { + $json['error'] = sprintf($this->language->get('error_order'), $this->url->link('sale/order.info', 'user_token=' . $this->session->data['user_token'] . '&order_id=' . $order_voucher_info['order_id'])); + + break; + } + } + + if (!$json) { + $this->load->model('sale/voucher'); + + foreach ($selected as $voucher_id) { + $this->model_sale_voucher->deleteVoucher($voucher_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function history(): void { + $this->load->language('sale/voucher'); + + $this->response->setOutput($this->getHistory()); + } + + /** + * @return string + */ + public function getHistory(): string { + if (isset($this->request->get['voucher_id'])) { + $voucher_id = (int)$this->request->get['voucher_id']; + } else { + $voucher_id = 0; + } + + if (isset($this->request->get['page']) && $this->request->get['route'] == 'sale/voucher.history') { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $limit = 10; + + $data['histories'] = []; + + $this->load->model('sale/voucher'); + + $results = $this->model_sale_voucher->getHistories($voucher_id, ($page - 1) * $limit, $limit); + + foreach ($results as $result) { + $data['histories'][] = [ + 'order_id' => $result['order_id'], + 'customer' => $result['customer'], + 'amount' => $this->currency->format($result['amount'], $this->config->get('config_currency')), + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])) + ]; + } + + $history_total = $this->model_sale_voucher->getTotalHistories($voucher_id); + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $history_total, + 'page' => $page, + 'limit' => $limit, + 'url' => $this->url->link('sale/voucher.history', 'user_token=' . $this->session->data['user_token'] . '&voucher_id=' . $voucher_id . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($history_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($history_total - $limit)) ? $history_total : ((($page - 1) * $limit) + $limit), $history_total, ceil($history_total / $limit)); + + return $this->load->view('sale/voucher_history', $data); + } + + /** + * @return void + */ + public function send(): void { + $this->load->language('mail/voucher'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'sale/voucher')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('sale/voucher'); + + $vouchers = []; + + if (isset($this->request->post['selected'])) { + $vouchers = $this->request->post['selected']; + } + + if (isset($this->request->post['voucher_id'])) { + $vouchers[] = $this->request->post['voucher_id']; + } + + if ($vouchers) { + foreach ($vouchers as $voucher_id) { + $this->load->controller('mail/voucher', $voucher_id); + } + + $json['success'] = $this->language->get('text_sent'); + } + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/sale/voucher_theme.php b/admininistrator/controller/sale/voucher_theme.php new file mode 100644 index 0000000..d329120 --- /dev/null +++ b/admininistrator/controller/sale/voucher_theme.php @@ -0,0 +1,327 @@ +load->language('sale/voucher_theme'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('sale/voucher_theme', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('sale/voucher_theme.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('sale/voucher_theme.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('sale/voucher_theme', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('sale/voucher_theme'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'vtd.name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('sale/voucher_theme.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['voucher_themes'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('sale/voucher_theme'); + + $voucher_theme_total = $this->model_sale_voucher_theme->getTotalVoucherThemes(); + + $results = $this->model_sale_voucher_theme->getVoucherThemes($filter_data); + + foreach ($results as $result) { + $data['voucher_themes'][] = [ + 'voucher_theme_id' => $result['voucher_theme_id'], + 'name' => $result['name'], + 'edit' => $this->url->link('sale/voucher_theme.form', 'user_token=' . $this->session->data['user_token'] . '&voucher_theme_id=' . $result['voucher_theme_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('sale/voucher_theme.list', 'user_token=' . $this->session->data['user_token'] . '&sort=name' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $voucher_theme_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('sale/voucher_theme.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($voucher_theme_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($voucher_theme_total - $this->config->get('config_pagination_admin'))) ? $voucher_theme_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $voucher_theme_total, ceil($voucher_theme_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('sale/voucher_theme_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('sale/voucher_theme'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['voucher_theme_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('sale/voucher_theme', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('sale/voucher_theme.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('sale/voucher_theme', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['voucher_theme_id'])) { + $this->load->model('sale/voucher_theme'); + + $voucher_theme_info = $this->model_sale_voucher_theme->getVoucherTheme($this->request->get['voucher_theme_id']); + } + + if (isset($this->request->get['voucher_theme_id'])) { + $data['voucher_theme_id'] = (int)$this->request->get['voucher_theme_id']; + } else { + $data['voucher_theme_id'] = 0; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (!empty($voucher_theme_info)) { + $data['voucher_theme_description'] = $this->model_sale_voucher_theme->getDescriptions($this->request->get['voucher_theme_id']); + } else { + $data['voucher_theme_description'] = []; + } + + if (!empty($voucher_theme_info)) { + $data['image'] = $voucher_theme_info['image']; + } else { + $data['image'] = ''; + } + + $this->load->model('tool/image'); + + $data['placeholder'] = $this->model_tool_image->resize('no_image.png', 100, 100); + + if (is_file(DIR_IMAGE . html_entity_decode($data['image'], ENT_QUOTES, 'UTF-8'))) { + $data['thumb'] = $this->model_tool_image->resize(html_entity_decode($data['image'], ENT_QUOTES, 'UTF-8'), 100, 100); + } else { + $data['thumb'] = $data['placeholder']; + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('sale/voucher_theme_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('sale/voucher_theme'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'sale/voucher_theme')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + foreach ($this->request->post['voucher_theme_description'] as $language_id => $value) { + if ((oc_strlen($value['name']) < 3) || (oc_strlen($value['name']) > 32)) { + $json['error']['name_' . $language_id] = $this->language->get('error_name'); + } + } + + if (!$this->request->post['image']) { + $json['error']['image'] = $this->language->get('error_image'); + } + + if (!$json) { + $this->load->model('sale/voucher_theme'); + + if (!$this->request->post['voucher_theme_id']) { + $json['voucher_theme_id'] = $this->model_sale_voucher_theme->addVoucherTheme($this->request->post); + } else { + $this->model_sale_voucher_theme->editVoucherTheme($this->request->post['voucher_theme_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('sale/voucher_theme'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'sale/voucher_theme')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('sale/voucher'); + + foreach ($selected as $voucher_theme_id) { + $voucher_total = $this->model_sale_voucher->getTotalVouchersByVoucherThemeId($voucher_theme_id); + + if ($voucher_total) { + $json['error'] = sprintf($this->language->get('error_voucher'), $voucher_total); + } + } + + if (!$json) { + $this->load->model('sale/voucher_theme'); + + foreach ($selected as $voucher_theme_id) { + $this->model_sale_voucher_theme->deleteVoucherTheme($voucher_theme_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/setting/setting.php b/admininistrator/controller/setting/setting.php new file mode 100644 index 0000000..0adac57 --- /dev/null +++ b/admininistrator/controller/setting/setting.php @@ -0,0 +1,860 @@ +load->language('setting/setting'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_stores'), + 'href' => $this->url->link('setting/store', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('setting/setting', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['save'] = $this->url->link('setting/setting.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('setting/store', 'user_token=' . $this->session->data['user_token']); + + // General + $data['config_meta_title'] = $this->config->get('config_meta_title'); + $data['config_meta_description'] = $this->config->get('config_meta_description'); + $data['config_meta_keyword'] = $this->config->get('config_meta_keyword'); + + $data['store_url'] = HTTP_CATALOG; + + $data['themes'] = []; + + $this->load->model('setting/extension'); + + $extensions = $this->model_setting_extension->getExtensionsByType('theme'); + + foreach ($extensions as $extension) { + $this->load->language('extension/' . $extension['extension'] . '/theme/' . $extension['code'], 'extension'); + + $data['themes'][] = [ + 'text' => $this->language->get('extension_heading_title'), + 'value' => $extension['code'] + ]; + } + + $data['config_theme'] = $this->config->get('config_theme'); + + $this->load->model('design/layout'); + + $data['layouts'] = $this->model_design_layout->getLayouts(); + + $data['config_layout_id'] = $this->config->get('config_layout_id'); + + // Store Details + $data['config_name'] = $this->config->get('config_name'); + $data['config_owner'] = $this->config->get('config_owner'); + $data['config_address'] = $this->config->get('config_address'); + $data['config_geocode'] = $this->config->get('config_geocode'); + $data['config_email'] = $this->config->get('config_email'); + $data['config_telephone'] = $this->config->get('config_telephone'); + $data['config_image'] = $this->config->get('config_image'); + + $this->load->model('tool/image'); + + $data['placeholder'] = $this->model_tool_image->resize('no_image.png', 100, 100); + + if (is_file(DIR_IMAGE . html_entity_decode($data['config_image'], ENT_QUOTES, 'UTF-8'))) { + $data['thumb'] = $this->model_tool_image->resize(html_entity_decode($data['config_image'], ENT_QUOTES, 'UTF-8'), 100, 100); + } else { + $data['thumb'] = $data['placeholder']; + } + + $data['config_open'] = $this->config->get('config_open'); + $data['config_comment'] = $this->config->get('config_comment'); + + $this->load->model('localisation/location'); + + $data['locations'] = $this->model_localisation_location->getLocations(); + + if ($this->config->get('config_location')) { + $data['config_location'] = $this->config->get('config_location'); + } else { + $data['config_location'] = []; + } + + // Localisation + $this->load->model('localisation/country'); + + $data['countries'] = $this->model_localisation_country->getCountries(); + + $data['config_country_id'] = $this->config->get('config_country_id'); + + $data['config_zone_id'] = $this->config->get('config_zone_id'); + + if ($this->config->has('config_timezone')) { + $data['config_timezone'] = $this->config->get('config_timezone'); + } else { + $data['config_timezone'] = 'UTC'; + } + + $data['timezones'] = []; + + $timestamp = date_create('now'); + + $timezones = timezone_identifiers_list(); + + foreach ($timezones as $timezone) { + date_timezone_set($timestamp, timezone_open($timezone)); + + $hour = ' (' . date_format($timestamp, 'P') . ')'; + + $data['timezones'][] = [ + 'text' => $timezone . $hour, + 'value' => $timezone + ]; + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + $data['config_language'] = $this->config->get('config_language'); + + $data['config_language_admin'] = $this->config->get('config_language_admin'); + + $this->load->model('localisation/currency'); + + $data['currencies'] = $this->model_localisation_currency->getCurrencies(); + + $data['config_currency'] = $this->config->get('config_currency'); + + $data['currency_engines'] = []; + + $this->load->model('setting/extension'); + + $extensions = $this->model_setting_extension->getExtensionsByType('currency'); + + foreach ($extensions as $extension) { + if ($this->config->get('currency_' . $extension['code'] . '_status')) { + $this->load->language('extension/' . $extension['extension'] . '/currency/' . $extension['code'], 'extension'); + + $data['currency_engines'][] = [ + 'text' => $this->language->get('extension_heading_title'), + 'value' => $extension['code'] + ]; + } + } + + $data['config_currency_engine'] = $this->config->get('config_currency_engine'); + $data['config_currency_auto'] = $this->config->get('config_currency_auto'); + + $this->load->model('localisation/length_class'); + + $data['length_classes'] = $this->model_localisation_length_class->getLengthClasses(); + + $data['config_length_class_id'] = $this->config->get('config_length_class_id'); + + $this->load->model('localisation/weight_class'); + + $data['weight_classes'] = $this->model_localisation_weight_class->getWeightClasses(); + + $data['config_weight_class_id'] = $this->config->get('config_weight_class_id'); + + // Options + $data['config_product_description_length'] = $this->config->get('config_product_description_length'); + + if ($this->config->get('config_pagination')) { + $data['config_pagination'] = $this->config->get('config_pagination'); + } else { + $data['config_pagination'] = 15; + } + + $data['config_product_count'] = $this->config->get('config_product_count'); + + if ($this->config->get('config_pagination_admin')) { + $data['config_pagination_admin'] = $this->config->get('config_pagination_admin'); + } else { + $data['config_pagination_admin'] = 10; + } + + $data['config_product_report_status'] = $this->config->get('config_product_report_status'); + + $data['config_review_status'] = $this->config->get('config_review_status'); + $data['config_review_purchased'] = $this->config->get('config_review_purchased'); + $data['config_review_guest'] = $this->config->get('config_review_guest'); + + // CMS + $data['config_article_description_length'] = $this->config->get('config_article_description_length'); + $data['config_comment_status'] = $this->config->get('config_comment_status'); + $data['config_comment_guest'] = $this->config->get('config_comment_guest'); + + $data['config_voucher_min'] = $this->config->get('config_voucher_min'); + $data['config_voucher_max'] = $this->config->get('config_voucher_max'); + + $data['config_cookie_id'] = $this->config->get('config_cookie_id'); + + $data['config_gdpr_id'] = $this->config->get('config_gdpr_id'); + $data['config_gdpr_limit'] = $this->config->get('config_gdpr_limit'); + + $data['config_tax'] = $this->config->get('config_tax'); + $data['config_tax_default'] = $this->config->get('config_tax_default'); + $data['config_tax_customer'] = $this->config->get('config_tax_customer'); + + $data['config_customer_online'] = $this->config->get('config_customer_online'); + + if ($this->config->has('config_customer_online_expire')) { + $data['config_customer_online_expire'] = $this->config->get('config_customer_online_expire'); + } else { + $data['config_customer_online_expire'] = 1; + } + + $data['config_customer_activity'] = $this->config->get('config_customer_activity'); + $data['config_customer_search'] = $this->config->get('config_customer_search'); + + $this->load->model('customer/customer_group'); + + $data['customer_groups'] = $this->model_customer_customer_group->getCustomerGroups(); + + $data['config_customer_group_id'] = $this->config->get('config_customer_group_id'); + + if ($this->config->get('config_customer_group_display')) { + $data['config_customer_group_display'] = $this->config->get('config_customer_group_display'); + } else { + $data['config_customer_group_display'] = []; + } + + $data['config_customer_price'] = $this->config->get('config_customer_price'); + $data['config_telephone_display'] = $this->config->get('config_telephone_display'); + $data['config_telephone_required'] = $this->config->get('config_telephone_required'); + + if ($this->config->has('config_login_attempts')) { + $data['config_login_attempts'] = $this->config->get('config_login_attempts'); + } else { + $data['config_login_attempts'] = 5; + } + + $this->load->model('catalog/information'); + + $data['informations'] = $this->model_catalog_information->getInformations(); + + $data['config_account_id'] = $this->config->get('config_account_id'); + + $data['config_cart_weight'] = $this->config->get('config_cart_weight'); + $data['config_checkout_guest'] = $this->config->get('config_checkout_guest'); + $data['config_checkout_payment_address'] = $this->config->get('config_checkout_payment_address'); + $data['config_checkout_shipping_address'] = $this->config->get('config_checkout_shipping_address'); + $data['config_checkout_id'] = $this->config->get('config_checkout_id'); + + if ($this->config->get('config_invoice_prefix')) { + $data['config_invoice_prefix'] = $this->config->get('config_invoice_prefix'); + } else { + $data['config_invoice_prefix'] = 'INV-' . date('Y') . '-00'; + } + + $this->load->model('localisation/order_status'); + + $data['order_statuses'] = $this->model_localisation_order_status->getOrderStatuses(); + + $data['config_order_status_id'] = $this->config->get('config_order_status_id'); + + if ($this->config->get('config_processing_status')) { + $data['config_processing_status'] = $this->config->get('config_processing_status'); + } else { + $data['config_processing_status'] = []; + } + + if ($this->config->get('config_complete_status')) { + $data['config_complete_status'] = $this->config->get('config_complete_status'); + } else { + $data['config_complete_status'] = []; + } + + $data['config_fraud_status_id'] = $this->config->get('config_fraud_status_id'); + + // Subscription + $this->load->model('localisation/subscription_status'); + + $data['subscription_statuses'] = $this->model_localisation_subscription_status->getSubscriptionStatuses(); + + $data['config_subscription_status_id'] = $this->config->get('config_subscription_status_id'); + $data['config_subscription_active_status_id'] = $this->config->get('config_subscription_active_status_id'); + $data['config_subscription_suspended_status_id'] = $this->config->get('config_subscription_suspended_status_id'); + $data['config_subscription_expired_status_id'] = $this->config->get('config_subscription_expired_status_id'); + $data['config_subscription_canceled_status_id'] = $this->config->get('config_subscription_canceled_status_id'); + $data['config_subscription_failed_status_id'] = $this->config->get('config_subscription_failed_status_id'); + $data['config_subscription_denied_status_id'] = $this->config->get('config_subscription_denied_status_id'); + + // Api + $this->load->model('user/api'); + + $data['apis'] = $this->model_user_api->getApis(); + + $data['config_api_id'] = $this->config->get('config_api_id'); + + $data['config_stock_display'] = $this->config->get('config_stock_display'); + $data['config_stock_warning'] = $this->config->get('config_stock_warning'); + $data['config_stock_checkout'] = $this->config->get('config_stock_checkout'); + + if ($this->config->has('config_affiliate_status')) { + $data['config_affiliate_status'] = $this->config->get('config_affiliate_status'); + } else { + $data['config_affiliate_status'] = ''; + } + + $data['config_affiliate_group_id'] = $this->config->get('config_affiliate_group_id'); + + if ($this->config->has('config_affiliate_approval')) { + $data['config_affiliate_approval'] = $this->config->get('config_affiliate_approval'); + } else { + $data['config_affiliate_approval'] = ''; + } + + if ($this->config->has('config_affiliate_auto')) { + $data['config_affiliate_auto'] = $this->config->get('config_affiliate_auto'); + } else { + $data['config_affiliate_auto'] = ''; + } + + if ($this->config->has('config_affiliate_commission')) { + $data['config_affiliate_commission'] = $this->config->get('config_affiliate_commission'); + } else { + $data['config_affiliate_commission'] = '5.00'; + } + + if ($this->config->has('config_affiliate_expire')) { + $data['config_affiliate_expire'] = $this->config->get('config_affiliate_expire'); + } else { + $data['config_affiliate_expire'] = 0; + } + + // Affiliate terms + $data['config_affiliate_id'] = $this->config->get('config_affiliate_id'); + + $this->load->model('localisation/return_status'); + + $data['return_statuses'] = $this->model_localisation_return_status->getReturnStatuses(); + + $data['config_return_status_id'] = $this->config->get('config_return_status_id'); + + // Return terms + $data['config_return_id'] = $this->config->get('config_return_id'); + + // Captcha + $data['config_captcha'] = $this->config->get('config_captcha'); + + $this->load->model('setting/extension'); + + $data['captchas'] = []; + + // Get a list of installed captchas + $extensions = $this->model_setting_extension->getExtensionsByType('captcha'); + + foreach ($extensions as $extension) { + $this->load->language('extension/' . $extension['extension'] . '/captcha/' . $extension['code'], 'extension'); + + if ($this->config->get('captcha_' . $extension['code'] . '_status')) { + $data['captchas'][] = [ + 'text' => $this->language->get('extension_heading_title'), + 'value' => $extension['code'] + ]; + } + } + + if ($this->config->has('config_captcha_page')) { + $data['config_captcha_page'] = $this->config->get('config_captcha_page'); + } else { + $data['config_captcha_page'] = []; + } + + $data['captcha_pages'] = []; + + $data['captcha_pages'][] = [ + 'text' => $this->language->get('text_register'), + 'value' => 'register' + ]; + + $data['captcha_pages'][] = [ + 'text' => $this->language->get('text_guest'), + 'value' => 'guest' + ]; + + $data['captcha_pages'][] = [ + 'text' => $this->language->get('text_review'), + 'value' => 'review' + ]; + + $data['captcha_pages'][] = [ + 'text' => $this->language->get('text_comment'), + 'value' => 'comment' + ]; + + $data['captcha_pages'][] = [ + 'text' => $this->language->get('text_return'), + 'value' => 'returns' + ]; + + $data['captcha_pages'][] = [ + 'text' => $this->language->get('text_contact'), + 'value' => 'contact' + ]; + + // Images + $data['config_logo'] = $this->config->get('config_logo'); + + $this->load->model('tool/image'); + + $data['placeholder'] = $this->model_tool_image->resize('no_image.png', 100, 100); + + if (is_file(DIR_IMAGE . html_entity_decode($data['config_logo'], ENT_QUOTES, 'UTF-8'))) { + $data['logo'] = $this->model_tool_image->resize(html_entity_decode($data['config_logo'], ENT_QUOTES, 'UTF-8'), 100, 100); + } else { + $data['logo'] = $data['placeholder']; + } + + if ($this->config->get('config_image_category_width')) { + $data['config_image_category_width'] = $this->config->get('config_image_category_width'); + } else { + $data['config_image_category_width'] = 80; + } + + if ($this->config->get('config_image_category_height')) { + $data['config_image_category_height'] = $this->config->get('config_image_category_height'); + } else { + $data['config_image_category_height'] = 80; + } + + if ($this->config->get('config_image_thumb_width')) { + $data['config_image_thumb_width'] = $this->config->get('config_image_thumb_width'); + } else { + $data['config_image_thumb_width'] = 228; + } + + if ($this->config->get('config_image_thumb_height')) { + $data['config_image_thumb_height'] = $this->config->get('config_image_thumb_height'); + } else { + $data['config_image_thumb_height'] = 228; + } + + if ($this->config->get('config_image_popup_width')) { + $data['config_image_popup_width'] = $this->config->get('config_image_popup_width'); + } else { + $data['config_image_popup_width'] = 500; + } + + if ($this->config->get('config_image_popup_height')) { + $data['config_image_popup_height'] = $this->config->get('config_image_popup_height'); + } else { + $data['config_image_popup_height'] = 500; + } + + if ($this->config->get('config_image_product_width')) { + $data['config_image_product_width'] = $this->config->get('config_image_product_width'); + } else { + $data['config_image_product_width'] = 228; + } + + if ($this->config->get('config_image_product_height')) { + $data['config_image_product_height'] = $this->config->get('config_image_product_height'); + } else { + $data['config_image_product_height'] = 228; + } + + if ($this->config->get('config_image_additional_width')) { + $data['config_image_additional_width'] = $this->config->get('config_image_additional_width'); + } else { + $data['config_image_additional_width'] = 74; + } + + if ($this->config->get('config_image_additional_height')) { + $data['config_image_additional_height'] = $this->config->get('config_image_additional_height'); + } else { + $data['config_image_additional_height'] = 74; + } + + if ($this->config->get('config_image_related_width')) { + $data['config_image_related_width'] = $this->config->get('config_image_related_width'); + } else { + $data['config_image_related_width'] = 80; + } + + if ($this->config->get('config_image_related_height')) { + $data['config_image_related_height'] = $this->config->get('config_image_related_height'); + } else { + $data['config_image_related_height'] = 80; + } + + if ($this->config->get('config_image_compare_width')) { + $data['config_image_compare_width'] = $this->config->get('config_image_compare_width'); + } else { + $data['config_image_compare_width'] = 90; + } + + if ($this->config->get('config_image_compare_height')) { + $data['config_image_compare_height'] = $this->config->get('config_image_compare_height'); + } else { + $data['config_image_compare_height'] = 90; + } + + if ($this->config->get('config_image_blog_width')) { + $data['config_image_blog_width'] = $this->config->get('config_image_blog_width'); + } else { + $data['config_image_blog_width'] = 90; + } + + if ($this->config->get('config_image_blog_height')) { + $data['config_image_blog_height'] = $this->config->get('config_image_blog_height'); + } else { + $data['config_image_blog_height'] = 90; + } + + if ($this->config->get('config_image_wishlist_width')) { + $data['config_image_wishlist_width'] = $this->config->get('config_image_wishlist_width'); + } else { + $data['config_image_wishlist_width'] = 47; + } + + if ($this->config->get('config_image_wishlist_height')) { + $data['config_image_wishlist_height'] = $this->config->get('config_image_wishlist_height'); + } else { + $data['config_image_wishlist_height'] = 47; + } + + if ($this->config->get('config_image_cart_width')) { + $data['config_image_cart_width'] = $this->config->get('config_image_cart_width'); + } else { + $data['config_image_cart_width'] = 47; + } + + if ($this->config->get('config_image_cart_height')) { + $data['config_image_cart_height'] =$this->config->get('config_image_cart_height'); + } else { + $data['config_image_cart_height'] = 47; + } + + if ($this->config->get('config_image_location_width')) { + $data['config_image_location_width'] = $this->config->get('config_image_location_width'); + } else { + $data['config_image_location_width'] = 268; + } + + if ($this->config->get('config_image_location_height')) { + $data['config_image_location_height'] = $this->config->get('config_image_location_height'); + } else { + $data['config_image_location_height'] = 50; + } + + // Mail + $data['config_mail_engine'] = $this->config->get('config_mail_engine'); + $data['config_mail_parameter'] = $this->config->get('config_mail_parameter'); + $data['config_mail_smtp_hostname'] = $this->config->get('config_mail_smtp_hostname'); + $data['config_mail_smtp_username'] = $this->config->get('config_mail_smtp_username'); + $data['config_mail_smtp_password'] = $this->config->get('config_mail_smtp_password'); + + if ($this->config->has('config_mail_smtp_port')) { + $data['config_mail_smtp_port'] = $this->config->get('config_mail_smtp_port'); + } else { + $data['config_mail_smtp_port'] = 25; + } + + if ($this->config->has('config_mail_smtp_timeout')) { + $data['config_mail_smtp_timeout'] = $this->config->get('config_mail_smtp_timeout'); + } else { + $data['config_mail_smtp_timeout'] = 5; + } + + if ($this->config->has('config_mail_alert')) { + $data['config_mail_alert'] = $this->config->get('config_mail_alert'); + } else { + $data['config_mail_alert'] = []; + } + + $data['mail_alerts'] = []; + + $data['mail_alerts'][] = [ + 'text' => $this->language->get('text_mail_account'), + 'value' => 'account' + ]; + + $data['mail_alerts'][] = [ + 'text' => $this->language->get('text_mail_affiliate'), + 'value' => 'affiliate' + ]; + + $data['mail_alerts'][] = [ + 'text' => $this->language->get('text_mail_order'), + 'value' => 'order' + ]; + + $data['mail_alerts'][] = [ + 'text' => $this->language->get('text_mail_review'), + 'value' => 'review' + ]; + + $data['config_mail_alert_email'] = $this->config->get('config_mail_alert_email'); + + // Server + $data['config_maintenance'] = $this->config->get('config_maintenance'); + + if ($this->config->has('config_session_expire')) { + $data['config_session_expire'] = $this->config->get('config_session_expire'); + } else { + $data['config_session_expire'] = 3600; + } + + $data['config_session_samesite'] = $this->config->get('config_session_samesite'); + $data['config_seo_url'] = $this->config->get('config_seo_url'); + $data['config_robots'] = $this->config->get('config_robots'); + $data['config_compression'] = $this->config->get('config_compression'); + + // Security + $data['config_security'] = $this->config->get('config_security'); + $data['config_shared'] = $this->config->get('config_shared'); + $data['config_encryption'] = $this->config->get('config_encryption'); + + // Uploads + if ($this->config->get('config_file_max_size')) { + $data['config_file_max_size'] = $this->config->get('config_file_max_size'); + } else { + $data['config_file_max_size'] = 20; + } + + $data['config_file_ext_allowed'] = $this->config->get('config_file_ext_allowed'); + $data['config_file_mime_allowed'] = $this->config->get('config_file_mime_allowed'); + + // Errors + $data['config_error_display'] = $this->config->get('config_error_display'); + $data['config_error_log'] = $this->config->get('config_error_log'); + $data['config_error_filename'] = $this->config->get('config_error_filename'); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('setting/setting', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('setting/setting'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'setting/setting')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if (!$this->request->post['config_meta_title']) { + $json['error']['meta_title'] = $this->language->get('error_meta_title'); + } + + if (!$this->request->post['config_name']) { + $json['error']['name'] = $this->language->get('error_name'); + } + + if ((oc_strlen($this->request->post['config_owner']) < 3) || (oc_strlen($this->request->post['config_owner']) > 64)) { + $json['error']['owner'] = $this->language->get('error_owner'); + } + + if ((oc_strlen($this->request->post['config_address']) < 3) || (oc_strlen($this->request->post['config_address']) > 256)) { + $json['error']['address'] = $this->language->get('error_address'); + } + + if ((oc_strlen($this->request->post['config_email']) > 96) || !filter_var($this->request->post['config_email'], FILTER_VALIDATE_EMAIL)) { + $json['error']['email'] = $this->language->get('error_email'); + } + + if ((oc_strlen($this->request->post['config_telephone']) < 3) || (oc_strlen($this->request->post['config_telephone']) > 32)) { + $json['error']['telephone'] = $this->language->get('error_telephone'); + } + + if (!$this->request->post['config_product_description_length']) { + $json['error']['product_description_length'] = $this->language->get('error_product_description_length'); + } + + if (!$this->request->post['config_pagination']) { + $json['error']['pagination'] = $this->language->get('error_pagination'); + } + + if (!$this->request->post['config_pagination_admin']) { + $json['error']['pagination_admin'] = $this->language->get('error_pagination'); + } + + if (!$this->request->post['config_article_description_length']) { + $json['error']['article_description_length'] = $this->language->get('error_article_description_length'); + } + + if (!empty($this->request->post['config_customer_group_display']) && !in_array($this->request->post['config_customer_group_id'], $this->request->post['config_customer_group_display'])) { + $json['error']['customer_group_display'] = $this->language->get('error_customer_group_display'); + } + + if ($this->request->post['config_login_attempts'] < 1) { + $json['error']['login_attempts'] = $this->language->get('error_login_attempts'); + } + + if (!$this->request->post['config_customer_online_expire']) { + $json['error']['customer_online_expire'] = $this->language->get('error_customer_online_expire'); + } + + if (!$this->request->post['config_voucher_min']) { + $json['error']['voucher_min'] = $this->language->get('error_voucher_min'); + } + + if (!$this->request->post['config_voucher_max']) { + $json['error']['voucher_max'] = $this->language->get('error_voucher_max'); + } + + if (!isset($this->request->post['config_processing_status'])) { + $json['error']['processing_status'] = $this->language->get('error_processing_status'); + } + + if (!isset($this->request->post['config_complete_status'])) { + $json['error']['complete_status'] = $this->language->get('error_complete_status'); + } + + if (!$this->request->post['config_image_category_width'] || !$this->request->post['config_image_category_height']) { + $json['error']['image_category'] = $this->language->get('error_image_category'); + } + + if (!$this->request->post['config_image_thumb_width'] || !$this->request->post['config_image_thumb_height']) { + $json['error']['image_thumb'] = $this->language->get('error_image_thumb'); + } + + if (!$this->request->post['config_image_popup_width'] || !$this->request->post['config_image_popup_height']) { + $json['error']['image_popup'] = $this->language->get('error_image_popup'); + } + + if (!$this->request->post['config_image_product_width'] || !$this->request->post['config_image_product_height']) { + $json['error']['image_product'] = $this->language->get('error_image_product'); + } + + if (!$this->request->post['config_image_additional_width'] || !$this->request->post['config_image_additional_height']) { + $json['error']['image_additional'] = $this->language->get('error_image_additional'); + } + + if (!$this->request->post['config_image_related_width'] || !$this->request->post['config_image_related_height']) { + $json['error']['image_related'] = $this->language->get('error_image_related'); + } + + if (!$this->request->post['config_image_compare_width'] || !$this->request->post['config_image_compare_height']) { + $json['error']['image_compare'] = $this->language->get('error_image_compare'); + } + + if (!$this->request->post['config_image_wishlist_width'] || !$this->request->post['config_image_wishlist_height']) { + $json['error']['image_wishlist'] = $this->language->get('error_image_wishlist'); + } + + if (!$this->request->post['config_image_cart_width'] || !$this->request->post['config_image_cart_height']) { + $json['error']['image_cart'] = $this->language->get('error_image_cart'); + } + + if (!$this->request->post['config_image_location_width'] || !$this->request->post['config_image_location_height']) { + $json['error']['image_location'] = $this->language->get('error_image_location'); + } + + if ($this->request->post['config_security'] && !$this->request->post['config_mail_engine']) { + $json['error']['warning'] = $this->language->get('error_security'); + } + + if ((oc_strlen($this->request->post['config_encryption']) < 32) || (oc_strlen($this->request->post['config_encryption']) > 1024)) { + $json['error']['encryption'] = $this->language->get('error_encryption'); + } + + if (!$this->request->post['config_file_max_size']) { + $json['error']['file_max_size'] = $this->language->get('error_file_max_size'); + } + + $disallowed = [ + 'php', + 'php4', + 'php3' + ]; + + $extensions = explode("\n", $this->request->post['config_file_ext_allowed']); + + foreach ($extensions as $extension) { + if (in_array(trim($extension), $disallowed)) { + $json['error']['file_ext_allowed'] = $this->language->get('error_extension'); + + break; + } + } + + $disallowed = [ + 'php', + 'php4', + 'php3' + ]; + + $mimes = explode("\n", $this->request->post['config_file_mime_allowed']); + + foreach ($mimes as $mime) { + if (in_array(trim($mime), $disallowed)) { + $json['error']['file_mime_allowed'] = $this->language->get('error_mime'); + + break; + } + } + + if (!$this->request->post['config_error_filename']) { + $json['error']['error_filename'] = $this->language->get('error_log_required'); + } elseif (preg_match('/\.\.[\/\\\]?/', $this->request->post['config_error_filename'])) { + $json['error']['error_filename'] = $this->language->get('error_log_invalid'); + } elseif (substr($this->request->post['config_error_filename'], strrpos($this->request->post['config_error_filename'], '.')) != '.log') { + $json['error']['error_filename'] = $this->language->get('error_log_extension'); + } + + if (isset($json['error']) && !isset($json['error']['warning'])) { + $json['error']['warning'] = $this->language->get('error_warning'); + } + + if (!$json) { + $this->load->model('setting/setting'); + + $this->model_setting_setting->editSetting('config', $this->request->post); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function theme(): void { + if (isset($this->request->get['theme'])) { + $theme = basename($this->request->get['theme']); + } else { + $theme = ''; + } + + $this->load->model('setting/extension'); + + $extension_info = $this->model_setting_extension->getExtensionByCode('theme', $theme); + + if ($extension_info) { + $this->response->setOutput(HTTP_CATALOG . 'extension/' . $extension_info['extension'] . '/admin/view/image/' . $extension_info['code'] . '.png'); + } else { + $this->response->setOutput(HTTP_CATALOG . 'image/no_image.png'); + } + } +} diff --git a/admininistrator/controller/setting/store.php b/admininistrator/controller/setting/store.php new file mode 100644 index 0000000..08eb216 --- /dev/null +++ b/admininistrator/controller/setting/store.php @@ -0,0 +1,776 @@ +load->language('setting/store'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('setting/store', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('setting/store.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('setting/store.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('setting/store', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('setting/store'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('setting/store.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['stores'] = []; + + $store_total = 0; + + if ($page == 1) { + $store_total = 1; + + $data['stores'][] = [ + 'store_id' => 0, + 'name' => $this->config->get('config_name') . $this->language->get('text_default'), + 'url' => HTTP_CATALOG, + 'edit' => $this->url->link('setting/setting', 'user_token=' . $this->session->data['user_token']) + ]; + } + + $this->load->model('setting/store'); + + $this->load->model('setting/setting'); + + $store_total += $this->model_setting_store->getTotalStores(); + + $results = $this->model_setting_store->getStores(); + + foreach ($results as $result) { + $data['stores'][] = [ + 'store_id' => $result['store_id'], + 'name' => $result['name'], + 'url' => $result['url'], + 'edit' => $this->url->link('setting/store.form', 'user_token=' . $this->session->data['user_token'] . '&store_id=' . $result['store_id']) + ]; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $store_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('setting/store.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($store_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($store_total - $this->config->get('config_pagination_admin'))) ? $store_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $store_total, ceil($store_total / $this->config->get('config_pagination_admin'))); + + return $this->load->view('setting/store_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('setting/store'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['store_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('setting/store', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_settings'), + 'href' => $this->url->link('setting/store.form', 'user_token=' . $this->session->data['user_token'] . (isset($this->request->post['store_id']) ? '&store_id=' . $this->request->get['store_id'] : '') . $url) + ]; + + $data['save'] = $this->url->link('setting/store.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('setting/store', 'user_token=' . $this->session->data['user_token']); + + if (isset($this->request->get['store_id'])) { + $this->load->model('setting/setting'); + + $store_info = $this->model_setting_setting->getSetting('config', $this->request->get['store_id']); + } + + if (isset($this->request->get['store_id'])) { + $data['store_id'] = (int)$this->request->get['store_id']; + } else { + $data['store_id'] = 0; + } + + if (isset($store_info['config_url'])) { + $data['config_url'] = $store_info['config_url']; + } else { + $data['config_url'] = ''; + } + + if (isset($store_info['config_meta_title'])) { + $data['config_meta_title'] = $store_info['config_meta_title']; + } else { + $data['config_meta_title'] = ''; + } + + if (isset($store_info['config_meta_description'])) { + $data['config_meta_description'] = $store_info['config_meta_description']; + } else { + $data['config_meta_description'] = ''; + } + + if (isset($store_info['config_meta_keyword'])) { + $data['config_meta_keyword'] = $store_info['config_meta_keyword']; + } else { + $data['config_meta_keyword'] = ''; + } + + $data['themes'] = []; + + $this->load->model('setting/extension'); + + $extensions = $this->model_setting_extension->getExtensionsByType('theme'); + + foreach ($extensions as $extension) { + $this->load->language('extension/' . $extension['extension'] . '/theme/' . $extension['code'], 'extension'); + + $data['themes'][] = [ + 'text' => $this->language->get('extension_heading_title'), + 'value' => $extension['code'] + ]; + } + + if (isset($store_info['config_theme'])) { + $data['config_theme'] = $store_info['config_theme']; + } else { + $data['config_theme'] = ''; + } + + $this->load->model('design/layout'); + + $data['layouts'] = $this->model_design_layout->getLayouts(); + + if (isset($store_info['config_layout_id'])) { + $data['config_layout_id'] = $store_info['config_layout_id']; + } else { + $data['config_layout_id'] = ''; + } + + if (isset($store_info['config_name'])) { + $data['config_name'] = $store_info['config_name']; + } else { + $data['config_name'] = ''; + } + + if (isset($store_info['config_owner'])) { + $data['config_owner'] = $store_info['config_owner']; + } else { + $data['config_owner'] = ''; + } + + if (isset($store_info['config_address'])) { + $data['config_address'] = $store_info['config_address']; + } else { + $data['config_address'] = ''; + } + + if (isset($store_info['config_geocode'])) { + $data['config_geocode'] = $store_info['config_geocode']; + } else { + $data['config_geocode'] = ''; + } + + if (isset($store_info['config_email'])) { + $data['config_email'] = $store_info['config_email']; + } else { + $data['config_email'] = ''; + } + + if (isset($store_info['config_telephone'])) { + $data['config_telephone'] = $store_info['config_telephone']; + } else { + $data['config_telephone'] = ''; + } + + if (isset($store_info['config_image'])) { + $data['config_image'] = $store_info['config_image']; + } else { + $data['config_image'] = ''; + } + + $this->load->model('tool/image'); + + $data['placeholder'] = $this->model_tool_image->resize('no_image.png', 100, 100); + + if (is_file(DIR_IMAGE . html_entity_decode($data['config_image'], ENT_QUOTES, 'UTF-8'))) { + $data['thumb'] = $this->model_tool_image->resize(html_entity_decode($data['config_image'], ENT_QUOTES, 'UTF-8'), 750, 90); + } else { + $data['thumb'] = $data['placeholder']; + } + + if (isset($store_info['config_open'])) { + $data['config_open'] = $store_info['config_open']; + } else { + $data['config_open'] = ''; + } + + if (isset($store_info['config_comment'])) { + $data['config_comment'] = $store_info['config_comment']; + } else { + $data['config_comment'] = ''; + } + + $this->load->model('localisation/location'); + + $data['locations'] = $this->model_localisation_location->getLocations(); + + if (isset($store_info['config_location'])) { + $data['config_location'] = $store_info['config_location']; + } else { + $data['config_location'] = []; + } + + $this->load->model('localisation/country'); + + $data['countries'] = $this->model_localisation_country->getCountries(); + + if (isset($store_info['config_country_id'])) { + $data['config_country_id'] = $store_info['config_country_id']; + } else { + $data['config_country_id'] = $this->config->get('config_country_id'); + } + + if (isset($store_info['config_zone_id'])) { + $data['config_zone_id'] = $store_info['config_zone_id']; + } else { + $data['config_zone_id'] = $this->config->get('config_zone_id'); + } + + $this->load->model('localisation/language'); + + $data['languages'] = $this->model_localisation_language->getLanguages(); + + if (isset($store_info['config_language'])) { + $data['config_language'] = $store_info['config_language']; + } else { + $data['config_language'] = $this->config->get('config_language'); + } + + $this->load->model('localisation/currency'); + + $data['currencies'] = $this->model_localisation_currency->getCurrencies(); + + if (isset($store_info['config_currency'])) { + $data['config_currency'] = $store_info['config_currency']; + } else { + $data['config_currency'] = $this->config->get('config_currency'); + } + + // Options + if (isset($store_info['config_product_description_length'])) { + $data['config_product_description_length'] = $store_info['config_product_description_length']; + } else { + $data['config_product_description_length'] = 100; + } + + if (isset($store_info['config_pagination'])) { + $data['config_pagination'] = $store_info['config_pagination']; + } else { + $data['config_pagination'] = 15; + } + + if (isset($store_info['config_product_count'])) { + $data['config_product_count'] = $store_info['config_product_count']; + } else { + $data['config_product_count'] = 10; + } + + if (isset($store_info['config_cookie_id'])) { + $data['config_cookie_id'] = $store_info['config_cookie_id']; + } else { + $data['config_cookie_id'] = ''; + } + + if (isset($store_info['config_gdpr_id'])) { + $data['config_gdpr_id'] = $store_info['config_gdpr_id']; + } else { + $data['config_gdpr_id'] = ''; + } + + if (isset($store_info['config_tax'])) { + $data['config_tax'] = $store_info['config_tax']; + } else { + $data['config_tax'] = ''; + } + + if (isset($store_info['config_tax_default'])) { + $data['config_tax_default'] = $store_info['config_tax_default']; + } else { + $data['config_tax_default'] = ''; + } + + if (isset($store_info['config_tax_customer'])) { + $data['config_tax_customer'] = $store_info['config_tax_customer']; + } else { + $data['config_tax_customer'] = ''; + } + + $this->load->model('customer/customer_group'); + + $data['customer_groups'] = $this->model_customer_customer_group->getCustomerGroups(); + + if (isset($store_info['config_customer_group_id'])) { + $data['config_customer_group_id'] = $store_info['config_customer_group_id']; + } else { + $data['config_customer_group_id'] = ''; + } + + if (isset($store_info['config_customer_group_display'])) { + $data['config_customer_group_display'] = $store_info['config_customer_group_display']; + } else { + $data['config_customer_group_display'] = []; + } + + if (isset($store_info['config_customer_price'])) { + $data['config_customer_price'] = $store_info['config_customer_price']; + } else { + $data['config_customer_price'] = ''; + } + + $this->load->model('catalog/information'); + + $data['informations'] = $this->model_catalog_information->getInformations(); + + if (isset($store_info['config_account_id'])) { + $data['config_account_id'] = $store_info['config_account_id']; + } else { + $data['config_account_id'] = ''; + } + + if (isset($store_info['config_cart_weight'])) { + $data['config_cart_weight'] = $store_info['config_cart_weight']; + } else { + $data['config_cart_weight'] = ''; + } + + if (isset($store_info['config_checkout_guest'])) { + $data['config_checkout_guest'] = $store_info['config_checkout_guest']; + } else { + $data['config_checkout_guest'] = ''; + } + + if (isset($store_info['config_checkout_id'])) { + $data['config_checkout_id'] = $store_info['config_checkout_id']; + } else { + $data['config_checkout_id'] = ''; + } + + if (isset($store_info['config_stock_display'])) { + $data['config_stock_display'] = $store_info['config_stock_display']; + } else { + $data['config_stock_display'] = ''; + } + + if (isset($store_info['config_stock_checkout'])) { + $data['config_stock_checkout'] = $store_info['config_stock_checkout']; + } else { + $data['config_stock_checkout'] = ''; + } + + // Images + if (isset($store_info['config_logo'])) { + $data['config_logo'] = $store_info['config_logo']; + } else { + $data['config_logo'] = ''; + } + + $this->load->model('tool/image'); + + $data['placeholder'] = $this->model_tool_image->resize('no_image.png', 100, 100); + + if (is_file(DIR_IMAGE . html_entity_decode($data['config_logo'], ENT_QUOTES, 'UTF-8'))) { + $data['logo'] = $this->model_tool_image->resize(html_entity_decode($data['config_logo'], ENT_QUOTES, 'UTF-8'), 100, 100); + } else { + $data['logo'] = $data['placeholder']; + } + + if (isset($store_info['config_image_category_width'])) { + $data['config_image_category_width'] = $store_info['config_image_category_width']; + } else { + $data['config_image_category_width'] = 80; + } + + if (isset($store_info['config_image_category_height'])) { + $data['config_image_category_height'] = $store_info['config_image_category_height']; + } else { + $data['config_image_category_height'] = 80; + } + + if (isset($store_info['config_image_thumb_width'])) { + $data['config_image_thumb_width'] = $store_info['config_image_thumb_width']; + } else { + $data['config_image_thumb_width'] = 228; + } + + if (isset($store_info['config_image_thumb_height'])) { + $data['config_image_thumb_height'] = $store_info['config_image_thumb_height']; + } else { + $data['config_image_thumb_height'] = 228; + } + + if (isset($store_info['config_image_popup_width'])) { + $data['config_image_popup_width'] = $store_info['config_image_popup_width']; + } else { + $data['config_image_popup_width'] = 500; + } + + if (isset($store_info['config_image_popup_height'])) { + $data['config_image_popup_height'] = $store_info['config_image_popup_height']; + } else { + $data['config_image_popup_height'] = 500; + } + + if (isset($store_info['config_image_product_width'])) { + $data['config_image_product_width'] = $store_info['config_image_product_width']; + } else { + $data['config_image_product_width'] = 228; + } + + if (isset($store_info['config_image_product_height'])) { + $data['config_image_product_height'] = $store_info['config_image_product_height']; + } else { + $data['config_image_product_height'] = 228; + } + + if (isset($store_info['config_image_additional_width'])) { + $data['config_image_additional_width'] = $store_info['config_image_additional_width']; + } else { + $data['config_image_additional_width'] = 74; + } + + if (isset($store_info['config_image_additional_height'])) { + $data['config_image_additional_height'] = $store_info['config_image_additional_height']; + } else { + $data['config_image_additional_height'] = 74; + } + + if (isset($store_info['config_image_related_width'])) { + $data['config_image_related_width'] = $store_info['config_image_related_width']; + } else { + $data['config_image_related_width'] = 80; + } + + if (isset($store_info['config_image_related_height'])) { + $data['config_image_related_height'] = $store_info['config_image_related_height']; + } else { + $data['config_image_related_height'] = 80; + } + + if (isset($store_info['config_image_blog_width'])) { + $data['config_image_blog_width'] = $store_info['config_image_blog_width']; + } else { + $data['config_image_blog_width'] = 90; + } + + if (isset($store_info['config_image_blog_height'])) { + $data['config_image_blog_height'] = $store_info['config_image_blog_height']; + } else { + $data['config_image_blog_height'] = 90; + } + + if (isset($store_info['config_image_compare_width'])) { + $data['config_image_compare_width'] = $store_info['config_image_compare_width']; + } else { + $data['config_image_compare_width'] = 90; + } + + if (isset($store_info['config_image_compare_height'])) { + $data['config_image_compare_height'] = $store_info['config_image_compare_height']; + } else { + $data['config_image_compare_height'] = 90; + } + + if (isset($store_info['config_image_wishlist_width'])) { + $data['config_image_wishlist_width'] = $store_info['config_image_wishlist_width']; + } else { + $data['config_image_wishlist_width'] = 47; + } + + if (isset($store_info['config_image_wishlist_height'])) { + $data['config_image_wishlist_height'] = $store_info['config_image_wishlist_height']; + } else { + $data['config_image_wishlist_height'] = 47; + } + + if (isset($store_info['config_image_cart_width'])) { + $data['config_image_cart_width'] = $store_info['config_image_cart_width']; + } else { + $data['config_image_cart_width'] = 47; + } + + if (isset($store_info['config_image_cart_height'])) { + $data['config_image_cart_height'] = $store_info['config_image_cart_height']; + } else { + $data['config_image_cart_height'] = 47; + } + + if (isset($store_info['config_image_location_width'])) { + $data['config_image_location_width'] = $store_info['config_image_location_width']; + } else { + $data['config_image_location_width'] = 268; + } + + if (isset($store_info['config_image_location_height'])) { + $data['config_image_location_height'] = $store_info['config_image_location_height']; + } else { + $data['config_image_location_height'] = 50; + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('setting/store_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('setting/store'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'setting/store')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if (!$this->request->post['config_url']) { + $json['error']['url'] = $this->language->get('error_url'); + } + + if (!$this->request->post['config_meta_title']) { + $json['error']['meta_title'] = $this->language->get('error_meta_title'); + } + + if (!$this->request->post['config_name']) { + $json['error']['name'] = $this->language->get('error_name'); + } + + if ((oc_strlen($this->request->post['config_owner']) < 3) || (oc_strlen($this->request->post['config_owner']) > 64)) { + $json['error']['owner'] = $this->language->get('error_owner'); + } + + if ((oc_strlen($this->request->post['config_address']) < 3) || (oc_strlen($this->request->post['config_address']) > 256)) { + $json['error']['address'] = $this->language->get('error_address'); + } + + if ((oc_strlen($this->request->post['config_email']) > 96) || !filter_var($this->request->post['config_email'], FILTER_VALIDATE_EMAIL)) { + $json['error']['email'] = $this->language->get('error_email'); + } + + if ((oc_strlen($this->request->post['config_telephone']) < 3) || (oc_strlen($this->request->post['config_telephone']) > 32)) { + $json['error']['telephone'] = $this->language->get('error_telephone'); + } + + if (!empty($this->request->post['config_customer_group_display']) && !in_array($this->request->post['config_customer_group_id'], $this->request->post['config_customer_group_display'])) { + $json['error']['customer_group_display'] = $this->language->get('error_customer_group_display'); + } + + if (!$this->request->post['config_product_description_length']) { + $json['error']['product_description_length'] = $this->language->get('error_product_description_length'); + } + + if (!$this->request->post['config_pagination']) { + $json['error']['pagination'] = $this->language->get('error_pagination'); + } + + if (!$this->request->post['config_image_category_width'] || !$this->request->post['config_image_category_height']) { + $json['error']['image_category'] = $this->language->get('error_image_category'); + } + + if (!$this->request->post['config_image_thumb_width'] || !$this->request->post['config_image_thumb_height']) { + $json['error']['image_thumb'] = $this->language->get('error_image_thumb'); + } + + if (!$this->request->post['config_image_popup_width'] || !$this->request->post['config_image_popup_height']) { + $json['error']['image_popup'] = $this->language->get('error_image_popup'); + } + + if (!$this->request->post['config_image_product_width'] || !$this->request->post['config_image_product_height']) { + $json['error']['image_product'] = $this->language->get('error_image_product'); + } + + if (!$this->request->post['config_image_additional_width'] || !$this->request->post['config_image_additional_height']) { + $json['error']['image_additional'] = $this->language->get('error_image_additional'); + } + + if (!$this->request->post['config_image_related_width'] || !$this->request->post['config_image_related_height']) { + $json['error']['image_related'] = $this->language->get('error_image_related'); + } + + if (!$this->request->post['config_image_compare_width'] || !$this->request->post['config_image_compare_height']) { + $json['error']['image_compare'] = $this->language->get('error_image_compare'); + } + + if (!$this->request->post['config_image_wishlist_width'] || !$this->request->post['config_image_wishlist_height']) { + $json['error']['image_wishlist'] = $this->language->get('error_image_wishlist'); + } + + if (!$this->request->post['config_image_cart_width'] || !$this->request->post['config_image_cart_height']) { + $json['error']['image_cart'] = $this->language->get('error_image_cart'); + } + + if (!$this->request->post['config_image_location_width'] || !$this->request->post['config_image_location_height']) { + $json['error']['image_location'] = $this->language->get('error_image_location'); + } + + if (isset($json['error']) && !isset($json['error']['warning'])) { + $json['error']['warning'] = $this->language->get('error_warning'); + } + + if (!$json) { + $this->load->model('setting/setting'); + + $this->load->model('setting/store'); + + if (!$this->request->post['store_id']) { + $json['store_id'] = $this->model_setting_store->addStore($this->request->post); + + $this->model_setting_setting->editSetting('config', $this->request->post, $json['store_id']); + } else { + $this->model_setting_store->editStore($this->request->post['store_id'], $this->request->post); + + $this->model_setting_setting->editSetting('config', $this->request->post, $this->request->post['store_id']); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('setting/store'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'setting/store')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('sale/order'); + $this->load->model('sale/subscription'); + + foreach ($selected as $store_id) { + if (!$store_id) { + $json['error'] = $this->language->get('error_default'); + } + + $order_total = $this->model_sale_order->getTotalOrdersByStoreId($store_id); + + if ($order_total) { + $json['error'] = sprintf($this->language->get('error_store'), $order_total); + } + + $subscription_total = $this->model_sale_subscription->getTotalSubscriptionsByStoreId($store_id); + + if ($subscription_total) { + $json['error'] = sprintf($this->language->get('error_store'), $subscription_total); + } + } + + if (!$json) { + $this->load->model('setting/store'); + + $this->load->model('setting/setting'); + + foreach ($selected as $store_id) { + $this->model_setting_store->deleteStore($store_id); + + $this->model_setting_setting->deleteSetting('config', $store_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/startup/application.php b/admininistrator/controller/startup/application.php new file mode 100644 index 0000000..8bfe77f --- /dev/null +++ b/admininistrator/controller/startup/application.php @@ -0,0 +1,44 @@ +registry->set('url', new \Opencart\System\Library\Url($this->config->get('site_url'))); + + // Customer + $this->registry->set('customer', new \Opencart\System\Library\Cart\Customer($this->registry)); + + // Currency + $this->registry->set('currency', new \Opencart\System\Library\Cart\Currency($this->registry)); + + // Tax + $this->registry->set('tax', new \Opencart\System\Library\Cart\Tax($this->registry)); + + if ($this->config->get('config_tax_default') == 'shipping') { + $this->tax->setShippingAddress((int)$this->config->get('config_country_id'), (int)$this->config->get('config_zone_id')); + } + + if ($this->config->get('config_tax_default') == 'payment') { + $this->tax->setPaymentAddress((int)$this->config->get('config_country_id'), (int)$this->config->get('config_zone_id')); + } + + $this->tax->setStoreAddress((int)$this->config->get('config_country_id'), (int)$this->config->get('config_zone_id')); + + // Weight + $this->registry->set('weight', new \Opencart\System\Library\Cart\Weight($this->registry)); + + // Length + $this->registry->set('length', new \Opencart\System\Library\Cart\Length($this->registry)); + + // Cart + $this->registry->set('cart', new \Opencart\System\Library\Cart\Cart($this->registry)); + } +} diff --git a/admininistrator/controller/startup/authorize.php b/admininistrator/controller/startup/authorize.php new file mode 100644 index 0000000..14f4ebf --- /dev/null +++ b/admininistrator/controller/startup/authorize.php @@ -0,0 +1,55 @@ +request->get['route'])) { + $route = (string)$this->request->get['route']; + } else { + $route = ''; + } + + if (isset($this->request->cookie['authorize'])) { + $token = (string)$this->request->cookie['authorize']; + } else { + $token = ''; + } + + // Remove any method call for checking ignore pages. + $pos = strrpos($route, '.'); + + if ($pos !== false) { + $route = substr($route, 0, $pos); + } + + $ignore = [ + 'common/login', + 'common/logout', + 'common/forgotten', + 'common/authorize' + ]; + + if ($this->config->get('config_security') && !in_array($route, $ignore)) { + $this->load->model('user/user'); + + $token_info = $this->model_user_user->getAuthorizeByToken($this->user->getId(), $token); + + if (!$token_info || !$token_info['status'] && $token_info['attempts'] <= 2) { + return new \Opencart\System\Engine\Action('common/authorize'); + } + + if ($token_info && !$token_info['status'] && $token_info['attempts'] > 2) { + return new \Opencart\System\Engine\Action('common/authorize.unlock'); + } + } + + return null; + } +} \ No newline at end of file diff --git a/admininistrator/controller/startup/error.php b/admininistrator/controller/startup/error.php new file mode 100644 index 0000000..389fab9 --- /dev/null +++ b/admininistrator/controller/startup/error.php @@ -0,0 +1,85 @@ +registry->set('log', new \Opencart\System\Library\Log($this->config->get('config_error_filename') ? $this->config->get('config_error_filename') : $this->config->get('error_filename'))); + + set_error_handler([$this, 'error']); + set_exception_handler([$this, 'exception']); + } + + /** + * @param string $code + * @param string $message + * @param string $file + * @param string $line + * + * @return bool + */ + public function error(string $code, string $message, string $file, string $line): bool { + switch ($code) { + case E_NOTICE: + case E_USER_NOTICE: + $error = 'Notice'; + break; + case E_WARNING: + case E_USER_WARNING: + $error = 'Warning'; + break; + case E_ERROR: + case E_USER_ERROR: + $error = 'Fatal Error'; + break; + default: + $error = 'Unknown'; + break; + } + + if ($this->config->get('config_error_log')) { + $sting = 'PHP ' . $error . ': ' . $message . "\n"; + $sting .= 'File: ' . $file . "\n"; + $sting .= 'Line: ' . $line . "\n"; + + $this->log->write($sting); + } + + if ($this->config->get('config_error_display')) { + echo '' . $error . ': ' . $message . ' in ' . $file . ' on line ' . $line . ''; + } else { + header('Location: ' . $this->config->get('error_page')); + exit(); + } + + return true; + } + + /** + * @param \Throwable $e + * + * @return void + */ + public function exception(\Throwable $e): void { + if ($this->config->get('config_error_log')) { + $sting = $e->getCode() . ': ' . $e->getMessage() . "\n"; + $sting .= 'File: ' . $e->getFile() . "\n"; + $sting .= 'Line: ' . $e->getLine() . "\n"; + + $this->log->write($sting); + } + + if ($this->config->get('config_error_display')) { + echo '' . $e->getMessage() . ': in ' . $e->getFile() . ' on line ' . $e->getLine() . ''; + } else { + header('Location: ' . $this->config->get('error_page')); + exit(); + } + } +} diff --git a/admininistrator/controller/startup/event.php b/admininistrator/controller/startup/event.php new file mode 100644 index 0000000..7b72e70 --- /dev/null +++ b/admininistrator/controller/startup/event.php @@ -0,0 +1,34 @@ +load->model('setting/event'); + + $results = $this->model_setting_event->getEvents(); + + foreach ($results as $result) { + if ($result['status']) { + $part = explode('/', $result['trigger']); + + if ($part[0] == 'admin') { + array_shift($part); + + $this->event->register(implode('/', $part), new \Opencart\System\Engine\Action($result['action']), $result['sort_order']); + } + + if ($part[0] == 'system') { + $this->event->register($result['trigger'], new \Opencart\System\Engine\Action($result['action']), $result['sort_order']); + } + } + } + } +} \ No newline at end of file diff --git a/admininistrator/controller/startup/extension.php b/admininistrator/controller/startup/extension.php new file mode 100644 index 0000000..3dc6719 --- /dev/null +++ b/admininistrator/controller/startup/extension.php @@ -0,0 +1,36 @@ +load->model('setting/extension'); + + $results = $this->model_setting_extension->getInstalls(); + + foreach ($results as $result) { + $extension = str_replace(['_', '/'], ['', '\\'], ucwords($result['code'], '_/')); + + // Register controllers, models and system extension folders + $this->autoloader->register('Opencart\Admin\Controller\Extension\\' . $extension, DIR_EXTENSION . $result['code'] . '/admin/controller/'); + $this->autoloader->register('Opencart\Admin\Model\Extension\\' . $extension, DIR_EXTENSION . $result['code'] . '/admin/model/'); + $this->autoloader->register('Opencart\System\Library\Extension\\' . $extension, DIR_EXTENSION . $result['code'] . '/system/library/'); + + // Template directory + $this->template->addPath('extension/' . $result['code'], DIR_EXTENSION . $result['code'] . '/admin/view/template/'); + + // Language directory + $this->language->addPath('extension/' . $result['code'], DIR_EXTENSION . $result['code'] . '/admin/language/'); + + // Config directory + $this->config->addPath('extension/' . $result['code'], DIR_EXTENSION . $result['code'] . '/system/config/'); + } + } +} \ No newline at end of file diff --git a/admininistrator/controller/startup/language.php b/admininistrator/controller/startup/language.php new file mode 100644 index 0000000..26852d0 --- /dev/null +++ b/admininistrator/controller/startup/language.php @@ -0,0 +1,79 @@ +request->cookie['language'])) { + $code = (string)$this->request->cookie['language']; + } else { + $code = $this->config->get('config_language_admin'); + } + + $this->load->model('localisation/language'); + + self::$languages = $this->model_localisation_language->getLanguages(); + + if (isset(self::$languages[$code])) { + $language_info = self::$languages[$code]; + + // Language + if ($language_info['extension']) { + $this->language->addPath('extension/' . $language_info['extension'], DIR_EXTENSION . $language_info['extension'] . '/admin/language/'); + } + + // Set the config language_id key + $this->config->set('config_language_id', $language_info['language_id']); + $this->config->set('config_language_admin', $language_info['code']); + + $this->load->language('default'); + } + } + + // Fill the language up with default values + + /** + * @param $route + * @param $prefix + * @param $code + * @param $output + * + * @return void + */ + public function after(&$route, &$prefix, &$code, &$output): void { + if (!$code) { + $code = $this->config->get('config_language_admin'); + } + + // Use $this->language->load so it's not triggering infinite loops + $this->language->load($route, $prefix, $code); + + if (isset(self::$languages[$code])) { + $language_info = self::$languages[$code]; + + $path = ''; + + if ($language_info['extension']) { + $extension = 'extension/' . $language_info['extension']; + + if (oc_substr($route, 0, strlen($extension)) != $extension) { + $path = $extension . '/'; + } + } + + // Use $this->language->load so it's not triggering infinite loops + $this->language->load($path . $route, $prefix, $code); + } + } +} diff --git a/admininistrator/controller/startup/login.php b/admininistrator/controller/startup/login.php new file mode 100644 index 0000000..edd9607 --- /dev/null +++ b/admininistrator/controller/startup/login.php @@ -0,0 +1,54 @@ +request->get['route'])) { + $route = (string)$this->request->get['route']; + } else { + $route = ''; + } + + // Remove any method call for checking ignore pages. + $pos = strrpos($route, '.'); + + if ($pos !== false) { + $route = substr($route, 0, $pos); + } + + $ignore = [ + 'common/login', + 'common/forgotten', + 'common/language' + ]; + + // User + $this->registry->set('user', new \Opencart\System\Library\Cart\User($this->registry)); + + if (!$this->user->isLogged() && !in_array($route, $ignore)) { + return new \Opencart\System\Engine\Action('common/login'); + } + + $ignore = [ + 'common/login', + 'common/logout', + 'common/forgotten', + 'common/language', + 'error/not_found', + 'error/permission' + ]; + + if (!in_array($route, $ignore) && (!isset($this->request->get['user_token']) || !isset($this->session->data['user_token']) || ($this->request->get['user_token'] != $this->session->data['user_token']))) { + return new \Opencart\System\Engine\Action('common/login'); + } + + return null; + } +} diff --git a/admininistrator/controller/startup/notification.php b/admininistrator/controller/startup/notification.php new file mode 100644 index 0000000..ed94b11 --- /dev/null +++ b/admininistrator/controller/startup/notification.php @@ -0,0 +1,56 @@ +request->cookie['notification'])) { + $curl = curl_init(); + + // Gets the latest information from opencart.com about news, updates and security. + curl_setopt($curl, CURLOPT_URL, OPENCART_SERVER . 'index.php?route=api/notification'); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_HEADER, false); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 30); + curl_setopt($curl, CURLOPT_TIMEOUT, 30); + + $response = curl_exec($curl); + + curl_close($curl); + + if ($response) { + $notification = json_decode($response, true); + } else { + $notification = ''; + } + + if (isset($notification['notification'])) { + foreach ($notification['notifications'] as $result) { + $notification_info = $this->model_notification->addNotification($result['notification_id']); + + if (!$notification_info) { + $this->model_notification->addNotification($result); + } + } + } + + // Only grab the + $option = [ + 'expires' => time() + 3600 * 24 * 7, + 'path' => $this->config->get('session_path'), + 'secure' => $this->request->server['HTTPS'], + 'httponly' => false, + 'SameSite' => $this->config->get('config_session_samesite') + ]; + + setcookie('notification', true, $option); + } + } +} \ No newline at end of file diff --git a/admininistrator/controller/startup/permission.php b/admininistrator/controller/startup/permission.php new file mode 100644 index 0000000..0f73baa --- /dev/null +++ b/admininistrator/controller/startup/permission.php @@ -0,0 +1,41 @@ +request->get['route'])) { + $pos = strrpos($this->request->get['route'], '.'); + + if ($pos === false) { + $route = $this->request->get['route']; + } else { + $route = substr($this->request->get['route'], 0, $pos); + } + + // We want to ignore some pages from having its permission checked. + $ignore = [ + 'common/dashboard', + 'common/login', + 'common/logout', + 'common/forgotten', + 'common/authorize', + 'common/language', + 'error/not_found', + 'error/permission' + ]; + + if (!in_array($route, $ignore) && !$this->user->hasPermission('access', $route)) { + return new \Opencart\System\Engine\Action('error/permission'); + } + } + + return null; + } +} diff --git a/admininistrator/controller/startup/sass.php b/admininistrator/controller/startup/sass.php new file mode 100644 index 0000000..eb5a24f --- /dev/null +++ b/admininistrator/controller/startup/sass.php @@ -0,0 +1,44 @@ +config->get('developer_sass')) { + $scss = new \ScssPhp\ScssPhp\Compiler(); + $scss->setImportPaths(DIR_APPLICATION . 'view/stylesheet/'); + + $output = $scss->compileString('@import "' . $filename . '.scss"')->getCss(); + + $handle = fopen($stylesheet, 'w'); + + flock($handle, LOCK_EX); + + fwrite($handle, $output); + + fflush($handle); + + flock($handle, LOCK_UN); + + fclose($handle); + } + } + } + } +} diff --git a/admininistrator/controller/startup/session.php b/admininistrator/controller/startup/session.php new file mode 100644 index 0000000..b97ebd8 --- /dev/null +++ b/admininistrator/controller/startup/session.php @@ -0,0 +1,41 @@ +config->get('session_engine'), $this->registry); + $this->registry->set('session', $session); + + if (isset($this->request->cookie[$this->config->get('session_name')])) { + $session_id = $this->request->cookie[$this->config->get('session_name')]; + } else { + $session_id = ''; + } + + $session->start($session_id); + + // Update the session lifetime + if ($this->config->get('config_session_expire')) { + $this->config->set('session_expire', $this->config->get('config_session_expire')); + } + + // Require higher security for session cookies + $option = [ + 'expires' => $this->config->get('config_session_expire') ? time() + (int)$this->config->get('config_session_expire') : 0, + 'path' => $this->config->get('session_path'), + 'secure' => $this->request->server['HTTPS'], + 'httponly' => false, + 'SameSite' => $this->config->get('config_session_samesite') + ]; + + setcookie($this->config->get('session_name'), $session->getId(), $option); + } +} \ No newline at end of file diff --git a/admininistrator/controller/startup/setting.php b/admininistrator/controller/startup/setting.php new file mode 100644 index 0000000..b613fc6 --- /dev/null +++ b/admininistrator/controller/startup/setting.php @@ -0,0 +1,39 @@ +load->model('setting/setting'); + + // Settings + $results = $this->model_setting_setting->getSettings(0); + + foreach ($results as $result) { + if (!$result['serialized']) { + $this->config->set($result['key'], $result['value']); + } else { + $this->config->set($result['key'], json_decode($result['value'], true)); + } + } + + // Set time zone + if ($this->config->get('config_timezone')) { + date_default_timezone_set($this->config->get('config_timezone')); + + // Sync PHP and DB time zones. + $this->db->query("SET time_zone = '" . $this->db->escape(date('P')) . "'"); + } + + // Response output compression level + if ($this->config->get('config_compression')) { + $this->response->setCompression((int)$this->config->get('config_compression')); + } + } +} diff --git a/admininistrator/controller/startup/startup.php b/admininistrator/controller/startup/startup.php new file mode 100644 index 0000000..c9f40ef --- /dev/null +++ b/admininistrator/controller/startup/startup.php @@ -0,0 +1,24 @@ +load->model('setting/startup'); + + $results = $this->model_setting_startup->getStartups(); + + foreach ($results as $result) { + if ((substr($result['action'], 0, 6) == 'admin/') && $result['status']) { + $this->load->controller(substr($result['action'], 6)); + } + } + } +} \ No newline at end of file diff --git a/admininistrator/controller/tool/backup.php b/admininistrator/controller/tool/backup.php new file mode 100644 index 0000000..f122298 --- /dev/null +++ b/admininistrator/controller/tool/backup.php @@ -0,0 +1,457 @@ +load->language('tool/backup'); + + $this->document->setTitle($this->language->get('heading_title')); + + // Use the ini_get('upload_max_filesize') for the max file size + $data['error_upload_size'] = sprintf($this->language->get('error_upload_size'), ini_get('upload_max_filesize')); + + $data['config_file_max_size'] = ((int)preg_filter('/[^0-9]/', '', ini_get('upload_max_filesize')) * 1024 * 1024); + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('tool/backup', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['upload'] = $this->url->link('tool/backup.upload', 'user_token=' . $this->session->data['user_token']); + + $this->load->model('tool/backup'); + + $ignore = [ + DB_PREFIX . 'user', + DB_PREFIX . 'user_group' + ]; + + $data['tables'] = []; + + $results = $this->model_tool_backup->getTables(); + + foreach ($results as $result) { + if (!in_array($result, $ignore)) { + $data['tables'][] = $result; + } + } + + $data['history'] = $this->getHistory(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('tool/backup', $data)); + } + + /** + * @return void + */ + public function history(): void { + $this->load->language('tool/backup'); + + $this->response->setOutput($this->getHistory()); + } + + /** + * @return string + */ + public function getHistory(): string { + $this->load->language('tool/backup'); + + $data['histories'] = []; + + $files = glob(DIR_STORAGE . 'backup/*.sql'); + + foreach ($files as $file) { + $size = filesize($file); + + $i = 0; + + $suffix = [ + 'B', + 'KB', + 'MB', + 'GB', + 'TB', + 'PB', + 'EB', + 'ZB', + 'YB' + ]; + + while (($size / 1024) > 1) { + $size = $size / 1024; + + $i++; + } + + $data['histories'][] = [ + 'filename' => basename($file), + 'size' => round(substr($size, 0, strpos($size, '.') + 4), 2) . $suffix[$i], + 'date_added' => date($this->language->get('datetime_format'), filemtime($file)), + 'download' => $this->url->link('tool/backup.download', 'user_token=' . $this->session->data['user_token'] . '&filename=' . urlencode(basename($file))), + ]; + } + + return $this->load->view('tool/backup_history', $data); + } + + /** + * @return void + */ + public function backup(): void { + $this->load->language('tool/backup'); + + $json = []; + + if (isset($this->request->get['filename'])) { + $filename = basename(html_entity_decode($this->request->get['filename'], ENT_QUOTES, 'UTF-8')); + } else { + $filename = date('Y-m-d H.i.s') . '.sql'; + } + + if (isset($this->request->get['table'])) { + $table = $this->request->get['table']; + } else { + $table = ''; + } + + if (isset($this->request->post['backup'])) { + $backup = $this->request->post['backup']; + } else { + $backup = []; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + if (!$this->user->hasPermission('modify', 'tool/backup')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('tool/backup'); + + $allowed = $this->model_tool_backup->getTables(); + + if (!in_array($table, $allowed)) { + $json['error'] = sprintf($this->language->get('error_table'), $table); + } + + if (!$json) { + $output = ''; + + if ($page == 1) { + $output .= 'TRUNCATE TABLE `' . $this->db->escape($table) . '`;' . "\n\n"; + } + + $record_total = $this->model_tool_backup->getTotalRecords($table); + + $results = $this->model_tool_backup->getRecords($table, ($page - 1) * 200, 200); + + foreach ($results as $result) { + $fields = ''; + + foreach (array_keys($result) as $value) { + $fields .= '`' . $value . '`, '; + } + + $values = ''; + + foreach (array_values($result) as $value) { + if ($value !== null) { + $value = str_replace(["\x00", "\x0a", "\x0d", "\x1a"], ['\0', '\n', '\r', '\Z'], $value); + $value = str_replace(["\n", "\r", "\t"], ['\n', '\r', '\t'], $value); + $value = str_replace('\\', '\\\\', $value); + $value = str_replace('\'', '\\\'', $value); + $value = str_replace('\\\n', '\n', $value); + $value = str_replace('\\\r', '\r', $value); + $value = str_replace('\\\t', '\t', $value); + + $values .= '\'' . $value . '\', '; + } else { + $values .= 'NULL, '; + } + } + + $output .= 'INSERT INTO `' . $table . '` (' . preg_replace('/, $/', '', $fields) . ') VALUES (' . preg_replace('/, $/', '', $values) . ');' . "\n"; + } + + $position = array_search($table, $backup); + + if (($page * 200) >= $record_total) { + $output .= "\n"; + + if (isset($backup[$position + 1])) { + $table = $backup[$position + 1]; + } else { + $table = ''; + } + } + + if ($position !== false) { + $json['progress'] = round(($position / count($backup)) * 100); + } else { + $json['progress'] = 0; + } + + $handle = fopen(DIR_STORAGE . 'backup/' . $filename, 'a'); + + fwrite($handle, $output); + + fclose($handle); + + if (!$table) { + $json['success'] = $this->language->get('text_success'); + } elseif (($page * 200) >= $record_total) { + $json['text'] = sprintf($this->language->get('text_backup'), $table, ($page - 1) * 200, $record_total); + + $json['next'] = $this->url->link('tool/backup.backup', 'user_token=' . $this->session->data['user_token'] . '&filename=' . urlencode($filename) . '&table=' . $table . '&page=1', true); + } else { + $json['text'] = sprintf($this->language->get('text_backup'), $table, ($page - 1) * 200, $page * 200); + + $json['next'] = $this->url->link('tool/backup.backup', 'user_token=' . $this->session->data['user_token'] . '&filename=' . urlencode($filename) . '&table=' . $table . '&page=' . ($page + 1), true); + } + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function restore(): void { + $this->load->language('tool/backup'); + + $json = []; + + if (isset($this->request->get['filename'])) { + $filename = basename(html_entity_decode($this->request->get['filename'], ENT_QUOTES, 'UTF-8')); + } else { + $filename = ''; + } + + if (isset($this->request->get['position'])) { + $position = $this->request->get['position']; + } else { + $position = 0; + } + + if (!$this->user->hasPermission('modify', 'tool/backup')) { + $json['error'] = $this->language->get('error_permission'); + } + + $file = DIR_STORAGE . 'backup/' . $filename; + + if (!is_file($file)) { + $json['error'] = $this->language->get('error_file'); + } + + if (!$json) { + // We set $i so we can batch execute the queries rather than do them all at once. + $i = 0; + $start = false; + + $handle = fopen($file, 'r'); + + fseek($handle, $position, SEEK_SET); + + while (!feof($handle) && ($i < 100)) { + $position = ftell($handle); + + $line = fgets($handle, 1000000); + + if (substr($line, 0, 14) == 'TRUNCATE TABLE' || substr($line, 0, 11) == 'INSERT INTO') { + $sql = ''; + + $start = true; + } + + if ($i > 0 && (substr($line, 0, strlen('TRUNCATE TABLE `' . DB_PREFIX . 'user`')) == 'TRUNCATE TABLE `' . DB_PREFIX . 'user`' || substr($line, 0, strlen('TRUNCATE TABLE `' . DB_PREFIX . 'user_group`')) == 'TRUNCATE TABLE `' . DB_PREFIX . 'user_group`')) { + fseek($handle, $position, SEEK_SET); + + break; + } + + if ($start) { + $sql .= $line; + } + + if ($start && substr($line, -2) == ";\n") { + $this->db->query(substr($sql, 0, strlen($sql) -2)); + + $start = false; + } + + $i++; + } + + $position = ftell($handle); + + $size = filesize($file); + + if ($position) { + $json['progress'] = round(($position / $size) * 100); + } else { + $json['progress'] = 0; + } + + if ($position && !feof($handle)) { + $json['text'] = sprintf($this->language->get('text_restore'), $position, $size); + + $json['next'] = $this->url->link('tool/backup.restore', 'user_token=' . $this->session->data['user_token'] . '&filename=' . urlencode($filename) . '&position=' . $position, true); + } else { + $json['success'] = $this->language->get('text_success'); + + $this->cache->delete('*'); + } + + fclose($handle); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function upload(): void { + $this->load->language('tool/backup'); + + $json = []; + + // Check user has permission + if (!$this->user->hasPermission('modify', 'tool/backup')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (empty($this->request->files['upload']['name']) || !is_file($this->request->files['upload']['tmp_name'])) { + $json['error'] = $this->language->get('error_upload'); + } + + if (!$json) { + // Sanitize the filename + $filename = basename(html_entity_decode($this->request->files['upload']['name'], ENT_QUOTES, 'UTF-8')); + + if ((oc_strlen($filename) < 3) || (oc_strlen($filename) > 128)) { + $json['error'] = $this->language->get('error_filename'); + } + + // Allowed file extension types + if (strtolower(substr(strrchr($filename, '.'), 1)) != 'sql') { + $json['error'] = $this->language->get('error_file_type'); + } + } + + if (!$json) { + move_uploaded_file($this->request->files['upload']['tmp_name'], DIR_STORAGE . 'backup/' . $filename); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function download(): void { + $this->load->language('tool/backup'); + + $json = []; + + if (isset($this->request->get['filename'])) { + $filename = basename(html_entity_decode($this->request->get['filename'], ENT_QUOTES, 'UTF-8')); + } else { + $filename = ''; + } + + // Check user has permission + if (!$this->user->hasPermission('modify', 'tool/backup')) { + $this->response->redirect($this->url->link('error/permission', 'user_token=' . $this->session->data['user_token'], true)); + } + + $file = DIR_STORAGE . 'backup/' . $filename; + + if (!is_file($file)) { + $this->response->redirect($this->url->link('error/not_found', 'user_token=' . $this->session->data['user_token'], true)); + } + + if (!headers_sent()) { + header('Content-Type: application/octet-stream'); + header('Content-Disposition: attachment; filename="' . $filename . '"'); + header('Expires: 0'); + header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); + header('Pragma: public'); + header('Content-Length: ' . filesize($file)); + + if (ob_get_level()) { + ob_end_clean(); + } + + readfile($file, 'rb'); + + exit(); + } else { + exit($this->language->get('error_headers_sent')); + } + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('tool/backup'); + + $json = []; + + if (isset($this->request->get['filename'])) { + $filename = basename(html_entity_decode($this->request->get['filename'], ENT_QUOTES, 'UTF-8')); + } else { + $filename = ''; + } + + // Check user has permission + if (!$this->user->hasPermission('modify', 'tool/backup')) { + $json['error'] = $this->language->get('error_permission'); + } + + $file = DIR_STORAGE . 'backup/' . $filename; + + if (!is_file($file)) { + $json['error'] = $this->language->get('error_file'); + } + + if (!$json) { + unlink($file); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/tool/log.php b/admininistrator/controller/tool/log.php new file mode 100644 index 0000000..3afe067 --- /dev/null +++ b/admininistrator/controller/tool/log.php @@ -0,0 +1,171 @@ +load->language('tool/log'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('tool/log', 'user_token=' . $this->session->data['user_token']) + ]; + + if (isset($this->session->data['error'])) { + $data['error_warning'] = $this->session->data['error']; + + unset($this->session->data['error']); + } else { + $data['error_warning'] = ''; + } + + $file = DIR_LOGS . $this->config->get('config_error_filename'); + + if (!is_file($file)) { + file_put_contents($file, '', FILE_APPEND); + } + + + $data['log'] = []; + + $files = glob(DIR_LOGS . '*.log'); + + foreach ($files as $file) { + $error = ''; + + $filename = basename($file); + + $size = filesize($file); + + if ($size >= 3145728) { + $suffix = [ + 'B', + 'KB', + 'MB', + 'GB', + 'TB', + 'PB', + 'EB', + 'ZB', + 'YB' + ]; + + $i = 0; + + while (($size / 1024) > 1) { + $size = $size / 1024; + $i++; + } + + $error = sprintf($this->language->get('error_size'), $filename, round(substr($size, 0, strpos($size, '.') + 4), 2) . $suffix[$i]); + } + + $handle = fopen($file, 'r+'); + + $data['logs'][] = [ + 'name' => $filename, + 'output' => fread($handle, 3145728), + 'download' => $this->url->link('tool/log.download', 'user_token=' . $this->session->data['user_token'] . '&filename=' . $filename), + 'clear' => $this->url->link('tool/log.clear', 'user_token=' . $this->session->data['user_token'] . '&filename=' . $filename), + 'error' => $error + ]; + + fclose($handle); + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('tool/log', $data)); + } + + /** + * @return void + */ + public function download(): void { + $this->load->language('tool/log'); + + if (isset($this->request->get['filename'])) { + $filename = (string)basename($this->request->get['filename']); + } else { + $filename = ''; + } + + $file = DIR_LOGS . $filename; + + if (!is_file($file)) { + $this->session->data['error'] = sprintf($this->language->get('error_file'), $filename); + + $this->response->redirect($this->url->link('tool/log', 'user_token=' . $this->session->data['user_token'], true)); + } + + if (!filesize($file)) { + $this->session->data['error'] = sprintf($this->language->get('error_empty'), $filename); + + $this->response->redirect($this->url->link('tool/log', 'user_token=' . $this->session->data['user_token'], true)); + } + + $this->response->addheader('Pragma: public'); + $this->response->addheader('Expires: 0'); + $this->response->addheader('Content-Description: File Transfer'); + $this->response->addheader('Content-Type: application/octet-stream'); + $this->response->addheader('Content-Disposition: attachment; filename="' . $this->config->get('config_name') . '_' . date('Y-m-d_H-i-s', time()) . '_error.log"'); + $this->response->addheader('Content-Transfer-Encoding: binary'); + + $this->response->setOutput(file_get_contents($file, FILE_USE_INCLUDE_PATH, null)); + } + + /** + * @return void + */ + public function clear(): void { + $this->load->language('tool/log'); + + if (isset($this->request->get['filename'])) { + $filename = (string)$this->request->get['filename']; + } else { + $filename = ''; + } + + $json = []; + + if (!$this->user->hasPermission('modify', 'tool/log')) { + $json['error'] = $this->language->get('error_permission'); + } + + $file = DIR_LOGS . $filename; + + if (!is_file($file)) { + $json['error'] = sprintf($this->language->get('error_file'), $filename); + } + + if (!$json) { + $handle = fopen($file, 'w+'); + + fclose($handle); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/tool/notification.php b/admininistrator/controller/tool/notification.php new file mode 100644 index 0000000..f871434 --- /dev/null +++ b/admininistrator/controller/tool/notification.php @@ -0,0 +1,178 @@ +load->language('tool/notification'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('tool/notification', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('tool/notification', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('tool/notification'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + public function getList(): string { + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['notifications'] = []; + + $this->load->model('tool/notification'); + + $notification_total = $this->model_tool_notification->getTotalNotifications(); + + $filter_data = [ + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $results = $this->model_tool_notification->getNotifications($filter_data); + + foreach ($results as $result) { + $second = time() - strtotime($result['date_added']); + + $ranges = [ + 'second' => $second, + 'minute' => floor($second / 60), + 'hour' => floor($second / 3600), + 'day' => floor($second / 86400), + 'week' => floor($second / 604800), + 'month' => floor($second / 2629743), + 'year' => floor($second / 31556926) + ]; + + foreach ($ranges as $range => $value) { + if ($value) { + $date_added = $value; + $code = $range . ($value > 1) ? 's' : ''; + } + } + + $data['notifications'][] = [ + 'notification_id' => $result['notification_id'], + 'title' => $result['title'], + 'status' => $result['status'], + 'date_added' => sprintf($this->language->get('text_' . $code . '_ago'), $date_added), + 'view' => $this->url->link('tool/notification.info', 'user_token=' . $this->session->data['user_token'] . '¬ification_id=' . $result['notification_id'] . $url), + 'delete' => $this->url->link('tool/notification.delete', 'user_token=' . $this->session->data['user_token'] . '¬ification_id=' . $result['notification_id'] . $url) + ]; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $notification_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('tool/notification.list', 'user_token=' . $this->session->data['user_token'] . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($notification_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($notification_total - $this->config->get('config_pagination_admin'))) ? $notification_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $notification_total, ceil($notification_total / $this->config->get('config_pagination_admin'))); + + return $this->load->view('tool/notification_list', $data); + } + + /** + * @return void + */ + public function info(): void { + if (isset($this->request->get['notification_id'])) { + $notification_id = $this->request->get['notification_id']; + } else { + $notification_id = 0; + } + + $this->load->model('tool/notification'); + + $notification_info = $this->model_tool_notification->getNotification($notification_id); + + if ($notification_info) { + $this->load->language('tool/notification'); + + $data['title'] = $notification_info['title']; + + $data['text'] = oc_bbcode_decode($notification_info['text']); + + $this->model_tool_notification->editStatus($notification_id, 1); + + $this->response->setOutput($this->load->view('tool/notification_info', $data)); + } + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('tool/notification'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'tool/notification')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('tool/notification'); + + foreach ($selected as $notification_id) { + $this->model_tool_notification->deleteNotification($notification_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/tool/upgrade.php b/admininistrator/controller/tool/upgrade.php new file mode 100644 index 0000000..b99febe --- /dev/null +++ b/admininistrator/controller/tool/upgrade.php @@ -0,0 +1,226 @@ +load->language('tool/upgrade'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('tool/upgrade', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['current_version'] = VERSION; + $data['upgrade'] = false; + + $curl = curl_init(OPENCART_SERVER . 'index.php?route=api/upgrade'); + + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_FORBID_REUSE, 1); + curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1); + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); + + $response = curl_exec($curl); + + curl_close($curl); + + $response_info = json_decode($response, true); + + if ($response_info) { + $data['latest_version'] = $response_info['version']; + $data['date_added'] = date($this->language->get('date_format_short'), strtotime($response_info['date_added'])); + $data['log'] = nl2br($response_info['log']); + + if (!version_compare(VERSION, $response_info['version'], '>=')) { + $data['upgrade'] = true; + } + } else { + $data['latest_version'] = ''; + $data['date_added'] = ''; + $data['log'] = ''; + } + + // For testing + //$data['latest_version'] = 'master'; + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('tool/upgrade', $data)); + } + + /** + * @return void + */ + public function download(): void { + $this->load->language('tool/upgrade'); + + $json = []; + + if (isset($this->request->get['version'])) { + $version = $this->request->get['version']; + } else { + $version = ''; + } + + if (!$this->user->hasPermission('modify', 'tool/upgrade')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (version_compare($version, VERSION, '<')) { + $json['error'] = $this->language->get('error_version'); + } + + $file = DIR_DOWNLOAD . 'opencart-' . $version . '.zip'; + + $handle = fopen($file, 'w'); + + set_time_limit(0); + + $curl = curl_init('https://github.com/opencart/opencart/archive/' . $version . '.zip'); + + curl_setopt($curl, CURLOPT_USERAGENT, 'OpenCart ' . VERSION); + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); + curl_setopt($curl, CURLOPT_FORBID_REUSE, 1); + curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1); + curl_setopt($curl, CURLOPT_TIMEOUT, 300); + curl_setopt($curl, CURLOPT_FILE, $handle); + + curl_exec($curl); + + fclose($handle); + + $status = curl_getinfo($curl, CURLINFO_HTTP_CODE); + + if ($status != 200) { + $json['error'] = $this->language->get('error_download'); + } + + curl_close($curl); + + if (!$json) { + $json['text'] = $this->language->get('text_install'); + + $json['next'] = $this->url->link('tool/upgrade.install', 'user_token=' . $this->session->data['user_token'] . '&version=' . $version, true); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function install(): void { + $this->load->language('tool/upgrade'); + + $json = []; + + if (isset($this->request->get['version'])) { + $version = $this->request->get['version']; + } else { + $version = ''; + } + + if (!$this->user->hasPermission('modify', 'tool/upgrade')) { + $json['error'] = $this->language->get('error_permission'); + } + + $file = DIR_DOWNLOAD . 'opencart-' . $version . '.zip'; + + if (!is_file($file)) { + $json['error'] = $this->language->get('error_file'); + } + + if (!$json) { + // Unzip the files + $zip = new \ZipArchive(); + + if ($zip->open($file, \ZipArchive::RDONLY)) { + $remove = 'opencart-' . $version . '/upload/'; + + // Check if any of the files already exist. + for ($i = 0; $i < $zip->numFiles; $i++) { + $source = $zip->getNameIndex($i); + + if (substr($source, 0, strlen($remove)) == $remove) { + // Only extract the contents of the upload folder + $destination = str_replace('\\', '/', substr($source, strlen($remove))); + + if (substr($destination, 0, 8) == 'install/') { + // Default copy location + $path = ''; + + // Must not have a path before files and directories can be moved + $directories = explode('/', dirname($destination)); + + foreach ($directories as $directory) { + if (!$path) { + $path = $directory; + } else { + $path = $path . '/' . $directory; + } + + if (!is_dir(DIR_OPENCART . $path) && !@mkdir(DIR_OPENCART . $path, 0777)) { + $json['error'] = sprintf($this->language->get('error_directory'), $path); + } + } + + // Check if the path is not directory and check there is no existing file + if (substr($destination, -1) != '/') { + if (is_file(DIR_OPENCART . $destination)) { + unlink(DIR_OPENCART . $destination); + } + + if (!copy('zip://' . $file . '#' . $source, DIR_OPENCART . $destination)) { + $json['error'] = sprintf($this->language->get('error_copy'), $source, $destination); + } + } + } + } + } + + $zip->close(); + + $json['text'] = $this->language->get('text_patch'); + + $json['next'] = HTTP_CATALOG . 'install/index.php?route=upgrade/upgrade_1&version=' . $version . '&admin=' . rtrim(substr(DIR_APPLICATION, strlen(DIR_OPENCART), -1)); + } else { + $json['error'] = $this->language->get('error_unzip'); + } + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/tool/upload.php b/admininistrator/controller/tool/upload.php new file mode 100644 index 0000000..860f727 --- /dev/null +++ b/admininistrator/controller/tool/upload.php @@ -0,0 +1,412 @@ +load->language('tool/upload'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('tool/upload', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('tool/upload.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('tool/upload.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('tool/upload', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('tool/upload'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['filter_name'])) { + $filter_name = $this->request->get['filter_name']; + } else { + $filter_name = ''; + } + + if (isset($this->request->get['filter_date_from'])) { + $filter_date_from = $this->request->get['filter_date_from']; + } else { + $filter_date_from = ''; + } + + if (isset($this->request->get['filter_date_to'])) { + $filter_date_to = $this->request->get['filter_date_to']; + } else { + $filter_date_to = ''; + } + + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'date_added'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'DESC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('tool/upload.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['uploads'] = []; + + $filter_data = [ + 'filter_name' => $filter_name, + 'filter_date_from' => $filter_date_from, + 'filter_date_to' => $filter_date_to, + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('tool/upload'); + + $upload_total = $this->model_tool_upload->getTotalUploads($filter_data); + + $results = $this->model_tool_upload->getUploads($filter_data); + + foreach ($results as $result) { + $data['uploads'][] = [ + 'upload_id' => $result['upload_id'], + 'name' => $result['name'], + 'code' => $result['code'], + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])), + 'download' => $this->url->link('tool/upload.download', 'user_token=' . $this->session->data['user_token'] . '&code=' . $result['code'] . $url) + ]; + } + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['sort_name'] = $this->url->link('tool/upload.list', 'user_token=' . $this->session->data['user_token'] . '&sort=name' . $url); + $data['sort_code'] = $this->url->link('tool/upload.list', 'user_token=' . $this->session->data['user_token'] . '&sort=code' . $url); + $data['sort_date_added'] = $this->url->link('tool/upload.list', 'user_token=' . $this->session->data['user_token'] . '&sort=date_added' . $url); + + $url = ''; + + if (isset($this->request->get['filter_name'])) { + $url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8')); + } + + if (isset($this->request->get['filter_date_from'])) { + $url .= '&filter_date_from=' . $this->request->get['filter_date_from']; + } + + if (isset($this->request->get['filter_date_to'])) { + $url .= '&filter_date_to=' . $this->request->get['filter_date_to']; + } + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $upload_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('tool/upload.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($upload_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($upload_total - $this->config->get('config_pagination_admin'))) ? $upload_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $upload_total, ceil($upload_total / $this->config->get('config_pagination_admin'))); + + $data['filter_name'] = $filter_name; + $data['filter_date_from'] = $filter_date_from; + $data['filter_date_to'] = $filter_date_to; + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('tool/upload_list', $data); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('tool/upload'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'tool/upload')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('tool/upload'); + + foreach ($selected as $upload_id) { + // Remove file before deleting DB record. + $upload_info = $this->model_tool_upload->getUpload($upload_id); + + if ($upload_info && is_file(DIR_UPLOAD . $upload_info['filename'])) { + unlink(DIR_UPLOAD . $upload_info['filename']); + } + + $this->model_tool_upload->deleteUpload($upload_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function download(): void { + $this->load->language('tool/upload'); + + if (isset($this->request->get['code'])) { + $code = $this->request->get['code']; + } else { + $code = ''; + } + + $this->load->model('tool/upload'); + + $upload_info = $this->model_tool_upload->getUploadByCode($code); + + if ($upload_info) { + $file = DIR_UPLOAD . $upload_info['filename']; + $mask = basename($upload_info['name']); + + if (!headers_sent()) { + if (is_file($file)) { + header('Content-Type: application/octet-stream'); + header('Content-Description: File Transfer'); + header('Content-Disposition: attachment; filename="' . ($mask ? $mask : basename($file)) . '"'); + header('Content-Transfer-Encoding: binary'); + header('Expires: 0'); + header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); + header('Pragma: public'); + header('Content-Length: ' . filesize($file)); + + readfile($file, 'rb'); + exit; + } else { + exit(sprintf($this->language->get('error_not_found'), basename($file))); + } + } else { + exit($this->language->get('error_headers_sent')); + } + } else { + $this->load->language('error/not_found'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('error/not_found', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('error/not_found', $data)); + } + } + + /** + * @return void + */ + public function upload(): void { + $this->load->language('tool/upload'); + + $json = []; + + // Check user has permission + if (!$this->user->hasPermission('modify', 'tool/upload')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (empty($this->request->files['file']['name']) || !is_file($this->request->files['file']['tmp_name'])) { + $json['error'] = $this->language->get('error_upload'); + } + + if (!$json) { + // Sanitize the filename + $filename = basename(html_entity_decode($this->request->files['file']['name'], ENT_QUOTES, 'UTF-8')); + + // Validate the filename length + if ((oc_strlen($filename) < 3) || (oc_strlen($filename) > 128)) { + $json['error'] = $this->language->get('error_filename'); + } + + // Allowed file extension types + $allowed = []; + + $extension_allowed = preg_replace('~\r?\n~', "\n", $this->config->get('config_file_ext_allowed')); + + $filetypes = explode("\n", $extension_allowed); + + foreach ($filetypes as $filetype) { + $allowed[] = trim($filetype); + } + + if (!in_array(strtolower(substr(strrchr($filename, '.'), 1)), $allowed)) { + $json['error'] = $this->language->get('error_file_type'); + } + + // Allowed file mime types + $allowed = []; + + $mime_allowed = preg_replace('~\r?\n~', "\n", $this->config->get('config_file_mime_allowed')); + + $filetypes = explode("\n", $mime_allowed); + + foreach ($filetypes as $filetype) { + $allowed[] = trim($filetype); + } + + if (!in_array($this->request->files['file']['type'], $allowed)) { + $json['error'] = $this->language->get('error_file_type'); + } + + // Return any upload error + if ($this->request->files['file']['error'] != UPLOAD_ERR_OK) { + $json['error'] = $this->language->get('error_upload_' . $this->request->files['file']['error']); + } + } + + if (!$json) { + $file = $filename . '.' . oc_token(32); + + move_uploaded_file($this->request->files['file']['tmp_name'], DIR_UPLOAD . $file); + + // Hide the uploaded file name so people cannot link to it directly. + $this->load->model('tool/upload'); + + $json['code'] = $this->model_tool_upload->addUpload($filename, $file); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/user/api.php b/admininistrator/controller/user/api.php new file mode 100644 index 0000000..9d50381 --- /dev/null +++ b/admininistrator/controller/user/api.php @@ -0,0 +1,372 @@ +load->language('user/api'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('user/api', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('user/api.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('user/api.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('user/api', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('user/api'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'username'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('user/api.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['apis'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('user/api'); + + $user_total = $this->model_user_api->getTotalApis(); + + $results = $this->model_user_api->getApis($filter_data); + + foreach ($results as $result) { + $data['apis'][] = [ + 'api_id' => $result['api_id'], + 'username' => $result['username'], + 'status' => ($result['status'] ? $this->language->get('text_enabled') : $this->language->get('text_disabled')), + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])), + 'date_modified' => date($this->language->get('date_format_short'), strtotime($result['date_modified'])), + 'edit' => $this->url->link('user/api.form', 'user_token=' . $this->session->data['user_token'] . '&api_id=' . $result['api_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_username'] = $this->url->link('user/api.list', 'user_token=' . $this->session->data['user_token'] . '&sort=username' . $url); + $data['sort_status'] = $this->url->link('user/api.list', 'user_token=' . $this->session->data['user_token'] . '&sort=status' . $url); + $data['sort_date_added'] = $this->url->link('user/api.list', 'user_token=' . $this->session->data['user_token'] . '&sort=date_added' . $url); + $data['sort_date_modified'] = $this->url->link('user/api.list', 'user_token=' . $this->session->data['user_token'] . '&sort=date_modified' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $user_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('user/api.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($user_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($user_total - $this->config->get('config_pagination_admin'))) ? $user_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $user_total, ceil($user_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('user/api_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('user/api'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['api_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + $data['text_ip'] = sprintf($this->language->get('text_ip'), $this->request->server['REMOTE_ADDR']); + + if (isset($this->request->get['api_id'])) { + $data['api_id'] = $this->request->get['api_id']; + } else { + $data['api_id'] = 0; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('user/api', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('user/api.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('user/api', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['api_id'])) { + $this->load->model('user/api'); + + $api_info = $this->model_user_api->getApi($this->request->get['api_id']); + } + + if (isset($this->request->get['api_id'])) { + $data['api_id'] = (int)$this->request->get['api_id']; + } else { + $data['api_id'] = 0; + } + + if (!empty($api_info)) { + $data['username'] = $api_info['username']; + } else { + $data['username'] = ''; + } + + if (!empty($api_info)) { + $data['key'] = $api_info['key']; + } else { + $data['key'] = ''; + } + + if (!empty($api_info)) { + $data['status'] = $api_info['status']; + } else { + $data['status'] = 0; + } + + // IP + if (!empty($api_info)) { + $data['api_ips'] = $this->model_user_api->getIps($this->request->get['api_id']); + } else { + $data['api_ips'] = []; + } + + // Session + $data['api_sessions'] = []; + + if (!empty($api_info)) { + $results = $this->model_user_api->getSessions($this->request->get['api_id']); + + foreach ($results as $result) { + $data['api_sessions'][] = [ + 'api_session_id' => $result['api_session_id'], + 'session_id' => $result['session_id'], + 'ip' => $result['ip'], + 'date_added' => date($this->language->get('datetime_format'), strtotime($result['date_added'])), + 'date_modified' => date($this->language->get('datetime_format'), strtotime($result['date_modified'])) + ]; + } + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('user/api_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('user/api'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'user/api')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if ((oc_strlen($this->request->post['username']) < 3) || (oc_strlen($this->request->post['username']) > 64)) { + $json['error']['username'] = $this->language->get('error_username'); + } + + if ((oc_strlen($this->request->post['key']) < 64) || (oc_strlen($this->request->post['key']) > 256)) { + $json['error']['key'] = $this->language->get('error_key'); + } + + if (!isset($json['error']['warning']) && !isset($this->request->post['api_ip'])) { + $json['error']['warning'] = $this->language->get('error_ip'); + } + + if (!$json) { + $this->load->model('user/api'); + + if (!$this->request->post['api_id']) { + $json['api_id'] = $this->model_user_api->addApi($this->request->post); + } else { + $this->model_user_api->editApi($this->request->post['api_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('user/api'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'user/api')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('user/api'); + + foreach ($selected as $api_id) { + $this->model_user_api->deleteApi($api_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function deleteSession(): void { + $this->load->language('user/api'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'user/api')) { + $json['error'] = $this->language->get('error_permission'); + } + + if (!$json) { + $this->load->model('user/api'); + + $this->model_user_api->deleteSession($this->request->get['api_session_id']); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/controller/user/profile.php b/admininistrator/controller/user/profile.php new file mode 100644 index 0000000..156e5f4 --- /dev/null +++ b/admininistrator/controller/user/profile.php @@ -0,0 +1,149 @@ +load->language('user/profile'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('user/profile', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['save'] = $this->url->link('user/profile.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']); + + $this->load->model('user/user'); + + $user_info = $this->model_user_user->getUser($this->user->getId()); + + if (!empty($user_info)) { + $data['username'] = $user_info['username']; + } else { + $data['username'] = ''; + } + + if (!empty($user_info)) { + $data['firstname'] = $user_info['firstname']; + } else { + $data['firstname'] = ''; + } + + if (!empty($user_info)) { + $data['lastname'] = $user_info['lastname']; + } else { + $data['lastname'] = ''; + } + + if (!empty($user_info)) { + $data['email'] = $user_info['email']; + } else { + $data['email'] = ''; + } + + if (!empty($user_info)) { + $data['image'] = $user_info['image']; + } else { + $data['image'] = ''; + } + + $this->load->model('tool/image'); + + $data['placeholder'] = $this->model_tool_image->resize('no_image.png', 100, 100); + + if (is_file(DIR_IMAGE . html_entity_decode($data['image'], ENT_QUOTES, 'UTF-8'))) { + $data['thumb'] = $this->model_tool_image->resize(html_entity_decode($data['image'], ENT_QUOTES, 'UTF-8'), 100, 100); + } else { + $data['thumb'] = $data['placeholder']; + } + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('user/profile', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('user/profile'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'user/profile')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if ((oc_strlen($this->request->post['username']) < 3) || (oc_strlen($this->request->post['username']) > 20)) { + $json['error']['username'] = $this->language->get('error_username'); + } + + $this->load->model('user/user'); + + $user_info = $this->model_user_user->getUserByUsername($this->request->post['username']); + + if ($user_info && ($this->user->getId() != $user_info['user_id'])) { + $json['error']['warning'] = $this->language->get('error_username_exists'); + } + + if ((oc_strlen($this->request->post['firstname']) < 1) || (oc_strlen($this->request->post['firstname']) > 32)) { + $json['error']['firstname'] = $this->language->get('error_firstname'); + } + + if ((oc_strlen($this->request->post['lastname']) < 1) || (oc_strlen($this->request->post['lastname']) > 32)) { + $json['error']['lastname'] = $this->language->get('error_lastname'); + } + + if ((oc_strlen($this->request->post['email']) > 96) || !filter_var($this->request->post['email'], FILTER_VALIDATE_EMAIL)) { + $json['error']['email'] = $this->language->get('error_email'); + } + + $user_info = $this->model_user_user->getUserByEmail($this->request->post['email']); + + if ($user_info && ($this->user->getId() != $user_info['user_id'])) { + $json['error']['warning'] = $this->language->get('error_email_exists'); + } + + if ($this->request->post['password']) { + if ((oc_strlen(html_entity_decode($this->request->post['password'], ENT_QUOTES, 'UTF-8')) < 4) || (oc_strlen(html_entity_decode($this->request->post['password'], ENT_QUOTES, 'UTF-8')) > 40)) { + $json['error']['password'] = $this->language->get('error_password'); + } + + if ($this->request->post['password'] != $this->request->post['confirm']) { + $json['error']['confirm'] = $this->language->get('error_confirm'); + } + } + + if (!$json) { + $user_data = array_merge($this->request->post, [ + 'user_group_id' => $this->user->getGroupId(), + 'status' => 1, + ]); + + $this->model_user_user->editUser($this->user->getId(), $user_data); + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} \ No newline at end of file diff --git a/admininistrator/controller/user/user.php b/admininistrator/controller/user/user.php new file mode 100644 index 0000000..8fd9354 --- /dev/null +++ b/admininistrator/controller/user/user.php @@ -0,0 +1,551 @@ +load->language('user/user'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('user/user', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('user/user.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('user/user.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('user/user', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('user/user'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'username'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('user/user.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['users'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('user/user'); + + $user_total = $this->model_user_user->getTotalUsers(); + + $results = $this->model_user_user->getUsers($filter_data); + + foreach ($results as $result) { + $data['users'][] = [ + 'user_id' => $result['user_id'], + 'username' => $result['username'], + 'status' => ($result['status'] ? $this->language->get('text_enabled') : $this->language->get('text_disabled')), + 'date_added' => date($this->language->get('date_format_short'), strtotime($result['date_added'])), + 'edit' => $this->url->link('user/user.form', 'user_token=' . $this->session->data['user_token'] . '&user_id=' . $result['user_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_username'] = $this->url->link('user/user.list', 'user_token=' . $this->session->data['user_token'] . '&sort=username' . $url); + $data['sort_status'] = $this->url->link('user/user.list', 'user_token=' . $this->session->data['user_token'] . '&sort=status' . $url); + $data['sort_date_added'] = $this->url->link('user/user.list', 'user_token=' . $this->session->data['user_token'] . '&sort=date_added' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $user_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('user/user.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($user_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($user_total - $this->config->get('config_pagination_admin'))) ? $user_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $user_total, ceil($user_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('user/user_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('user/user'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['user_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['save'] = $this->url->link('user/user.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('user/user', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['user_id'])) { + $this->load->model('user/user'); + + $user_info = $this->model_user_user->getUser($this->request->get['user_id']); + } + + if (isset($this->request->get['user_id'])) { + $data['user_id'] = (int)$this->request->get['user_id']; + } else { + $data['user_id'] = 0; + } + + if (!empty($user_info)) { + $data['username'] = $user_info['username']; + } else { + $data['username'] = ''; + } + + $this->load->model('user/user_group'); + + $data['user_groups'] = $this->model_user_user_group->getUserGroups(); + + if (!empty($user_info)) { + $data['user_group_id'] = $user_info['user_group_id']; + } else { + $data['user_group_id'] = 0; + } + + if (!empty($user_info)) { + $data['firstname'] = $user_info['firstname']; + } else { + $data['firstname'] = ''; + } + + if (!empty($user_info)) { + $data['lastname'] = $user_info['lastname']; + } else { + $data['lastname'] = ''; + } + + if (!empty($user_info)) { + $data['email'] = $user_info['email']; + } else { + $data['email'] = ''; + } + + if (!empty($user_info)) { + $data['image'] = $user_info['image']; + } else { + $data['image'] = ''; + } + + $this->load->model('tool/image'); + + $data['placeholder'] = $this->model_tool_image->resize('no_image.png', 100, 100); + + if (is_file(DIR_IMAGE . html_entity_decode($data['image'], ENT_QUOTES, 'UTF-8'))) { + $data['thumb'] = $this->model_tool_image->resize(html_entity_decode($data['image'], ENT_QUOTES, 'UTF-8'), 100, 100); + } else { + $data['thumb'] = $data['placeholder']; + } + + if (!empty($user_info)) { + $data['status'] = $user_info['status']; + } else { + $data['status'] = 0; + } + + $data['authorize'] = $this->getAuthorize(); + $data['login'] = $this->getLogin(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('user/user_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('user/user'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'user/user')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if ((oc_strlen($this->request->post['username']) < 3) || (oc_strlen($this->request->post['username']) > 20)) { + $json['error']['username'] = $this->language->get('error_username'); + } + + $this->load->model('user/user'); + + $user_info = $this->model_user_user->getUserByUsername($this->request->post['username']); + + if (!$this->request->post['user_id']) { + if ($user_info) { + $json['error']['warning'] = $this->language->get('error_username_exists'); + } + } else { + if ($user_info && ($this->request->post['user_id'] != $user_info['user_id'])) { + $json['error']['warning'] = $this->language->get('error_username_exists'); + } + } + + if ((oc_strlen($this->request->post['firstname']) < 1) || (oc_strlen($this->request->post['firstname']) > 32)) { + $json['error']['firstname'] = $this->language->get('error_firstname'); + } + + if ((oc_strlen($this->request->post['lastname']) < 1) || (oc_strlen($this->request->post['lastname']) > 32)) { + $json['error']['lastname'] = $this->language->get('error_lastname'); + } + + if ((oc_strlen($this->request->post['email']) > 96) || !filter_var($this->request->post['email'], FILTER_VALIDATE_EMAIL)) { + $json['error']['email'] = $this->language->get('error_email'); + } + + $user_info = $this->model_user_user->getUserByEmail($this->request->post['email']); + + if (!$this->request->post['user_id']) { + if ($user_info) { + $json['error']['warning'] = $this->language->get('error_email_exists'); + } + } else { + if ($user_info && ($this->request->post['user_id'] != $user_info['user_id'])) { + $json['error']['warning'] = $this->language->get('error_email_exists'); + } + } + + if ($this->request->post['password'] || (!isset($this->request->post['user_id']))) { + if ((oc_strlen(html_entity_decode($this->request->post['password'], ENT_QUOTES, 'UTF-8')) < 4) || (oc_strlen(html_entity_decode($this->request->post['password'], ENT_QUOTES, 'UTF-8')) > 40)) { + $json['error']['password'] = $this->language->get('error_password'); + } + + if ($this->request->post['password'] != $this->request->post['confirm']) { + $json['error']['confirm'] = $this->language->get('error_confirm'); + } + } + + if (!$json) { + if (!$this->request->post['user_id']) { + $json['user_id'] = $this->model_user_user->addUser($this->request->post); + } else { + $this->model_user_user->editUser($this->request->post['user_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('user/user'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'user/user')) { + $json['error'] = $this->language->get('error_permission'); + } + + foreach ($selected as $user_id) { + if ($this->user->getId() == $user_id) { + $json['error']['warning'] = $this->language->get('error_account'); + } + } + + if (!$json) { + $this->load->model('user/user'); + + foreach ($selected as $user_id) { + $this->model_user_user->deleteUser($user_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function authorize(): void { + $this->load->language('user/user'); + + $this->response->setOutput($this->getAuthorize()); + } + + /** + * @return string + */ + public function getAuthorize(): string { + if (isset($this->request->get['user_id'])) { + $user_id = (int)$this->request->get['user_id']; + } else { + $user_id = 0; + } + + if (isset($this->request->get['page']) && $this->request->get['route'] == 'user/user.login') { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $limit = 10; + + $data['authorizes'] = []; + + $this->load->model('user/user'); + + $results = $this->model_user_user->getAuthorizes($user_id, ($page - 1) * $limit, $limit); + + foreach ($results as $result) { + $data['authorizes'][] = [ + 'token' => $result['token'], + 'ip' => $result['ip'], + 'user_agent' => $result['user_agent'], + 'status' => $result['status'] ? $this->language->get('text_enabled') : $this->language->get('text_disabled'), + 'total' => $result['total'], + 'date_added' => date($this->language->get('datetime_format'), strtotime($result['date_added'])), + 'delete' => $this->url->link('user/user.deleteAuthorize', 'user_token=' . $this->session->data['user_token'] . '&user_authorize_id=' . $result['user_authorize_id']) + ]; + } + + $authorize_total = $this->model_user_user->getTotalAuthorizes($user_id); + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $authorize_total, + 'page' => $page, + 'limit' => $limit, + 'url' => $this->url->link('user/user.authorize', 'user_token=' . $this->session->data['user_token'] . '&user_id=' . $user_id . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($authorize_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($authorize_total - $limit)) ? $authorize_total : ((($page - 1) * $limit) + $limit), $authorize_total, ceil($authorize_total / $limit)); + + return $this->load->view('user/user_authorize', $data); + } + + /** + * @return void + */ + public function deleteAuthorize(): void { + $this->load->language('user/user'); + + $json = []; + + if (isset($this->request->get['user_authorize_id'])) { + $user_authorize_id = (int)$this->request->get['user_authorize_id']; + } else { + $user_authorize_id = 0; + } + + if (isset($this->request->cookie['authorize'])) { + $token = $this->request->cookie['authorize']; + } else { + $token = ''; + } + + if (!$this->user->hasPermission('modify', 'user/user')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('user/user'); + + $login_info = $this->model_user_user->getAuthorize($user_authorize_id); + + if (!$login_info) { + $json['error'] = $this->language->get('error_authorize'); + } + + if (!$json) { + $this->model_user_user->deleteAuthorize($user_authorize_id); + + // If the token is still present, then we enforce the user to log out automatically. + if ($login_info['token'] == $token) { + $this->session->data['success'] = $this->language->get('text_success'); + + $json['redirect'] = $this->url->link('common/login', '', true); + } else { + $json['success'] = $this->language->get('text_success'); + } + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function login(): void { + $this->load->language('user/user'); + + $this->response->setOutput($this->getLogin()); + } + + /** + * @return string + */ + public function getLogin(): string { + if (isset($this->request->get['user_id'])) { + $user_id = (int)$this->request->get['user_id']; + } else { + $user_id = 0; + } + + if (isset($this->request->get['page']) && $this->request->get['route'] == 'user/user.login') { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $limit = 10; + + $data['logins'] = []; + + $this->load->model('user/user'); + + $results = $this->model_user_user->getLogins($user_id, ($page - 1) * $limit, $limit); + + foreach ($results as $result) { + $data['logins'][] = [ + 'ip' => $result['ip'], + 'user_agent' => $result['user_agent'], + 'date_added' => date($this->language->get('datetime_format'), strtotime($result['date_added'])) + ]; + } + + $login_total = $this->model_user_user->getTotalLogins($user_id); + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $login_total, + 'page' => $page, + 'limit' => $limit, + 'url' => $this->url->link('user/user.login', 'user_token=' . $this->session->data['user_token'] . '&user_id=' . $user_id . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($login_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($login_total - $limit)) ? $login_total : ((($page - 1) * $limit) + $limit), $login_total, ceil($login_total / $limit)); + + return $this->load->view('user/user_login', $data); + } +} diff --git a/admininistrator/controller/user/user_permission.php b/admininistrator/controller/user/user_permission.php new file mode 100644 index 0000000..415c860 --- /dev/null +++ b/admininistrator/controller/user/user_permission.php @@ -0,0 +1,395 @@ +load->language('user/user_group'); + + $this->document->setTitle($this->language->get('heading_title')); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('user/user_permission', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['add'] = $this->url->link('user/user_permission.form', 'user_token=' . $this->session->data['user_token'] . $url); + $data['delete'] = $this->url->link('user/user_permission.delete', 'user_token=' . $this->session->data['user_token']); + + $data['list'] = $this->getList(); + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('user/user_group', $data)); + } + + /** + * @return void + */ + public function list(): void { + $this->load->language('user/user_group'); + + $this->response->setOutput($this->getList()); + } + + /** + * @return string + */ + protected function getList(): string { + if (isset($this->request->get['sort'])) { + $sort = (string)$this->request->get['sort']; + } else { + $sort = 'name'; + } + + if (isset($this->request->get['order'])) { + $order = (string)$this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = (int)$this->request->get['page']; + } else { + $page = 1; + } + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['action'] = $this->url->link('user/user_permission.list', 'user_token=' . $this->session->data['user_token'] . $url); + + $data['user_groups'] = []; + + $filter_data = [ + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_pagination_admin'), + 'limit' => $this->config->get('config_pagination_admin') + ]; + + $this->load->model('user/user_group'); + + $user_group_total = $this->model_user_user_group->getTotalUserGroups(); + + $results = $this->model_user_user_group->getUserGroups($filter_data); + + foreach ($results as $result) { + $data['user_groups'][] = [ + 'user_group_id' => $result['user_group_id'], + 'name' => $result['name'], + 'edit' => $this->url->link('user/user_permission.form', 'user_token=' . $this->session->data['user_token'] . '&user_group_id=' . $result['user_group_id'] . $url) + ]; + } + + $url = ''; + + if ($order == 'ASC') { + $url .= '&order=DESC'; + } else { + $url .= '&order=ASC'; + } + + $data['sort_name'] = $this->url->link('user/user_permission.list', 'user_token=' . $this->session->data['user_token'] . '&sort=name' . $url); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + $data['pagination'] = $this->load->controller('common/pagination', [ + 'total' => $user_group_total, + 'page' => $page, + 'limit' => $this->config->get('config_pagination_admin'), + 'url' => $this->url->link('user/user_permission.list', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}') + ]); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($user_group_total) ? (($page - 1) * $this->config->get('config_pagination_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_pagination_admin')) > ($user_group_total - $this->config->get('config_pagination_admin'))) ? $user_group_total : ((($page - 1) * $this->config->get('config_pagination_admin')) + $this->config->get('config_pagination_admin')), $user_group_total, ceil($user_group_total / $this->config->get('config_pagination_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + return $this->load->view('user/user_group_list', $data); + } + + /** + * @return void + */ + public function form(): void { + $this->load->language('user/user_group'); + + $this->document->setTitle($this->language->get('heading_title')); + + $data['text_form'] = !isset($this->request->get['user_group_id']) ? $this->language->get('text_add') : $this->language->get('text_edit'); + + $url = ''; + + if (isset($this->request->get['sort'])) { + $url .= '&sort=' . $this->request->get['sort']; + } + + if (isset($this->request->get['order'])) { + $url .= '&order=' . $this->request->get['order']; + } + + if (isset($this->request->get['page'])) { + $url .= '&page=' . $this->request->get['page']; + } + + $data['breadcrumbs'] = []; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token']) + ]; + + $data['breadcrumbs'][] = [ + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('user/user_permission', 'user_token=' . $this->session->data['user_token'] . $url) + ]; + + $data['save'] = $this->url->link('user/user_permission.save', 'user_token=' . $this->session->data['user_token']); + $data['back'] = $this->url->link('user/user_permission', 'user_token=' . $this->session->data['user_token'] . $url); + + if (isset($this->request->get['user_group_id'])) { + $this->load->model('user/user_group'); + + $user_group_info = $this->model_user_user_group->getUserGroup($this->request->get['user_group_id']); + } + + if (isset($this->request->get['user_group_id'])) { + $data['user_group_id'] = (int)$this->request->get['user_group_id']; + } else { + $data['user_group_id'] = 0; + } + + if (!empty($user_group_info)) { + $data['name'] = $user_group_info['name']; + } else { + $data['name'] = ''; + } + + // Routes to ignore + $ignore = [ + 'common/dashboard', + 'common/startup', + 'common/login', + 'common/logout', + 'common/forgotten', + 'common/authorize', + 'common/footer', + 'common/header', + 'common/column_left', + 'common/language', + 'common/pagination', + 'error/not_found', + 'error/permission', + 'event/currency', + 'event/debug', + 'event/language', + 'event/statistics', + 'startup/application', + 'startup/authorize', + 'startup/error', + 'startup/event', + 'startup/extension', + 'startup/language', + 'startup/login', + 'startup/notification', + 'startup/permission', + 'startup/sass', + 'startup/session', + 'startup/setting', + 'startup/startup' + ]; + + $files = []; + + // Make path into an array + $path = [DIR_APPLICATION . 'controller/*']; + + // While the path array is still populated keep looping through + while (count($path) != 0) { + $next = array_shift($path); + + foreach (glob($next . '/*') as $file) { + // If directory add to path array + if (is_dir($file)) { + $path[] = $file; + } + + // Add the file to the files to be deleted array + if (is_file($file)) { + $files[] = $file; + } + } + } + + // Sort the file array + sort($files); + + $data['permissions'] = []; + + foreach ($files as $file) { + $controller = substr($file, strlen(DIR_APPLICATION . 'controller/')); + + $permission = substr($controller, 0, strrpos($controller, '.')); + + if (!in_array($permission, $ignore)) { + $data['permissions'][] = $permission; + } + } + + $data['extensions'] = []; + + // Extension permissions + $this->load->model('setting/extension'); + + $results = $this->model_setting_extension->getPaths('%/admin/controller/%.php'); + + foreach ($results as $result) { + $data['extensions'][] = 'extension/' . str_replace('admin/controller/', '', substr($result['path'], 0, strrpos($result['path'], '.'))); + } + + if (isset($user_group_info['permission']['access'])) { + $data['access'] = $user_group_info['permission']['access']; + } else { + $data['access'] = []; + } + + if (isset($user_group_info['permission']['modify'])) { + $data['modify'] = $user_group_info['permission']['modify']; + } else { + $data['modify'] = []; + } + + $data['user_token'] = $this->session->data['user_token']; + + $data['header'] = $this->load->controller('common/header'); + $data['column_left'] = $this->load->controller('common/column_left'); + $data['footer'] = $this->load->controller('common/footer'); + + $this->response->setOutput($this->load->view('user/user_group_form', $data)); + } + + /** + * @return void + */ + public function save(): void { + $this->load->language('user/user_group'); + + $json = []; + + if (!$this->user->hasPermission('modify', 'user/user_permission')) { + $json['error']['warning'] = $this->language->get('error_permission'); + } + + if ((oc_strlen($this->request->post['name']) < 3) || (oc_strlen($this->request->post['name']) > 64)) { + $json['error']['name'] = $this->language->get('error_name'); + } + + if (!$json) { + $this->load->model('user/user_group'); + + if (!$this->request->post['user_group_id']) { + $json['user_group_id'] = $this->model_user_user_group->addUserGroup($this->request->post); + } else { + $this->model_user_user_group->editUserGroup($this->request->post['user_group_id'], $this->request->post); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } + + /** + * @return void + */ + public function delete(): void { + $this->load->language('user/user_group'); + + $json = []; + + if (isset($this->request->post['selected'])) { + $selected = $this->request->post['selected']; + } else { + $selected = []; + } + + if (!$this->user->hasPermission('modify', 'user/user_permission')) { + $json['error'] = $this->language->get('error_permission'); + } + + $this->load->model('user/user'); + + foreach ($selected as $user_group_id) { + $user_total = $this->model_user_user->getTotalUsersByGroupId($user_group_id); + + if ($user_total) { + $json['error'] = sprintf($this->language->get('error_user'), $user_total); + } + } + + if (!$json) { + $this->load->model('user/user_group'); + + foreach ($selected as $user_group_id) { + $this->model_user_user_group->deleteUserGroup($user_group_id); + } + + $json['success'] = $this->language->get('text_success'); + } + + $this->response->addHeader('Content-Type: application/json'); + $this->response->setOutput(json_encode($json)); + } +} diff --git a/admininistrator/index.php b/admininistrator/index.php new file mode 100644 index 0000000..f1e61e3 --- /dev/null +++ b/admininistrator/index.php @@ -0,0 +1,20 @@ +master product data. Otherwise the data will get replaced with the master product data when saved.'; +$_['text_list'] = 'Product List'; +$_['text_add'] = 'Add Product'; +$_['text_edit'] = 'Edit Product'; +$_['text_variant_add'] = 'Add Variant'; +$_['text_model'] = 'Model'; +$_['text_price'] = 'Price'; +$_['text_stock'] = 'Stock'; +$_['text_specification'] = 'Specification'; +$_['text_filter'] = 'Filter'; +$_['text_default'] = 'Default'; +$_['text_keyword'] = 'Do not use spaces, instead replace spaces with - and make sure the SEO URL is globally unique.'; +$_['text_option_add'] = 'Add Option'; +$_['text_option_value'] = 'Option Value'; +$_['text_select'] = 'Select'; +$_['text_radio'] = 'Radio'; +$_['text_checkbox'] = 'Checkbox'; +$_['text_input'] = 'Input'; +$_['text_text'] = 'Text'; +$_['text_textarea'] = 'Textarea'; +$_['text_file'] = 'File'; +$_['text_date'] = 'Date'; +$_['text_datetime'] = 'Date & Time'; +$_['text_time'] = 'Time'; +$_['text_image'] = 'Image'; +$_['text_image_additional'] = 'Additional Images'; +$_['text_reward'] = 'Buy Points'; +$_['text_points'] = 'Reward Points'; +$_['text_report'] = 'Reports'; + +// Column +$_['column_name'] = 'Product Name'; +$_['column_model'] = 'Model'; +$_['column_image'] = 'Image'; +$_['column_price'] = 'Price'; +$_['column_quantity'] = 'Quantity'; +$_['column_status'] = 'Status'; +$_['column_ip'] = 'IP'; +$_['column_store'] = 'Store'; +$_['column_country'] = 'Country'; +$_['column_date_added'] = 'Date Added'; +$_['column_action'] = 'Action'; + +// Entry +$_['entry_name'] = 'Product Name'; +$_['entry_description'] = 'Description'; +$_['entry_meta_title'] = 'Meta Tag Title'; +$_['entry_meta_keyword'] = 'Meta Tag Keywords'; +$_['entry_meta_description'] = 'Meta Tag Description'; +$_['entry_store'] = 'Stores'; +$_['entry_keyword'] = 'Keyword'; +$_['entry_model'] = 'Model'; +$_['entry_sku'] = 'SKU'; +$_['entry_upc'] = 'UPC'; +$_['entry_ean'] = 'EAN'; +$_['entry_jan'] = 'JAN'; +$_['entry_isbn'] = 'ISBN'; +$_['entry_mpn'] = 'MPN'; +$_['entry_location'] = 'Location'; +$_['entry_shipping'] = 'Requires Shipping'; +$_['entry_manufacturer'] = 'Manufacturer'; +$_['entry_date_available'] = 'Date Available'; +$_['entry_quantity'] = 'Quantity'; +$_['entry_minimum'] = 'Minimum Quantity'; +$_['entry_stock_status'] = 'Out Of Stock Status'; +$_['entry_price'] = 'Price'; +$_['entry_trial_price'] = 'Trial Price'; +$_['entry_tax_class'] = 'Tax Class'; +$_['entry_points'] = 'Points'; +$_['entry_subtract'] = 'Subtract Stock'; +$_['entry_weight_class'] = 'Weight Class'; +$_['entry_weight'] = 'Weight'; +$_['entry_dimension'] = 'Dimensions (L x W x H)'; +$_['entry_length_class'] = 'Length Class'; +$_['entry_length'] = 'Length'; +$_['entry_width'] = 'Width'; +$_['entry_height'] = 'Height'; +$_['entry_option'] = 'Option'; +$_['entry_option_value'] = 'Option Value'; +$_['entry_customer_group'] = 'Customer Group'; +$_['entry_date_start'] = 'Date Start'; +$_['entry_date_end'] = 'Date End'; +$_['entry_priority'] = 'Priority'; +$_['entry_attribute'] = 'Attribute'; +$_['entry_attribute_group'] = 'Attribute Group'; +$_['entry_image'] = 'Image'; +$_['entry_text'] = 'Text'; +$_['entry_required'] = 'Required'; +$_['entry_status'] = 'Status'; +$_['entry_sort_order'] = 'Sort Order'; +$_['entry_category'] = 'Categories'; +$_['entry_filter'] = 'Filters'; +$_['entry_download'] = 'Downloads'; +$_['entry_related'] = 'Related Products'; +$_['entry_tag'] = 'Product Tags'; +$_['entry_reward'] = 'Reward Points'; +$_['entry_layout'] = 'Layout Override'; +$_['entry_subscription'] = 'Subscription Plan'; + +// Help +$_['help_tag'] = 'Comma separated'; +$_['help_sku'] = 'Stock Keeping Unit'; +$_['help_upc'] = 'Universal Product Code'; +$_['help_ean'] = 'European Article Number'; +$_['help_jan'] = 'Japanese Article Number'; +$_['help_isbn'] = 'International Standard Book Number'; +$_['help_mpn'] = 'Manufacturer Part Number'; +$_['help_minimum'] = 'Force a minimum ordered amount'; +$_['help_stock_status'] = 'Status shown when a product is out of stock'; +$_['help_manufacturer'] = '(Autocomplete)'; +$_['help_category'] = '(Autocomplete)'; +$_['help_filter'] = '(Autocomplete)'; +$_['help_download'] = '(Autocomplete)'; +$_['help_related'] = '(Autocomplete)'; +$_['help_option'] = '(Autocomplete)'; +$_['help_points'] = 'Number of points needed to buy this item. If you don\'t want this product to be purchased with points leave as 0.'; + +// Error +$_['error_warning'] = 'Warning: Please check the form carefully for errors!'; +$_['error_permission'] = 'Warning: You do not have permission to modify products!'; +$_['error_name'] = 'Product Name must be greater than 1 and less than 255 characters!'; +$_['error_meta_title'] = 'Meta Title must be greater than 1 and less than 255 characters!'; +$_['error_model'] = 'Product Model must be greater than 1 and less than 64 characters!'; +$_['error_keyword'] = 'SEO URL must be between 1 and 64 characters!'; +$_['error_keyword_exists'] = 'SEO URL must be unique!'; +$_['error_keyword_character'] = 'Keyword can only use characters a-z, 0-9, - and _!'; +$_['error_required'] = '%s required!'; diff --git a/admininistrator/language/en-gb/catalog/review.php b/admininistrator/language/en-gb/catalog/review.php new file mode 100644 index 0000000..3904c86 --- /dev/null +++ b/admininistrator/language/en-gb/catalog/review.php @@ -0,0 +1,42 @@ +OpenCart © 2009-' . date('Y') . ' All Rights Reserved.'; +$_['text_version'] = 'Version %s'; \ No newline at end of file diff --git a/admininistrator/language/en-gb/common/forgotten.php b/admininistrator/language/en-gb/common/forgotten.php new file mode 100644 index 0000000..fdda8bc --- /dev/null +++ b/admininistrator/language/en-gb/common/forgotten.php @@ -0,0 +1,22 @@ +GDPR account deletion requests will process after %s days so any fraud detection, chargebacks or refunds can be processed.'; +$_['text_approve'] = 'Approve'; +$_['text_deny'] = 'Deny'; +$_['text_delete'] = 'Delete'; +$_['text_unverified'] = 'Unverified'; +$_['text_pending'] = 'Pending'; +$_['text_processing'] = 'Processing'; +$_['text_complete'] = 'Complete'; +$_['text_denied'] = 'Denied'; +$_['text_export'] = 'Export'; +$_['text_remove'] = 'Remove'; +$_['text_filter'] = 'Filter'; + +// Column +$_['column_email'] = 'E-Mail'; +$_['column_request'] = 'Request'; +$_['column_status'] = 'Status'; +$_['column_date_added'] = 'Date Added'; +$_['column_action'] = 'Action'; + +// Entry +$_['entry_email'] = 'E-Mail'; +$_['entry_action'] = 'Action'; +$_['entry_status'] = 'Status'; +$_['entry_date_from'] = 'Date From'; +$_['entry_date_to'] = 'Date To'; + +// Error +$_['error_permission'] = 'Warning: You do not have permission to modify GDPR approvals!'; diff --git a/admininistrator/language/en-gb/default.php b/admininistrator/language/en-gb/default.php new file mode 100644 index 0000000..e13bb3c --- /dev/null +++ b/admininistrator/language/en-gb/default.php @@ -0,0 +1,367 @@ +(Default)'; +$_['text_close'] = 'Close'; +$_['text_pagination'] = 'Showing %d to %d of %d (%d Pages)'; +$_['text_loading'] = 'Loading...'; +$_['text_no_results'] = 'No results!'; +$_['text_confirm'] = 'Are you sure?'; +$_['text_home'] = 'Home'; +$_['text_second_ago'] = 'just now'; +$_['text_seconds_ago'] = '%s seconds ago'; +$_['text_minute_ago'] = '%s minute ago'; +$_['text_minutes_ago'] = '%s minutes ago'; +$_['text_hour_ago'] = '%s hour ago'; +$_['text_hours_ago'] = '%s hours ago'; +$_['text_day_ago'] = '%s day ago'; +$_['text_days_ago'] = '%s days ago'; +$_['text_week_ago'] = '%s week ago'; +$_['text_weeks_ago'] = '%s weeks ago'; +$_['text_month_ago'] = '%s month ago'; +$_['text_months_ago'] = '%s months ago'; +$_['text_year_ago'] = '%s year ago'; +$_['text_years_ago'] = '%s years ago'; + +// Button +$_['button_add'] = 'Add New'; +$_['button_delete'] = 'Delete'; +$_['button_save'] = 'Save'; +$_['button_cancel'] = 'Cancel'; +$_['button_subscription_cancel'] = 'Cancel Subscription'; +$_['button_continue'] = 'Continue'; +$_['button_confirm'] = 'Confirm'; +$_['button_clear'] = 'Clear'; +$_['button_close'] = 'Close'; +$_['button_enable'] = 'Enable'; +$_['button_disable'] = 'Disable'; +$_['button_filter'] = 'Filter'; +$_['button_send'] = 'Send'; +$_['button_edit'] = 'Edit'; +$_['button_copy'] = 'Copy'; +$_['button_back'] = 'Back'; +$_['button_remove'] = 'Remove'; +$_['button_refresh'] = 'Refresh'; +$_['button_export'] = 'Export'; +$_['button_import'] = 'Import'; +$_['button_download'] = 'Download'; +$_['button_rebuild'] = 'Rebuild'; +$_['button_upload'] = 'Upload'; +$_['button_submit'] = 'Submit'; +$_['button_invoice_print'] = 'Print Invoice'; +$_['button_shipping_print'] = 'Print Shipping List'; +$_['button_address_add'] = 'Add Address'; +$_['button_attribute_add'] = 'Add Attribute'; +$_['button_banner_add'] = 'Add Banner'; +$_['button_custom_field_value_add'] = 'Add Custom Field'; +$_['button_product_add'] = 'Add Product'; +$_['button_filter_add'] = 'Add Filter'; +$_['button_option_add'] = 'Add Option'; +$_['button_option_value_add'] = 'Add Option Value'; +$_['button_subscription_add'] = 'Add Subscription'; +$_['button_discount_add'] = 'Add Discount'; +$_['button_special_add'] = 'Add Special'; +$_['button_image_add'] = 'Add Image'; +$_['button_geo_zone_add'] = 'Add Geo Zone'; +$_['button_history_add'] = 'Add History'; +$_['button_transaction_add'] = 'Add Transaction'; +$_['button_route_add'] = 'Add Route'; +$_['button_rule_add'] = 'Add Rule'; +$_['button_module_add'] = 'Add Module'; +$_['button_link_add'] = 'Add Link'; +$_['button_customer_add'] = 'Add Customer'; +$_['button_approve'] = 'Approve'; +$_['button_deny'] = 'Deny'; +$_['button_reset'] = 'Reset'; +$_['button_generate'] = 'Generate'; +$_['button_voucher_add'] = 'Add Voucher'; +$_['button_view'] = 'View'; +$_['button_reward_add'] = 'Add Reward Points'; +$_['button_reward_remove'] = 'Remove Reward Points'; +$_['button_commission_add'] = 'Add Commission'; +$_['button_commission_remove'] = 'Remove Commission'; +$_['button_credit_add'] = 'Add Credit'; +$_['button_credit_remove'] = 'Remove Credit'; +$_['button_ip_add'] = 'Add IP'; +$_['button_parent'] = 'Parent'; +$_['button_folder'] = 'New Folder'; +$_['button_search'] = 'Search'; +$_['button_install'] = 'Install'; +$_['button_uninstall'] = 'Uninstall'; +$_['button_link'] = 'Link'; +$_['button_currency'] = 'Refresh Currency Values'; +$_['button_apply'] = 'Apply'; +$_['button_category_add'] = 'Add Category'; +$_['button_order'] = 'View Order'; +$_['button_subscription'] = 'View Subscription'; +$_['button_buy'] = 'Buy'; +$_['button_restore'] = 'Restore'; +$_['button_run'] = 'Run Cron Job'; +$_['button_backup'] = 'Backup'; +$_['button_developer'] = 'Developer Setting'; +$_['button_master'] = 'Master Product'; +$_['button_resend'] = 'Resend'; +$_['button_calculate'] = 'Calculate Payments'; +$_['button_csv'] = 'Download CSV'; +$_['button_complete'] = 'Complete Payments'; + +// Tab +$_['tab_address'] = 'Addresses'; +$_['tab_additional'] = 'Additional'; +$_['tab_attribute'] = 'Attribute'; +$_['tab_comment'] = 'Comment'; +$_['tab_data'] = 'Data'; +$_['tab_description'] = 'Description'; +$_['tab_design'] = 'Design'; +$_['tab_discount'] = 'Discount'; +$_['tab_documentation'] = 'Documentation'; +$_['tab_general'] = 'General'; +$_['tab_history'] = 'History'; +$_['tab_ip'] = 'IP Addresses'; +$_['tab_links'] = 'Links'; +$_['tab_log'] = 'Log'; +$_['tab_image'] = 'Image'; +$_['tab_option'] = 'Option'; +$_['tab_server'] = 'Server'; +$_['tab_seo'] = 'SEO'; +$_['tab_store'] = 'Store'; +$_['tab_special'] = 'Special'; +$_['tab_session'] = 'Session'; +$_['tab_local'] = 'Local'; +$_['tab_mail'] = 'Mail'; +$_['tab_payment_method'] = 'Payment Methods'; +$_['tab_product'] = 'Products'; +$_['tab_reward'] = 'Reward Points'; +$_['tab_transaction'] = 'Transactions'; +$_['tab_voucher'] = 'Vouchers'; +$_['tab_subscription'] = 'Subscription'; +$_['tab_report'] = 'Report'; + +// Error +$_['error_exception'] = 'Error Code(%s): %s in %s on line %s'; +$_['error_upload_1'] = 'Warning: The uploaded file exceeds the upload_max_filesize directive in php.ini!'; +$_['error_upload_2'] = 'Warning: The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form!'; +$_['error_upload_3'] = 'Warning: The uploaded file was only partially uploaded!'; +$_['error_upload_4'] = 'Warning: No file was uploaded!'; +$_['error_upload_6'] = 'Warning: Missing a temporary folder!'; +$_['error_upload_7'] = 'Warning: Failed to write file to disk!'; +$_['error_upload_8'] = 'Warning: File upload stopped by extension!'; +$_['error_upload_999'] = 'Warning: No error code available!'; +$_['error_upload_size'] = 'Warning: The uploaded file exceeds the %smb max file size!'; +$_['error_curl'] = 'CURL: Error Code(%s): %s'; +$_['error_format_b'] = 'Warning: The uploaded file exceeds the max file size: %s bytes!'; +$_['error_format_kb'] = 'Warning: The uploaded file exceeds the max file size: %s kilobytes!'; +$_['error_format_mb'] = 'Warning: The uploaded file exceeds the max file size: %s megabytes!'; +$_['error_format_gb'] = 'Warning: The uploaded file exceeds the max file size: %s gigabytes!'; + +/* When doing translations only include the matching language code */ + +// CKEditor +//$_['ckeditor'] = 'af'; +//$_['ckeditor'] = 'ar'; +//$_['ckeditor'] = 'az'; +//$_['ckeditor'] = 'bg'; +//$_['ckeditor'] = 'bn'; +//$_['ckeditor'] = 'bs'; +//$_['ckeditor'] = 'ca'; +//$_['ckeditor'] = 'cs'; +//$_['ckeditor'] = 'cy'; +//$_['ckeditor'] = 'da'; +//$_['ckeditor'] = 'de'; +//$_['ckeditor'] = 'de-ch'; +//$_['ckeditor'] = 'el'; +$_['ckeditor'] = 'en'; +//$_['ckeditor'] = 'en-au'; +//$_['ckeditor'] = 'en-ca'; +//$_['ckeditor'] = 'en-gb'; +//$_['ckeditor'] = 'eo'; +//$_['ckeditor'] = 'es'; +//$_['ckeditor'] = 'es-mx'; +//$_['ckeditor'] = 'et'; +//$_['ckeditor'] = 'eu'; +//$_['ckeditor'] = 'fa'; +//$_['ckeditor'] = 'fi'; +//$_['ckeditor'] = 'fo'; +//$_['ckeditor'] = 'fr'; +//$_['ckeditor'] = 'gl'; +//$_['ckeditor'] = 'gu'; +//$_['ckeditor'] = 'he'; +//$_['ckeditor'] = 'hi'; +//$_['ckeditor'] = 'hr'; +//$_['ckeditor'] = 'hu'; +//$_['ckeditor'] = 'id'; +//$_['ckeditor'] = 'is'; +//$_['ckeditor'] = 'it'; +//$_['ckeditor'] = 'ja'; +//$_['ckeditor'] = 'ka'; +//$_['ckeditor'] = 'km'; +//$_['ckeditor'] = 'ko'; +//$_['ckeditor'] = 'ku'; +//$_['ckeditor'] = 'lt'; +//$_['ckeditor'] = 'lv'; +//$_['ckeditor'] = 'mk'; +//$_['ckeditor'] = 'mn'; +//$_['ckeditor'] = 'ms'; +//$_['ckeditor'] = 'nb'; +//$_['ckeditor'] = 'nl'; +//$_['ckeditor'] = 'no'; +//$_['ckeditor'] = 'oc'; +//$_['ckeditor'] = 'pl'; +//$_['ckeditor'] = 'pt'; +//$_['ckeditor'] = 'pt-br'; +//$_['ckeditor'] = 'ro'; +//$_['ckeditor'] = 'ru'; +//$_['ckeditor'] = 'si'; +//$_['ckeditor'] = 'sk'; +//$_['ckeditor'] = 'sl'; +//$_['ckeditor'] = 'sq'; +//$_['ckeditor'] = 'sr'; +//$_['ckeditor'] = 'sr-latn'; +//$_['ckeditor'] = 'sv'; +//$_['ckeditor'] = 'th'; +//$_['ckeditor'] = 'tr'; +//$_['ckeditor'] = 'tt'; +//$_['ckeditor'] = 'ug'; +//$_['ckeditor'] = 'uk'; +//$_['ckeditor'] = 'vi'; +//$_['ckeditor'] = 'zh'; +//$_['ckeditor'] = 'zh-cn'; + +// Datepicker +$_['datepicker'] = 'en-gb'; +//$_['datepicker'] = 'af'; +//$_['datepicker'] = 'ar-dz'; +//$_['datepicker'] = 'ar-kw'; +//$_['datepicker'] = 'ar-ly'; +//$_['datepicker'] = 'ar-ma'; +//$_['datepicker'] = 'ar-sa'; +//$_['datepicker'] = 'ar-tn'; +//$_['datepicker'] = 'ar'; +//$_['datepicker'] = 'az'; +//$_['datepicker'] = 'be'; +//$_['datepicker'] = 'bg'; +//$_['datepicker'] = 'bn'; +//$_['datepicker'] = 'bo'; +//$_['datepicker'] = 'br'; +//$_['datepicker'] = 'bs'; +//$_['datepicker'] = 'ca'; +//$_['datepicker'] = 'cs'; +//$_['datepicker'] = 'cv'; +//$_['datepicker'] = 'cy'; +//$_['datepicker'] = 'da'; +//$_['datepicker'] = 'de-at'; +//$_['datepicker'] = 'de-ch'; +//$_['datepicker'] = 'de'; +//$_['datepicker'] = 'dv'; +//$_['datepicker'] = 'el'; +//$_['datepicker'] = 'en-au'; +//$_['datepicker'] = 'en-ca'; +//$_['datepicker'] = 'en-gb'; +//$_['datepicker'] = 'en-ie'; +//$_['datepicker'] = 'en-nz'; +//$_['datepicker'] = 'eo'; +//$_['datepicker'] = 'es-do'; +//$_['datepicker'] = 'es'; +//$_['datepicker'] = 'et'; +//$_['datepicker'] = 'eu'; +//$_['datepicker'] = 'fa'; +//$_['datepicker'] = 'fi'; +//$_['datepicker'] = 'fo'; +//$_['datepicker'] = 'fr-ca'; +//$_['datepicker'] = 'fr-ch'; +//$_['datepicker'] = 'fr'; +//$_['datepicker'] = 'fy'; +//$_['datepicker'] = 'gd'; +//$_['datepicker'] = 'gl'; +//$_['datepicker'] = 'gom-latn'; +//$_['datepicker'] = 'he'; +//$_['datepicker'] = 'hi'; +//$_['datepicker'] = 'hr'; +//$_['datepicker'] = 'hu'; +//$_['datepicker'] = 'hy-am'; +//$_['datepicker'] = 'id'; +//$_['datepicker'] = 'is'; +//$_['datepicker'] = 'it'; +//$_['datepicker'] = 'ja'; +//$_['datepicker'] = 'jv'; +//$_['datepicker'] = 'ka'; +//$_['datepicker'] = 'kk'; +//$_['datepicker'] = 'km'; +//$_['datepicker'] = 'kn'; +//$_['datepicker'] = 'ko'; +//$_['datepicker'] = 'ky'; +//$_['datepicker'] = 'lb'; +//$_['datepicker'] = 'lo'; +//$_['datepicker'] = 'lt'; +//$_['datepicker'] = 'lv'; +//$_['datepicker'] = 'me'; +//$_['datepicker'] = 'mi'; +//$_['datepicker'] = 'mk'; +//$_['datepicker'] = 'ml'; +//$_['datepicker'] = 'mr'; +//$_['datepicker'] = 'ms-my'; +//$_['datepicker'] = 'ms'; +//$_['datepicker'] = 'my'; +//$_['datepicker'] = 'nb'; +//$_['datepicker'] = 'ne'; +//$_['datepicker'] = 'nl-be'; +//$_['datepicker'] = 'nl'; +//$_['datepicker'] = 'nn'; +//$_['datepicker'] = 'pa-in'; +//$_['datepicker'] = 'pl'; +//$_['datepicker'] = 'pt-br'; +//$_['datepicker'] = 'pt'; +//$_['datepicker'] = 'ro'; +//$_['datepicker'] = 'ru'; +//$_['datepicker'] = 'sd'; +//$_['datepicker'] = 'se'; +//$_['datepicker'] = 'si'; +//$_['datepicker'] = 'sk'; +//$_['datepicker'] = 'sl'; +//$_['datepicker'] = 'sq'; +//$_['datepicker'] = 'sr-cyrl'; +//$_['datepicker'] = 'sr'; +//$_['datepicker'] = 'ss'; +//$_['datepicker'] = 'sv'; +//$_['datepicker'] = 'sw'; +//$_['datepicker'] = 'ta'; +//$_['datepicker'] = 'te'; +//$_['datepicker'] = 'tet'; +//$_['datepicker'] = 'th'; +//$_['datepicker'] = 'tl-ph'; +//$_['datepicker'] = 'tlh'; +//$_['datepicker'] = 'tr'; +//$_['datepicker'] = 'tzl'; +//$_['datepicker'] = 'tzm-latn'; +//$_['datepicker'] = 'tzm'; +//$_['datepicker'] = 'uk'; +//$_['datepicker'] = 'ur'; +//$_['datepicker'] = 'uz-latn'; +//$_['datepicker'] = 'uz'; +//$_['datepicker'] = 'vi'; +//$_['datepicker'] = 'x-pseudo'; +//$_['datepicker'] = 'yo'; +//$_['datepicker'] = 'zh-cn'; +//$_['datepicker'] = 'zh-hk'; +//$_['datepicker'] = 'zh-tw'; diff --git a/admininistrator/language/en-gb/design/banner.php b/admininistrator/language/en-gb/design/banner.php new file mode 100644 index 0000000..0e7205f --- /dev/null +++ b/admininistrator/language/en-gb/design/banner.php @@ -0,0 +1,28 @@ +Twig syntax here.'; + +// Column +$_['column_store'] = 'Store'; +$_['column_route'] = 'Route'; +$_['column_date_added'] = 'Date Added'; +$_['column_action'] = 'Action'; + +// Error +$_['error_permission'] = 'Warning: You do not have permission to modify the theme editor!'; +$_['error_twig'] = 'Warning: You can only save .twig files!'; diff --git a/admininistrator/language/en-gb/design/translation.php b/admininistrator/language/en-gb/design/translation.php new file mode 100644 index 0000000..1fda306 --- /dev/null +++ b/admininistrator/language/en-gb/design/translation.php @@ -0,0 +1,32 @@ +here!'; +$_['text_add'] = 'Add Module'; +$_['text_list'] = 'Module List'; + +// Column +$_['column_name'] = 'Module Name'; +$_['column_status'] = 'Status'; +$_['column_action'] = 'Action'; + +// Entry +$_['entry_code'] = 'Module'; +$_['entry_name'] = 'Module Name'; + +// Error +$_['error_permission'] = 'Warning: You do not have permission to modify modules!'; +$_['error_extension'] = 'Warning: Extension does not exist!'; +$_['error_name'] = 'Module Name must be between 3 and 64 characters!'; +$_['error_code'] = 'Extension required!'; diff --git a/admininistrator/language/en-gb/extension/other.php b/admininistrator/language/en-gb/extension/other.php new file mode 100644 index 0000000..92e2470 --- /dev/null +++ b/admininistrator/language/en-gb/extension/other.php @@ -0,0 +1,16 @@ +Last Name = {lastname}
Company = {company}
Address 1 = {address_1}
Address 2 = {address_2}
City = {city}
Postcode = {postcode}
Zone = {zone}
Zone Code = {zone_code}
Country = {country}'; + +// Error +$_['error_permission'] = 'Warning: You do not have permission to modify address formats!'; +$_['error_name'] = 'Address Format Name must be between 1 and 128 characters!'; +$_['error_default'] = 'Warning: This address format cannot be deleted as it is currently assigned as the default address format!'; +$_['error_country'] = 'Warning: This address format cannot be deleted as it is currently assigned to %s countries!'; diff --git a/admininistrator/language/en-gb/localisation/country.php b/admininistrator/language/en-gb/localisation/country.php new file mode 100644 index 0000000..1d7dd5b --- /dev/null +++ b/admininistrator/language/en-gb/localisation/country.php @@ -0,0 +1,33 @@ +here.'; + +// Column +$_['column_title'] = 'Currency Title'; +$_['column_code'] = 'Code'; +$_['column_value'] = 'Value'; +$_['column_status'] = 'Status'; +$_['column_date_modified'] = 'Last Updated'; +$_['column_action'] = 'Action'; + +// Entry +$_['entry_title'] = 'Currency Title'; +$_['entry_code'] = 'Code'; +$_['entry_value'] = 'Value'; +$_['entry_symbol_left'] = 'Symbol Left'; +$_['entry_symbol_right'] = 'Symbol Right'; +$_['entry_decimal_place'] = 'Decimal Places'; +$_['entry_status'] = 'Status'; + +// Help +$_['help_code'] = 'Do not change if this is your default currency.'; +$_['help_value'] = 'The value of your default currency in the current currency unit. Set to 1 for your default currency.'; + +// Error +$_['error_permission'] = 'Warning: You do not have permission to modify currencies!'; +$_['error_extension'] = 'Warning: The currency extension could not be found!'; +$_['error_title'] = 'Currency Title must be between 3 and 32 characters!'; +$_['error_code'] = 'Currency Code must contain 3 characters!'; +$_['error_default'] = 'Warning: This currency cannot be deleted as it is currently assigned as the default store currency!'; +$_['error_store'] = 'Warning: This currency cannot be deleted as it is currently assigned to %s stores!'; +$_['error_order'] = 'Warning: This currency cannot be deleted as it is currently assigned to %s orders!'; \ No newline at end of file diff --git a/admininistrator/language/en-gb/localisation/geo_zone.php b/admininistrator/language/en-gb/localisation/geo_zone.php new file mode 100644 index 0000000..489114f --- /dev/null +++ b/admininistrator/language/en-gb/localisation/geo_zone.php @@ -0,0 +1,27 @@ +%s,'; +$_['text_user'] = 'User'; +$_['text_gdpr'] = 'Your GDPR data deletion request has been approved and will be deleted in %s Days.'; +$_['text_q'] = 'Q. Why do we not delete your data straight away?'; +$_['text_a'] = 'A. Account deletion requests will process after %s days so any refunds, chargebacks or fraud detection can be processed.'; +$_['text_delete'] = 'You will receive a email informing you when your account has been deleted.'; +$_['text_thanks'] = 'Thanks,'; \ No newline at end of file diff --git a/admininistrator/language/en-gb/mail/gdpr_delete.php b/admininistrator/language/en-gb/mail/gdpr_delete.php new file mode 100644 index 0000000..356d29e --- /dev/null +++ b/admininistrator/language/en-gb/mail/gdpr_delete.php @@ -0,0 +1,12 @@ +%s,'; +$_['text_user'] = 'User'; +$_['text_delete'] = 'Your GDPR data deletion request has now been completed.'; +$_['text_contact'] = 'For more information you can contact the store owner here:'; +$_['text_thanks'] = 'Thanks,'; + +// Button +$_['button_contact'] = 'Contact Us'; \ No newline at end of file diff --git a/admininistrator/language/en-gb/mail/gdpr_deny.php b/admininistrator/language/en-gb/mail/gdpr_deny.php new file mode 100644 index 0000000..b62a159 --- /dev/null +++ b/admininistrator/language/en-gb/mail/gdpr_deny.php @@ -0,0 +1,12 @@ +%s,'; +$_['text_user'] = 'User'; +$_['text_contact'] = 'Unfortunately your request has been denied. For more information you can contact the store here:'; +$_['text_thanks'] = 'Thanks,'; + +// Button +$_['button_contact'] = 'Contact Us'; \ No newline at end of file diff --git a/admininistrator/language/en-gb/mail/gdpr_export.php b/admininistrator/language/en-gb/mail/gdpr_export.php new file mode 100644 index 0000000..8d8bde4 --- /dev/null +++ b/admininistrator/language/en-gb/mail/gdpr_export.php @@ -0,0 +1,26 @@ +%s,'; +$_['text_user'] = 'User'; +$_['text_gdpr'] = 'Your GDPR data request has now been complete. Below you will find your GDPR data.'; +$_['text_account'] = 'Account'; +$_['text_customer'] = 'Personal Information'; +$_['text_address'] = 'Address'; +$_['text_addresses'] = 'Addresses'; +$_['text_name'] = 'Customer Name'; +$_['text_recipient'] = 'Recipient'; +$_['text_email'] = 'E-Mail'; +$_['text_telephone'] = 'Telephone'; +$_['text_company'] = 'Company'; +$_['text_address_1'] = 'Address 1'; +$_['text_address_2'] = 'Address 2'; +$_['text_postcode'] = 'Post Code'; +$_['text_city'] = 'City'; +$_['text_country'] = 'Country'; +$_['text_zone'] = 'Region / State'; +$_['text_history'] = 'Login History'; +$_['text_ip'] = 'IP'; +$_['text_date_added'] = 'Date Added'; +$_['text_thanks'] = 'Thanks,'; \ No newline at end of file diff --git a/admininistrator/language/en-gb/mail/returns.php b/admininistrator/language/en-gb/mail/returns.php new file mode 100644 index 0000000..8cb6696 --- /dev/null +++ b/admininistrator/language/en-gb/mail/returns.php @@ -0,0 +1,8 @@ +%s. Then, click on the link below and purchase the product you wish to use this gift certificate. Lastly, you can enter the gift certificate code on the Shopping Cart page before you click: Checkout.'; +$_['text_footer'] = 'Please reply to this email if you have any questions.'; +$_['text_sent'] = 'Success: Gift Voucher e-mail has been sent!'; diff --git a/admininistrator/language/en-gb/marketing/affiliate.php b/admininistrator/language/en-gb/marketing/affiliate.php new file mode 100644 index 0000000..8e94ef8 --- /dev/null +++ b/admininistrator/language/en-gb/marketing/affiliate.php @@ -0,0 +1,82 @@ +here.'; + +// Entry +$_['entry_username'] = 'Username'; +$_['entry_secret'] = 'Secret'; + +// Error +$_['error_permission'] = 'Warning: You do not have permission to modify marketplace API!'; +$_['error_username'] = 'Username required!'; +$_['error_secret'] = 'Secret required!'; diff --git a/admininistrator/language/en-gb/marketplace/cron.php b/admininistrator/language/en-gb/marketplace/cron.php new file mode 100644 index 0000000..de5f4da --- /dev/null +++ b/admininistrator/language/en-gb/marketplace/cron.php @@ -0,0 +1,28 @@ +opencart documentation page.'; +$_['text_cron_2'] = 'You need to set your Cron task to run every hour.'; +$_['text_info'] = 'CRON Information'; +$_['text_hour'] = 'Hour'; +$_['text_day'] = 'Day'; +$_['text_month'] = 'Month'; + +// Column +$_['column_code'] = 'Cron Code'; +$_['column_cycle'] = 'Cycle'; +$_['column_date_added'] = 'Date Added'; +$_['column_date_modified'] = 'Date Modified'; +$_['column_action'] = 'Action'; + +// entry +$_['entry_cron'] = 'Cron URL'; +$_['entry_description'] = 'Description'; + +// Error +$_['error_permission'] = 'Warning: You do not have permission to modify cron jobs!'; \ No newline at end of file diff --git a/admininistrator/language/en-gb/marketplace/event.php b/admininistrator/language/en-gb/marketplace/event.php new file mode 100644 index 0000000..4febe86 --- /dev/null +++ b/admininistrator/language/en-gb/marketplace/event.php @@ -0,0 +1,22 @@ + before you can download extensions or make any purchases!'; +$_['error_purchase'] = 'The extension could not be purchased!'; +$_['error_download'] = 'The extension could not be downloaded!'; diff --git a/admininistrator/language/en-gb/marketplace/promotion.php b/admininistrator/language/en-gb/marketplace/promotion.php new file mode 100644 index 0000000..deb42fb --- /dev/null +++ b/admininistrator/language/en-gb/marketplace/promotion.php @@ -0,0 +1,6 @@ +order!'; \ No newline at end of file diff --git a/admininistrator/language/en-gb/sale/voucher_theme.php b/admininistrator/language/en-gb/sale/voucher_theme.php new file mode 100644 index 0000000..ed52159 --- /dev/null +++ b/admininistrator/language/en-gb/sale/voucher_theme.php @@ -0,0 +1,24 @@ +https://security.google.com/settings/security/apppasswords.'; +$_['help_mail_alert'] = 'Select which features you would like to receive an alert email on when a customer uses them.'; +$_['help_mail_alert_email'] = 'Any additional emails you want to receive the alert email, in addition to the main store email. (comma separated).'; +$_['help_session_expire'] = 'Set the PHP Session lifetime in seconds (e.g. 3600 = 1 hour)'; +$_['help_session_samesite'] = 'Set the PHP Session samesite cookie'; +$_['help_security'] = 'Two-factor security for admin users.'; +$_['help_shared'] = 'Try to share the session cookie between stores so the cart can be passed between different domains.'; +$_['help_robots'] = 'A list of web crawler user agents that shared sessions will not be used with. Use separate lines for each user agent.'; +$_['help_seo_url'] = 'To use SEO URLs, apache module mod-rewrite must be installed and you need to rename the htaccess.txt to .htaccess.'; +$_['help_file_max_size'] = 'The maximum file size you can allow customers to upload. Enter as megabyte.'; +$_['help_file_ext_allowed'] = 'Add which file extensions are allowed to be uploaded. Use a new line for each value.'; +$_['help_file_mime_allowed'] = 'Add which file mime types are allowed to be uploaded. Use a new line for each value.'; +$_['help_maintenance'] = 'Prevents customers from browsing your store. They will instead see a maintenance message. If logged in as admin, you will see the store as normal.'; +$_['help_encryption'] = 'Please provide a secret key that will be used to encrypt private information when processing orders.'; +$_['help_compression'] = 'GZIP for more efficient transfer to requesting clients. Compression level must be between 0 - 9.'; + +// Error +$_['error_warning'] = 'Warning: Please check the form carefully for errors!'; +$_['error_permission'] = 'Warning: You do not have permission to modify settings!'; +$_['error_meta_title'] = 'Title must be between 3 and 32 characters!'; +$_['error_name'] = 'Store Name must be between 3 and 32 characters!'; +$_['error_owner'] = 'Store Owner must be between 3 and 64 characters!'; +$_['error_address'] = 'Store Address must be between 10 and 256 characters!'; +$_['error_email'] = 'E-Mail Address does not appear to be valid!'; +$_['error_telephone'] = 'Telephone must be between 3 and 32 characters!'; +$_['error_product_description_length'] = 'Product description length required!'; +$_['error_pagination'] = 'Pagination required!'; +$_['error_login_attempts'] = 'Login Attempts must be greater than 0!'; +$_['error_customer_group_display'] = 'You must include the default customer group if you are going to use this feature!'; +$_['error_voucher_min'] = 'Minimum voucher amount required!'; +$_['error_voucher_max'] = 'Maximum voucher amount required!'; +$_['error_customer_online_expire'] = 'Timeout setting required for customer online list!'; +$_['error_processing_status'] = 'You must choose at least 1 order process status'; +$_['error_complete_status'] = 'You must choose at least 1 order complete status'; +$_['error_image_thumb'] = 'Product Image Thumb Size dimensions required!'; +$_['error_image_popup'] = 'Product Image Popup Size dimensions required!'; +$_['error_image_product'] = 'Product List Size dimensions required!'; +$_['error_image_category'] = 'Category List Size dimensions required!'; +$_['error_image_additional'] = 'Additional Product Image Size dimensions required!'; +$_['error_image_related'] = 'Related Product Image Size dimensions required!'; +$_['error_image_compare'] = 'Compare Image Size dimensions required!'; +$_['error_image_wishlist'] = 'Wish List Image Size dimensions required!'; +$_['error_image_cart'] = 'Cart Image Size dimensions required!'; +$_['error_image_location'] = 'Store Image Size dimensions required!'; +$_['error_file_max_size'] = 'Max File Size required!'; +$_['error_security'] = 'Two-factor Security cannot be used if you do not have your email setup yet!'; +$_['error_extension'] = 'PHP uploads are not allowed!'; +$_['error_mime'] = 'PHP uploads are not allowed!'; +$_['error_log_required'] = 'Error Log Filename required!'; +$_['error_log_invalid'] = 'Error Log Filename invalid!'; +$_['error_log_extension'] = 'Error Log Filename extension needs to be .log!'; +$_['error_encryption'] = 'Encryption Key must be between 32 and 1024 characters!'; diff --git a/admininistrator/language/en-gb/setting/store.php b/admininistrator/language/en-gb/setting/store.php new file mode 100644 index 0000000..1c8b981 --- /dev/null +++ b/admininistrator/language/en-gb/setting/store.php @@ -0,0 +1,128 @@ +
Don\'t use directories to create a new store. You should always point another domain or sub domain to your hosting.'; +$_['help_geocode'] = 'Please enter your store location geocode manually.'; +$_['help_open'] = 'Fill in your stores opening times.'; +$_['help_comment'] = 'This field is for any special notes you would like to tell the customer i.e. Store does not accept cheques.'; +$_['help_location'] = 'The different store locations you have that you want displayed on the contact us form.'; +$_['help_currency'] = 'Change the default currency. Clear your browser cache to see the change and reset your existing cookie.'; +$_['help_pagination'] = 'Determines how many catalog items are shown per page (products, categories, etc)'; +$_['help_product_description_length'] = 'In the list view, short description character limit (categories, special etc)'; +$_['help_cookie'] = 'Display Cookie policy as part of the EU Law.'; +$_['help_gdpr'] = 'Enable GDPR features such as customers being able to request account deletion.'; +$_['help_tax_default'] = 'Use the store address to calculate taxes if customer is not logged in. You can choose to use the store address for the customer\'s shipping or payment address.'; +$_['help_tax_customer'] = 'Use the customers default address when they login to calculate taxes. You can choose to use the default address for the customer\'s shipping or payment address.'; +$_['help_customer_group'] = 'Default customer group.'; +$_['help_customer_group_display'] = 'Display customer groups that new customers can select to use such as wholesale and business when signing up.'; +$_['help_customer_price'] = 'Only show prices when a customer is logged in.'; +$_['help_account'] = 'Forces people to agree to terms before an account can be created.'; +$_['help_checkout_guest'] = 'Allow customers to checkout without creating an account. This will not be available when a downloadable product is in the shopping cart.'; +$_['help_checkout'] = 'Forces people to agree to terms before an a customer can checkout.'; +$_['help_stock_display'] = 'Display stock quantity on the product page.'; +$_['help_stock_checkout'] = 'Allow customers to still checkout if the products they are ordering are not in stock.'; +$_['help_product_count'] = 'Show the number of products inside the subcategories in the storefront header category menu. Be warned, this will cause an extreme performance hit for stores with a lot of subcategories!'; + +// Error +$_['error_warning'] = 'Warning: Please check the form carefully for errors!'; +$_['error_permission'] = 'Warning: You do not have permission to modify stores!'; +$_['error_url'] = 'Store URL required!'; +$_['error_meta_title'] = 'Title must be between 3 and 32 characters!'; +$_['error_name'] = 'Store Name must be between 3 and 32 characters!'; +$_['error_owner'] = 'Store Owner must be between 3 and 64 characters!'; +$_['error_address'] = 'Store Address must be between 10 and 256 characters!'; +$_['error_email'] = 'E-Mail Address does not appear to be valid!'; +$_['error_telephone'] = 'Telephone must be between 3 and 32 characters!'; +$_['error_product_description_length'] = 'Product description length required!'; +$_['error_pagination'] = 'Pagination required!'; +$_['error_customer_group_display'] = 'You must include the default customer group if you are going to use this feature!'; +$_['error_default'] = 'Warning: You cannot delete your default store!'; +$_['error_order'] = 'Warning: This Store cannot be deleted as it is currently assigned to %s orders!'; +$_['error_subscription'] = 'Warning: This Store cannot be deleted as it is currently assigned to %s subscriptions!'; +$_['error_image_thumb'] = 'Product Image Thumb Size dimensions required!'; +$_['error_image_popup'] = 'Product Image Popup Size dimensions required!'; +$_['error_image_product'] = 'Product List Size dimensions required!'; +$_['error_image_category'] = 'Category List Size dimensions required!'; +$_['error_image_additional'] = 'Additional Product Image Size dimensions required!'; +$_['error_image_related'] = 'Related Product Image Size dimensions required!'; +$_['error_image_compare'] = 'Compare Image Size dimensions required!'; +$_['error_image_wishlist'] = 'Wish List Image Size dimensions required!'; +$_['error_image_cart'] = 'Cart Image Size dimensions required!'; +$_['error_image_location'] = 'Store Image Size dimensions required!'; diff --git a/admininistrator/language/en-gb/tool/backup.php b/admininistrator/language/en-gb/tool/backup.php new file mode 100644 index 0000000..d3fd499 --- /dev/null +++ b/admininistrator/language/en-gb/tool/backup.php @@ -0,0 +1,33 @@ +~/storage/backup/ directory.'; + +// Column +$_['column_filename'] = 'Filename'; +$_['column_size'] = 'Size'; +$_['column_date_added'] = 'Date Added'; +$_['column_action'] = 'Action'; + +// Entry +$_['entry_progress'] = 'Progress'; +$_['entry_export'] = 'Export'; + +// Error +$_['error_permission'] = 'Warning: You do not have permission to modify Backup & Restore!'; +$_['error_export'] = 'Warning: You must select at least one table to export!'; +$_['error_table'] = 'Table %s is not in the allowed list!'; +$_['error_file'] = 'File could not be found!'; +$_['error_directory'] = 'Directory could not be found!'; +$_['error_not_found'] = 'Error: Could not find file %s !'; +$_['error_headers_sent'] = 'Error: Headers already sent out!'; +$_['error_upload_size'] = 'Upload file cannot be larger than %s!'; diff --git a/admininistrator/language/en-gb/tool/log.php b/admininistrator/language/en-gb/tool/log.php new file mode 100644 index 0000000..5a8a477 --- /dev/null +++ b/admininistrator/language/en-gb/tool/log.php @@ -0,0 +1,13 @@ +load->model('catalog/attribute'); + * + * @package Opencart\Admin\Model\Catalog + * */ +class Attribute extends \Opencart\System\Engine\Model { + /* + * Add Attribute + * + * Create a new attribute record in the database. + * + * @param array $data + * + * @return int returns the primary key of the new attribute record. + */ + /** + * @param array $data + * + * @return int + */ + public function addAttribute(array $data): int { + $this->db->query("INSERT INTO `" . DB_PREFIX . "attribute` SET `attribute_group_id` = '" . (int)$data['attribute_group_id'] . "', `sort_order` = '" . (int)$data['sort_order'] . "'"); + + $attribute_id = $this->db->getLastId(); + + foreach ($data['attribute_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "attribute_description` SET `attribute_id` = '" . (int)$attribute_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } + + return $attribute_id; + } + + /* + * Edit Attribute + * + * Edit attribute record in the database. + * + * @param int $attribute_id Primary key of the attribute record to edit. + * @param array $data Array of data [ + * 'attribute_group_id' + * ]. + * + * @return void + */ + /** + * @param int $attribute_id + * @param array $data + * + * @return void + */ + public function editAttribute(int $attribute_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "attribute` SET `attribute_group_id` = '" . (int)$data['attribute_group_id'] . "', `sort_order` = '" . (int)$data['sort_order'] . "' WHERE `attribute_id` = '" . (int)$attribute_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "attribute_description` WHERE `attribute_id` = '" . (int)$attribute_id . "'"); + + foreach ($data['attribute_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "attribute_description` SET `attribute_id` = '" . (int)$attribute_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } + } + + /* + * Delete Attribute + * + * Delete attribute record in the database. + * + * @param int $attribute_id primary key of the attribute record to be deleted + * + * @return void + * + */ + /** + * @param int $attribute_id + * + * @return void + */ + public function deleteAttribute(int $attribute_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "attribute` WHERE `attribute_id` = '" . (int)$attribute_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "attribute_description` WHERE `attribute_id` = '" . (int)$attribute_id . "'"); + } + + /* + * Get Attribute + * + * Get the record of the attribute record in the database. + * + * @param int $attribute_id primary key of the attribute record to be fetched + * + * @return array + * + */ + /** + * @param int $attribute_id + * + * @return array + */ + public function getAttribute(int $attribute_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "attribute` a LEFT JOIN `" . DB_PREFIX . "attribute_description` ad ON (a.`attribute_id` = ad.`attribute_id`) WHERE a.`attribute_id` = '" . (int)$attribute_id . "' AND ad.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return $query->row; + } + + /* + * Get Attributes + * + * Get the record of the attribute record in the database. + * + * @param array $data array of filters + * + * @return array + * + */ + /** + * @param array $data + * + * @return array + */ + public function getAttributes(array $data = []): array { + $sql = "SELECT *, (SELECT agd.`name` FROM `" . DB_PREFIX . "attribute_group_description` agd WHERE agd.`attribute_group_id` = a.`attribute_group_id` AND agd.`language_id` = '" . (int)$this->config->get('config_language_id') . "') AS attribute_group FROM `" . DB_PREFIX . "attribute` a LEFT JOIN `" . DB_PREFIX . "attribute_description` ad ON (a.`attribute_id` = ad.`attribute_id`) WHERE ad.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"; + + if (!empty($data['filter_name'])) { + $sql .= " AND ad.`name` LIKE '" . $this->db->escape((string)$data['filter_name'] . '%') . "'"; + } + + if (!empty($data['filter_attribute_group_id'])) { + $sql .= " AND a.`attribute_group_id` = '" . (int)$data['filter_attribute_group_id'] . "'"; + } + + $sort_data = ['ad.name', 'attribute_group', 'a.sort_order']; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `attribute_group`, ad.`name`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /* + * Get Descriptions + * + * Get the record of the attribute record in the database. + * + * @param int $attribute_id primary key of the attribute record to be fetched. + * + * @return array returns array of descriptions sorted by language_id + * + */ + /** + * @param int $attribute_id + * + * @return array + */ + public function getDescriptions(int $attribute_id): array { + $attribute_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "attribute_description` WHERE `attribute_id` = '" . (int)$attribute_id . "'"); + + foreach ($query->rows as $result) { + $attribute_data[$result['language_id']] = ['name' => $result['name']]; + } + + return $attribute_data; + } + + /* + * Get Total Attributes + * + * Get the total number of attribute records in the database. + * + * @return int Total number of attribute records. + */ + /** + * @return int + */ + public function getTotalAttributes(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "attribute`"); + + if ($query->num_rows) { + return (int)$query->row['total']; + } else { + return 0; + } + } + + /* + * Get Total Attributes By Attribute Group ID + * + * Get the total number of attribute records with group ID in the database. + * + * @param int $attribute_group_id foreign key of the attribute record to be fetched. + * + * @return int Total number of attribute records that have attribute group ID. + */ + /** + * @param int $attribute_group_id + * + * @return int + */ + public function getTotalAttributesByAttributeGroupId(int $attribute_group_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "attribute` WHERE `attribute_group_id` = '" . (int)$attribute_group_id . "'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/catalog/attribute_group.php b/admininistrator/model/catalog/attribute_group.php new file mode 100644 index 0000000..943dc12 --- /dev/null +++ b/admininistrator/model/catalog/attribute_group.php @@ -0,0 +1,127 @@ +db->query("INSERT INTO `" . DB_PREFIX . "attribute_group` SET `sort_order` = '" . (int)$data['sort_order'] . "'"); + + $attribute_group_id = $this->db->getLastId(); + + foreach ($data['attribute_group_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "attribute_group_description` SET `attribute_group_id` = '" . (int)$attribute_group_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } + + return $attribute_group_id; + } + + /** + * @param int $attribute_group_id + * @param array $data + * + * @return void + */ + public function editAttributeGroup(int $attribute_group_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "attribute_group` SET `sort_order` = '" . (int)$data['sort_order'] . "' WHERE `attribute_group_id` = '" . (int)$attribute_group_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "attribute_group_description` WHERE `attribute_group_id` = '" . (int)$attribute_group_id . "'"); + + foreach ($data['attribute_group_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "attribute_group_description` SET `attribute_group_id` = '" . (int)$attribute_group_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } + } + + /** + * @param int $attribute_group_id + * + * @return void + */ + public function deleteAttributeGroup(int $attribute_group_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "attribute_group` WHERE `attribute_group_id` = '" . (int)$attribute_group_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "attribute_group_description` WHERE `attribute_group_id` = '" . (int)$attribute_group_id . "'"); + } + + /** + * @param int $attribute_group_id + * + * @return array + */ + public function getAttributeGroup(int $attribute_group_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "attribute_group` WHERE `attribute_group_id` = '" . (int)$attribute_group_id . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getAttributeGroups(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "attribute_group` ag LEFT JOIN `" . DB_PREFIX . "attribute_group_description` agd ON (ag.`attribute_group_id` = agd.`attribute_group_id`) WHERE agd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"; + + $sort_data = ['agd.name', 'ag.sort_order']; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY agd.`name`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param int $attribute_group_id + * + * @return array + */ + public function getDescriptions(int $attribute_group_id): array { + $attribute_group_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "attribute_group_description` WHERE `attribute_group_id` = '" . (int)$attribute_group_id . "'"); + + foreach ($query->rows as $result) { + $attribute_group_data[$result['language_id']] = ['name' => $result['name']]; + } + + return $attribute_group_data; + } + + /** + * @return int + */ + public function getTotalAttributeGroups(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "attribute_group`"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/catalog/category.php b/admininistrator/model/catalog/category.php new file mode 100644 index 0000000..68880b3 --- /dev/null +++ b/admininistrator/model/catalog/category.php @@ -0,0 +1,451 @@ +db->query("INSERT INTO `" . DB_PREFIX . "category` SET `image` = '" . $this->db->escape((string)$data['image']) . "', `parent_id` = '" . (int)$data['parent_id'] . "', `top` = '" . (isset($data['top']) ? (int)$data['top'] : 0) . "', `column` = '" . (int)$data['column'] . "', `sort_order` = '" . (int)$data['sort_order'] . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "', `date_modified` = NOW(), `date_added` = NOW()"); + + $category_id = $this->db->getLastId(); + + foreach ($data['category_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "category_description` SET `category_id` = '" . (int)$category_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "', `description` = '" . $this->db->escape($value['description']) . "', `meta_title` = '" . $this->db->escape($value['meta_title']) . "', `meta_description` = '" . $this->db->escape($value['meta_description']) . "', `meta_keyword` = '" . $this->db->escape($value['meta_keyword']) . "'"); + } + + // MySQL Hierarchical Data Closure Table Pattern + $level = 0; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "category_path` WHERE `category_id` = '" . (int)$data['parent_id'] . "' ORDER BY `level` ASC"); + + foreach ($query->rows as $result) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "category_path` SET `category_id` = '" . (int)$category_id . "', `path_id` = '" . (int)$result['path_id'] . "', `level` = '" . (int)$level . "'"); + + $level++; + } + + $this->db->query("INSERT INTO `" . DB_PREFIX . "category_path` SET `category_id` = '" . (int)$category_id . "', `path_id` = '" . (int)$category_id . "', `level` = '" . (int)$level. "'"); + + if (isset($data['category_filter'])) { + foreach ($data['category_filter'] as $filter_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "category_filter` SET `category_id` = '" . (int)$category_id . "', `filter_id` = '" . (int)$filter_id . "'"); + } + } + + if (isset($data['category_store'])) { + foreach ($data['category_store'] as $store_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "category_to_store` SET `category_id` = '" . (int)$category_id . "', `store_id` = '" . (int)$store_id . "'"); + } + } + + // Seo urls on categories need to be done differently to they include the full keyword path + $parent_path = $this->getPath($data['parent_id']); + + if (!$parent_path) { + $path = $category_id; + } else { + $path = $parent_path . '_' . $category_id; + } + + $this->load->model('design/seo_url'); + + foreach ($data['category_seo_url'] as $store_id => $language) { + foreach ($language as $language_id => $keyword) { + $seo_url_info = $this->model_design_seo_url->getSeoUrlByKeyValue('path', $parent_path, $store_id, $language_id); + + if ($seo_url_info) { + $keyword = $seo_url_info['keyword'] . '/' . $keyword; + } + + $this->db->query("INSERT INTO `" . DB_PREFIX . "seo_url` SET `store_id` = '" . (int)$store_id . "', `language_id` = '" . (int)$language_id . "', `key` = 'path', `value`= '" . $this->db->escape($path) . "', `keyword` = '" . $this->db->escape($keyword) . "'"); + } + } + + // Set which layout to use with this category + if (isset($data['category_layout'])) { + foreach ($data['category_layout'] as $store_id => $layout_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "category_to_layout` SET `category_id` = '" . (int)$category_id . "', `store_id` = '" . (int)$store_id . "', `layout_id` = '" . (int)$layout_id . "'"); + } + } + + return $category_id; + } + + /** + * @param int $category_id + * @param array $data + * + * @return void + */ + public function editCategory(int $category_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "category` SET `image` = '" . $this->db->escape((string)$data['image']) . "', `parent_id` = '" . (int)$data['parent_id'] . "', `top` = '" . (isset($data['top']) ? (int)$data['top'] : 0) . "', `column` = '" . (int)$data['column'] . "', `sort_order` = '" . (int)$data['sort_order'] . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "', `date_modified` = NOW() WHERE `category_id` = '" . (int)$category_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "category_description` WHERE `category_id` = '" . (int)$category_id . "'"); + + foreach ($data['category_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "category_description` SET `category_id` = '" . (int)$category_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "', `description` = '" . $this->db->escape($value['description']) . "', `meta_title` = '" . $this->db->escape($value['meta_title']) . "', `meta_description` = '" . $this->db->escape($value['meta_description']) . "', `meta_keyword` = '" . $this->db->escape($value['meta_keyword']) . "'"); + } + + // Old path + $path_old = $this->getPath($category_id); + + // MySQL Hierarchical Data Closure Table Pattern + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "category_path` WHERE `path_id` = '" . (int)$category_id . "' ORDER BY `level` ASC"); + + if ($query->rows) { + foreach ($query->rows as $category_path) { + // Delete the path below the current one + $this->db->query("DELETE FROM `" . DB_PREFIX . "category_path` WHERE `category_id` = '" . (int)$category_path['category_id'] . "' AND `level` < '" . (int)$category_path['level'] . "'"); + + $paths = []; + + // Get the nodes new parents + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "category_path` WHERE `category_id` = '" . (int)$data['parent_id'] . "' ORDER BY `level` ASC"); + + foreach ($query->rows as $result) { + $paths[] = $result['path_id']; + } + + // Get whats left of the nodes current path + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "category_path` WHERE `category_id` = '" . (int)$category_path['category_id'] . "' ORDER BY `level` ASC"); + + foreach ($query->rows as $result) { + $paths[] = $result['path_id']; + } + + // Combine the paths with a new level + $level = 0; + + foreach ($paths as $path_id) { + $this->db->query("REPLACE INTO `" . DB_PREFIX . "category_path` SET `category_id` = '" . (int)$category_path['category_id'] . "', `path_id` = '" . (int)$path_id . "', `level` = '" . (int)$level . "'"); + + $level++; + } + } + } else { + // Delete the path below the current one + $this->db->query("DELETE FROM `" . DB_PREFIX . "category_path` WHERE `category_id` = '" . (int)$category_id . "'"); + + // Fix for records with no paths + $level = 0; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "category_path` WHERE `category_id` = '" . (int)$data['parent_id'] . "' ORDER BY `level` ASC"); + + foreach ($query->rows as $result) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "category_path` SET `category_id` = '" . (int)$category_id . "', `path_id` = '" . (int)$result['path_id'] . "', `level` = '" . (int)$level . "'"); + + $level++; + } + + $this->db->query("REPLACE INTO `" . DB_PREFIX . "category_path` SET `category_id` = '" . (int)$category_id . "', `path_id` = '" . (int)$category_id . "', `level` = '" . (int)$level . "'"); + } + + $this->db->query("DELETE FROM `" . DB_PREFIX . "category_filter` WHERE `category_id` = '" . (int)$category_id . "'"); + + if (isset($data['category_filter'])) { + foreach ($data['category_filter'] as $filter_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "category_filter` SET `category_id` = '" . (int)$category_id . "', `filter_id` = '" . (int)$filter_id . "'"); + } + } + + $this->db->query("DELETE FROM `" . DB_PREFIX . "category_to_store` WHERE `category_id` = '" . (int)$category_id . "'"); + + if (isset($data['category_store'])) { + foreach ($data['category_store'] as $store_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "category_to_store` SET `category_id` = '" . (int)$category_id . "', `store_id` = '" . (int)$store_id . "'"); + } + } + + // Seo urls on categories need to be done differently to they include the full keyword path + $path_parent = $this->getPath($data['parent_id']); + + if (!$path_parent) { + $path_new = $category_id; + } else { + $path_new = $path_parent . '_' . $category_id; + } + + // Get old data to so we know what to replace + $seo_url_data = $this->getSeoUrls($category_id); + + // Delete the old path + $this->db->query("DELETE FROM `" . DB_PREFIX . "seo_url` WHERE `key` = 'path' AND `value` = '" . $this->db->escape($path_old) . "'"); + + $this->load->model('design/seo_url'); + + foreach ($data['category_seo_url'] as $store_id => $language) { + foreach ($language as $language_id => $keyword) { + $parent_info = $this->model_design_seo_url->getSeoUrlByKeyValue('path', $path_parent, $store_id, $language_id); + + if ($parent_info) { + $keyword = $parent_info['keyword'] . '/' . $keyword; + } + + $this->db->query("INSERT INTO `" . DB_PREFIX . "seo_url` SET `store_id` = '" . (int)$store_id . "', `language_id` = '" . (int)$language_id . "', `key` = 'path', `value` = '" . $this->db->escape($path_new) . "', `keyword` = '" . $this->db->escape($keyword) . "'"); + + // Update sub category seo urls + if (isset($seo_url_data[$store_id][$language_id])) { + $this->db->query("UPDATE `" . DB_PREFIX . "seo_url` SET `value` = CONCAT('" . $this->db->escape($path_new . '_') . "', SUBSTRING(`value`, " . (strlen($path_old . '_') + 1) . ")), `keyword` = CONCAT('" . $this->db->escape($keyword) . "', SUBSTRING(`keyword`, " . (oc_strlen($seo_url_data[$store_id][$language_id]) + 1) . ")) WHERE `store_id` = '" . (int)$store_id . "' AND `language_id` = '" . (int)$language_id . "' AND `key` = 'path' AND `value` LIKE '" . $this->db->escape($path_old . '\_%') . "'"); + } + } + } + + // Layouts + $this->db->query("DELETE FROM `" . DB_PREFIX . "category_to_layout` WHERE `category_id` = '" . (int)$category_id . "'"); + + if (isset($data['category_layout'])) { + foreach ($data['category_layout'] as $store_id => $layout_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "category_to_layout` SET `category_id` = '" . (int)$category_id . "', `store_id` = '" . (int)$store_id . "', `layout_id` = '" . (int)$layout_id . "'"); + } + } + } + + /** + * @param int $category_id + * + * @return void + */ + public function deleteCategory(int $category_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "category` WHERE `category_id` = '" . (int)$category_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "category_description` WHERE `category_id` = '" . (int)$category_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "category_filter` WHERE `category_id` = '" . (int)$category_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "category_to_store` WHERE `category_id` = '" . (int)$category_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "category_to_layout` WHERE `category_id` = '" . (int)$category_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_to_category` WHERE `category_id` = '" . (int)$category_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "coupon_category` WHERE `category_id` = '" . (int)$category_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "seo_url` WHERE `key` = 'path' AND `value` = '" . $this->db->escape($this->getPath($category_id)) . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "category_path` WHERE `category_id` = '" . (int)$category_id . "'"); + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "category_path` WHERE `path_id` = '" . (int)$category_id . "'"); + + foreach ($query->rows as $result) { + $this->deleteCategory($result['category_id']); + } + } + + /** + * @param int $parent_id + * + * @return void + */ + public function repairCategories(int $parent_id = 0): void { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "category` WHERE `parent_id` = '" . (int)$parent_id . "'"); + + foreach ($query->rows as $category) { + // Delete the path below the current one + $this->db->query("DELETE FROM `" . DB_PREFIX . "category_path` WHERE `category_id` = '" . (int)$category['category_id'] . "'"); + + // Fix for records with no paths + $level = 0; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "category_path` WHERE `category_id` = '" . (int)$parent_id . "' ORDER BY `level` ASC"); + + foreach ($query->rows as $result) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "category_path` SET `category_id` = '" . (int)$category['category_id'] . "', `path_id` = '" . (int)$result['path_id'] . "', `level` = '" . (int)$level . "'"); + + $level++; + } + + $this->db->query("REPLACE INTO `" . DB_PREFIX . "category_path` SET `category_id` = '" . (int)$category['category_id'] . "', `path_id` = '" . (int)$category['category_id'] . "', `level` = '" . (int)$level . "'"); + + $this->repairCategories($category['category_id']); + } + } + + /** + * @param int $category_id + * + * @return array + */ + public function getCategory(int $category_id): array { + $query = $this->db->query("SELECT DISTINCT *, (SELECT GROUP_CONCAT(cd1.`name` ORDER BY `level` SEPARATOR ' > ') FROM `" . DB_PREFIX . "category_path` cp LEFT JOIN `" . DB_PREFIX . "category_description` cd1 ON (cp.`path_id` = cd1.`category_id` AND cp.`category_id` != cp.`path_id`) WHERE cp.`category_id` = c.`category_id` AND cd1.`language_id` = '" . (int)$this->config->get('config_language_id') . "' GROUP BY cp.`category_id`) AS `path` FROM `" . DB_PREFIX . "category` c LEFT JOIN `" . DB_PREFIX . "category_description` cd2 ON (c.`category_id` = cd2.`category_id`) WHERE c.`category_id` = '" . (int)$category_id . "' AND cd2.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return $query->row; + } + + /** + * @param int $category_id + * + * @return string + */ + public function getPath(int $category_id): string { + return implode('_', array_column($this->getPaths($category_id), 'path_id')); + } + + /** + * @param int $category_id + * + * @return array + */ + public function getPaths(int $category_id): array { + $query = $this->db->query("SELECT `category_id`, `path_id`, `level` FROM `" . DB_PREFIX . "category_path` WHERE `category_id` = '" . (int)$category_id . "' ORDER BY `level` ASC"); + + return $query->rows; + } + + /** + * @param array $data + * + * @return array + */ + public function getCategories(array $data = []): array { + $sql = "SELECT cp.`category_id` AS `category_id`, GROUP_CONCAT(cd1.`name` ORDER BY cp.`level` SEPARATOR ' > ') AS `name`, c1.`parent_id`, c1.`sort_order`, c1.`status` FROM `" . DB_PREFIX . "category_path` cp LEFT JOIN `" . DB_PREFIX . "category` c1 ON (cp.`category_id` = c1.`category_id`) LEFT JOIN `" . DB_PREFIX . "category` c2 ON (cp.`path_id` = c2.`category_id`) LEFT JOIN `" . DB_PREFIX . "category_description` cd1 ON (cp.`path_id` = cd1.`category_id`) LEFT JOIN `" . DB_PREFIX . "category_description` cd2 ON (cp.`category_id` = cd2.`category_id`) WHERE cd1.`language_id` = '" . (int)$this->config->get('config_language_id') . "' AND cd2.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"; + + if (!empty($data['filter_name'])) { + $sql .= " AND cd2.`name` LIKE '" . $this->db->escape((string)$data['filter_name']) . "'"; + } + + $sql .= " GROUP BY cp.`category_id`"; + + $sort_data = [ + 'name', + 'sort_order' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `sort_order`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param int $category_id + * + * @return array + */ + public function getDescriptions(int $category_id): array { + $category_description_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "category_description` WHERE `category_id` = '" . (int)$category_id . "'"); + + foreach ($query->rows as $result) { + $category_description_data[$result['language_id']] = [ + 'name' => $result['name'], + 'meta_title' => $result['meta_title'], + 'meta_description' => $result['meta_description'], + 'meta_keyword' => $result['meta_keyword'], + 'description' => $result['description'] + ]; + } + + return $category_description_data; + } + + /** + * @param int $category_id + * + * @return array + */ + public function getFilters(int $category_id): array { + $category_filter_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "category_filter` WHERE `category_id` = '" . (int)$category_id . "'"); + + foreach ($query->rows as $result) { + $category_filter_data[] = $result['filter_id']; + } + + return $category_filter_data; + } + + /** + * @param int $category_id + * + * @return array + */ + public function getSeoUrls(int $category_id): array { + $category_seo_url_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "seo_url` WHERE `key` = 'path' AND `value` = '" . $this->db->escape($this->getPath($category_id)) . "'"); + + foreach ($query->rows as $result) { + $category_seo_url_data[$result['store_id']][$result['language_id']] = $result['keyword']; + } + + return $category_seo_url_data; + } + + /** + * @param int $category_id + * + * @return array + */ + public function getStores(int $category_id): array { + $category_store_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "category_to_store` WHERE `category_id` = '" . (int)$category_id . "'"); + + foreach ($query->rows as $result) { + $category_store_data[] = $result['store_id']; + } + + return $category_store_data; + } + + /** + * @param int $category_id + * + * @return array + */ + public function getLayouts(int $category_id): array { + $category_layout_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "category_to_layout` WHERE `category_id` = '" . (int)$category_id . "'"); + + foreach ($query->rows as $result) { + $category_layout_data[$result['store_id']] = $result['layout_id']; + } + + return $category_layout_data; + } + + /** + * @return int + */ + public function getTotalCategories(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "category`"); + + return (int)$query->row['total']; + } + + /** + * @param int $layout_id + * + * @return int + */ + public function getTotalCategoriesByLayoutId(int $layout_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "category_to_layout` WHERE `layout_id` = '" . (int)$layout_id . "'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/catalog/download.php b/admininistrator/model/catalog/download.php new file mode 100644 index 0000000..f35b342 --- /dev/null +++ b/admininistrator/model/catalog/download.php @@ -0,0 +1,166 @@ +db->query("INSERT INTO `" . DB_PREFIX . "download` SET `filename` = '" . $this->db->escape((string)$data['filename']) . "', `mask` = '" . $this->db->escape((string)$data['mask']) . "', `date_added` = NOW()"); + + $download_id = $this->db->getLastId(); + + foreach ($data['download_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "download_description` SET `download_id` = '" . (int)$download_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } + + return $download_id; + } + + /** + * @param int $download_id + * @param array $data + * + * @return void + */ + public function editDownload(int $download_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "download` SET `filename` = '" . $this->db->escape((string)$data['filename']) . "', `mask` = '" . $this->db->escape((string)$data['mask']) . "' WHERE `download_id` = '" . (int)$download_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "download_description` WHERE `download_id` = '" . (int)$download_id . "'"); + + foreach ($data['download_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "download_description` SET `download_id` = '" . (int)$download_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } + } + + /** + * @param int $download_id + * + * @return void + */ + public function deleteDownload(int $download_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "download` WHERE `download_id` = '" . (int)$download_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "download_description` WHERE `download_id` = '" . (int)$download_id . "'"); + } + + /** + * @param int $download_id + * + * @return array + */ + public function getDownload(int $download_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "download` d LEFT JOIN `" . DB_PREFIX . "download_description` dd ON (d.`download_id` = dd.`download_id`) WHERE d.`download_id` = '" . (int)$download_id . "' AND dd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getDownloads(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "download` d LEFT JOIN `" . DB_PREFIX . "download_description` dd ON (d.`download_id` = dd.`download_id`) WHERE dd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"; + + if (!empty($data['filter_name'])) { + $sql .= " AND dd.`name` LIKE '" . $this->db->escape((string)$data['filter_name'] . '%') . "'"; + } + + $sort_data = [ + 'dd.name', + 'd.date_added' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY dd.`name`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param int $download_id + * + * @return array + */ + public function getDescriptions(int $download_id): array { + $download_description_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "download_description` WHERE `download_id` = '" . (int)$download_id . "'"); + + foreach ($query->rows as $result) { + $download_description_data[$result['language_id']] = ['name' => $result['name']]; + } + + return $download_description_data; + } + + /** + * @return int + */ + public function getTotalDownloads(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "download`"); + + return (int)$query->row['total']; + } + + /** + * @param int $download_id + * @param int $start + * @param int $limit + * + * @return array + */ + public function getReports(int $download_id, int $start = 0, int $limit = 10): array { + if ($start < 0) { + $start = 0; + } + + if ($limit < 1) { + $limit = 10; + } + + $query = $this->db->query("SELECT `ip`, `store_id`, `country`, `date_added` FROM `" . DB_PREFIX . "download_report` WHERE `download_id` = '" . (int)$download_id . "' ORDER BY `date_added` ASC LIMIT " . (int)$start . "," . (int)$limit); + + return $query->rows; + } + + /** + * @param int $download_id + * + * @return int + */ + public function getTotalReports(int $download_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "download_report` WHERE `download_id` = '" . (int)$download_id . "'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/catalog/filter.php b/admininistrator/model/catalog/filter.php new file mode 100644 index 0000000..e054a0b --- /dev/null +++ b/admininistrator/model/catalog/filter.php @@ -0,0 +1,234 @@ +db->query("INSERT INTO `" . DB_PREFIX . "filter_group` SET `sort_order` = '" . (int)$data['sort_order'] . "'"); + + $filter_group_id = $this->db->getLastId(); + + foreach ($data['filter_group_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "filter_group_description` SET `filter_group_id` = '" . (int)$filter_group_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } + + if (isset($data['filter'])) { + foreach ($data['filter'] as $filter) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "filter` SET `filter_group_id` = '" . (int)$filter_group_id . "', `sort_order` = '" . (int)$filter['sort_order'] . "'"); + + $filter_id = $this->db->getLastId(); + + foreach ($filter['filter_description'] as $language_id => $filter_description) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "filter_description` SET `filter_id` = '" . (int)$filter_id . "', `language_id` = '" . (int)$language_id . "', `filter_group_id` = '" . (int)$filter_group_id . "', `name` = '" . $this->db->escape($filter_description['name']) . "'"); + } + } + } + + return $filter_group_id; + } + + /** + * @param int $filter_group_id + * @param array $data + * + * @return void + */ + public function editFilter(int $filter_group_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "filter_group` SET `sort_order` = '" . (int)$data['sort_order'] . "' WHERE `filter_group_id` = '" . (int)$filter_group_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "filter_group_description` WHERE `filter_group_id` = '" . (int)$filter_group_id . "'"); + + foreach ($data['filter_group_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "filter_group_description` SET `filter_group_id` = '" . (int)$filter_group_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } + + $this->db->query("DELETE FROM `" . DB_PREFIX . "filter` WHERE `filter_group_id` = '" . (int)$filter_group_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "filter_description` WHERE `filter_group_id` = '" . (int)$filter_group_id . "'"); + + if (isset($data['filter'])) { + foreach ($data['filter'] as $filter) { + if ($filter['filter_id']) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "filter` SET `filter_id` = '" . (int)$filter['filter_id'] . "', `filter_group_id` = '" . (int)$filter_group_id . "', `sort_order` = '" . (int)$filter['sort_order'] . "'"); + } else { + $this->db->query("INSERT INTO `" . DB_PREFIX . "filter` SET `filter_group_id` = '" . (int)$filter_group_id . "', `sort_order` = '" . (int)$filter['sort_order'] . "'"); + } + + $filter_id = $this->db->getLastId(); + + foreach ($filter['filter_description'] as $language_id => $filter_description) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "filter_description` SET `filter_id` = '" . (int)$filter_id . "', `language_id` = '" . (int)$language_id . "', `filter_group_id` = '" . (int)$filter_group_id . "', `name` = '" . $this->db->escape($filter_description['name']) . "'"); + } + } + } + } + + /** + * @param int $filter_group_id + * + * @return void + */ + public function deleteFilter(int $filter_group_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "filter_group` WHERE `filter_group_id` = '" . (int)$filter_group_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "filter_group_description` WHERE `filter_group_id` = '" . (int)$filter_group_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "filter` WHERE `filter_group_id` = '" . (int)$filter_group_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "filter_description` WHERE `filter_group_id` = '" . (int)$filter_group_id . "'"); + } + + /** + * @param int $filter_group_id + * + * @return array + */ + public function getGroup(int $filter_group_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "filter_group` fg LEFT JOIN `" . DB_PREFIX . "filter_group_description` fgd ON (fg.`filter_group_id` = fgd.`filter_group_id`) WHERE fg.`filter_group_id` = '" . (int)$filter_group_id . "' AND fgd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getGroups(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "filter_group` fg LEFT JOIN `" . DB_PREFIX . "filter_group_description` fgd ON (fg.`filter_group_id` = fgd.`filter_group_id`) WHERE fgd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"; + + $sort_data = [ + 'fgd.name', + 'fg.sort_order' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY fgd.`name`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param int $filter_group_id + * + * @return array + */ + public function getGroupDescriptions(int $filter_group_id): array { + $filter_group_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "filter_group_description` WHERE `filter_group_id` = '" . (int)$filter_group_id . "'"); + + foreach ($query->rows as $result) { + $filter_group_data[$result['language_id']] = ['name' => $result['name']]; + } + + return $filter_group_data; + } + + /** + * @param int $filter_id + * + * @return array + */ + public function getFilter(int $filter_id): array { + $query = $this->db->query("SELECT *, (SELECT `name` FROM `" . DB_PREFIX . "filter_group_description` fgd WHERE f.`filter_group_id` = fgd.`filter_group_id` AND fgd.`language_id` = '" . (int)$this->config->get('config_language_id') . "') AS `group` FROM `" . DB_PREFIX . "filter` f LEFT JOIN `" . DB_PREFIX . "filter_description` fd ON (f.`filter_id` = fd.`filter_id`) WHERE f.`filter_id` = '" . (int)$filter_id . "' AND fd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getFilters(array $data): array { + $sql = "SELECT *, (SELECT name FROM `" . DB_PREFIX . "filter_group_description` fgd WHERE f.`filter_group_id` = fgd.`filter_group_id` AND fgd.`language_id` = '" . (int)$this->config->get('config_language_id') . "') AS `group` FROM `" . DB_PREFIX . "filter` f LEFT JOIN `" . DB_PREFIX . "filter_description` fd ON (f.`filter_id` = fd.`filter_id`) WHERE fd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"; + + if (!empty($data['filter_name'])) { + $sql .= " AND fd.`name` LIKE '" . $this->db->escape((string)$data['filter_name'] . '%') . "'"; + } + + $sql .= " ORDER BY f.`sort_order` ASC"; + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param int $filter_group_id + * + * @return array + */ + public function getDescriptions(int $filter_group_id): array { + $filter_data = []; + + $filter_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "filter` WHERE `filter_group_id` = '" . (int)$filter_group_id . "'"); + + foreach ($filter_query->rows as $filter) { + $filter_description_data = []; + + $filter_description_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "filter_description` WHERE `filter_id` = '" . (int)$filter['filter_id'] . "'"); + + foreach ($filter_description_query->rows as $filter_description) { + $filter_description_data[$filter_description['language_id']] = ['name' => $filter_description['name']]; + } + + $filter_data[] = [ + 'filter_id' => $filter['filter_id'], + 'filter_description' => $filter_description_data, + 'sort_order' => $filter['sort_order'] + ]; + } + + return $filter_data; + } + + /** + * @return int + */ + public function getTotalGroups(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "filter_group`"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/catalog/information.php b/admininistrator/model/catalog/information.php new file mode 100644 index 0000000..17d9200 --- /dev/null +++ b/admininistrator/model/catalog/information.php @@ -0,0 +1,262 @@ +db->query("INSERT INTO `" . DB_PREFIX . "information` SET `sort_order` = '" . (int)$data['sort_order'] . "', `bottom` = '" . (isset($data['bottom']) ? (int)$data['bottom'] : 0) . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "'"); + + $information_id = $this->db->getLastId(); + + foreach ($data['information_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "information_description` SET `information_id` = '" . (int)$information_id . "', `language_id` = '" . (int)$language_id . "', `title` = '" . $this->db->escape($value['title']) . "', `description` = '" . $this->db->escape($value['description']) . "', `meta_title` = '" . $this->db->escape($value['meta_title']) . "', `meta_description` = '" . $this->db->escape($value['meta_description']) . "', `meta_keyword` = '" . $this->db->escape($value['meta_keyword']) . "'"); + } + + if (isset($data['information_store'])) { + foreach ($data['information_store'] as $store_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "information_to_store` SET `information_id` = '" . (int)$information_id . "', `store_id` = '" . (int)$store_id . "'"); + } + } + + // SEO URL + if (isset($data['information_seo_url'])) { + foreach ($data['information_seo_url'] as $store_id => $language) { + foreach ($language as $language_id => $keyword) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "seo_url` SET `store_id` = '" . (int)$store_id . "', `language_id` = '" . (int)$language_id . "', `key` = 'information_id', `value` = '" . (int)$information_id . "', `keyword` = '" . $this->db->escape($keyword) . "'"); + } + } + } + + if (isset($data['information_layout'])) { + foreach ($data['information_layout'] as $store_id => $layout_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "information_to_layout` SET `information_id` = '" . (int)$information_id . "', `store_id` = '" . (int)$store_id . "', `layout_id` = '" . (int)$layout_id . "'"); + } + } + + $this->cache->delete('information'); + + return $information_id; + } + + /** + * @param int $information_id + * @param array $data + * + * @return void + */ + public function editInformation(int $information_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "information` SET `sort_order` = '" . (int)$data['sort_order'] . "', `bottom` = '" . (isset($data['bottom']) ? (int)$data['bottom'] : 0) . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "' WHERE `information_id` = '" . (int)$information_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "information_description` WHERE `information_id` = '" . (int)$information_id . "'"); + + foreach ($data['information_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "information_description` SET `information_id` = '" . (int)$information_id . "', `language_id` = '" . (int)$language_id . "', `title` = '" . $this->db->escape($value['title']) . "', `description` = '" . $this->db->escape($value['description']) . "', `meta_title` = '" . $this->db->escape($value['meta_title']) . "', `meta_description` = '" . $this->db->escape($value['meta_description']) . "', `meta_keyword` = '" . $this->db->escape($value['meta_keyword']) . "'"); + } + + $this->db->query("DELETE FROM `" . DB_PREFIX . "information_to_store` WHERE `information_id` = '" . (int)$information_id . "'"); + + if (isset($data['information_store'])) { + foreach ($data['information_store'] as $store_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "information_to_store` SET `information_id` = '" . (int)$information_id . "', `store_id` = '" . (int)$store_id . "'"); + } + } + + $this->db->query("DELETE FROM `" . DB_PREFIX . "seo_url` WHERE `key` = 'information_id' AND `value` = '" . (int)$information_id . "'"); + + if (isset($data['information_seo_url'])) { + foreach ($data['information_seo_url'] as $store_id => $language) { + foreach ($language as $language_id => $keyword) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "seo_url` SET `store_id` = '" . (int)$store_id . "', `language_id` = '" . (int)$language_id . "', `key` = 'information_id', `value` = '" . (int)$information_id . "', `keyword` = '" . $this->db->escape($keyword) . "'"); + } + } + } + + $this->db->query("DELETE FROM `" . DB_PREFIX . "information_to_layout` WHERE `information_id` = '" . (int)$information_id . "'"); + + if (isset($data['information_layout'])) { + foreach ($data['information_layout'] as $store_id => $layout_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "information_to_layout` SET `information_id` = '" . (int)$information_id . "', `store_id` = '" . (int)$store_id . "', `layout_id` = '" . (int)$layout_id . "'"); + } + } + + $this->cache->delete('information'); + } + + /** + * @param int $information_id + * + * @return void + */ + public function deleteInformation(int $information_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "information` WHERE `information_id` = '" . (int)$information_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "information_description` WHERE `information_id` = '" . (int)$information_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "information_to_store` WHERE `information_id` = '" . (int)$information_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "information_to_layout` WHERE `information_id` = '" . (int)$information_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "seo_url` WHERE `key` = 'information_id' AND `value` = '" . (int)$information_id . "'"); + + $this->cache->delete('information'); + } + + /** + * @param int $information_id + * + * @return array + */ + public function getInformation(int $information_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "information` WHERE `information_id` = '" . (int)$information_id . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getInformations(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "information` i LEFT JOIN `" . DB_PREFIX . "information_description` id ON (i.`information_id` = id.`information_id`) WHERE id.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"; + + $sort_data = [ + 'id.title', + 'i.sort_order' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY id.`title`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $information_data = $this->cache->get('information.' . md5($sql)); + + if (!$information_data) { + $query = $this->db->query($sql); + + $information_data = $query->rows; + + $this->cache->set('information.' . md5($sql), $information_data); + } + + return $information_data; + } + + /** + * @param int $information_id + * + * @return array + */ + public function getDescriptions(int $information_id): array { + $information_description_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "information_description` WHERE `information_id` = '" . (int)$information_id . "'"); + + foreach ($query->rows as $result) { + $information_description_data[$result['language_id']] = [ + 'title' => $result['title'], + 'description' => $result['description'], + 'meta_title' => $result['meta_title'], + 'meta_description' => $result['meta_description'], + 'meta_keyword' => $result['meta_keyword'] + ]; + } + + return $information_description_data; + } + + /** + * @param int $information_id + * + * @return array + */ + public function getStores(int $information_id): array { + $information_store_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "information_to_store` WHERE `information_id` = '" . (int)$information_id . "'"); + + foreach ($query->rows as $result) { + $information_store_data[] = $result['store_id']; + } + + return $information_store_data; + } + + /** + * @param int $information_id + * + * @return array + */ + public function getSeoUrls(int $information_id): array { + $information_seo_url_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "seo_url` WHERE `key` = 'information_id' AND `value` = '" . (int)$information_id . "'"); + + foreach ($query->rows as $result) { + $information_seo_url_data[$result['store_id']][$result['language_id']] = $result['keyword']; + } + + return $information_seo_url_data; + } + + /** + * @param int $information_id + * + * @return array + */ + public function getLayouts(int $information_id): array { + $information_layout_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "information_to_layout` WHERE `information_id` = '" . (int)$information_id . "'"); + + foreach ($query->rows as $result) { + $information_layout_data[$result['store_id']] = $result['layout_id']; + } + + return $information_layout_data; + } + + /** + * @return int + */ + public function getTotalInformations(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "information`"); + + return (int)$query->row['total']; + } + + /** + * @param int $layout_id + * + * @return int + */ + public function getTotalInformationsByLayoutId(int $layout_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "information_to_layout` WHERE `layout_id` = '" . (int)$layout_id . "'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/catalog/manufacturer.php b/admininistrator/model/catalog/manufacturer.php new file mode 100644 index 0000000..6a58256 --- /dev/null +++ b/admininistrator/model/catalog/manufacturer.php @@ -0,0 +1,224 @@ +db->query("INSERT INTO `" . DB_PREFIX . "manufacturer` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `image` = '" . $this->db->escape((string)$data['image']) . "', `sort_order` = '" . (int)$data['sort_order'] . "'"); + + $manufacturer_id = $this->db->getLastId(); + + if (isset($data['manufacturer_store'])) { + foreach ($data['manufacturer_store'] as $store_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "manufacturer_to_store` SET `manufacturer_id` = '" . (int)$manufacturer_id . "', `store_id` = '" . (int)$store_id . "'"); + } + } + + // SEO URL + if (isset($data['manufacturer_seo_url'])) { + foreach ($data['manufacturer_seo_url'] as $store_id => $language) { + foreach ($language as $language_id => $keyword) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "seo_url` SET `store_id` = '" . (int)$store_id . "', `language_id` = '" . (int)$language_id . "', `key` = 'manufacturer_id', `value` = '" . (int)$manufacturer_id . "', `keyword` = '" . $this->db->escape($keyword) . "'"); + } + } + } + + if (isset($data['manufacturer_layout'])) { + foreach ($data['manufacturer_layout'] as $store_id => $layout_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "manufacturer_to_layout` SET `manufacturer_id` = '" . (int)$manufacturer_id . "', `store_id` = '" . (int)$store_id . "', `layout_id` = '" . (int)$layout_id . "'"); + } + } + + $this->cache->delete('manufacturer'); + + return $manufacturer_id; + } + + /** + * @param int $manufacturer_id + * @param array $data + * + * @return void + */ + public function editManufacturer(int $manufacturer_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "manufacturer` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `image` = '" . $this->db->escape((string)$data['image']) . "', `sort_order` = '" . (int)$data['sort_order'] . "' WHERE `manufacturer_id` = '" . (int)$manufacturer_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "manufacturer_to_store` WHERE `manufacturer_id` = '" . (int)$manufacturer_id . "'"); + + if (isset($data['manufacturer_store'])) { + foreach ($data['manufacturer_store'] as $store_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "manufacturer_to_store` SET `manufacturer_id` = '" . (int)$manufacturer_id . "', `store_id` = '" . (int)$store_id . "'"); + } + } + + $this->db->query("DELETE FROM `" . DB_PREFIX . "seo_url` WHERE `key` = 'manufacturer_id' AND `value` = '" . (int)$manufacturer_id . "'"); + + if (isset($data['manufacturer_seo_url'])) { + foreach ($data['manufacturer_seo_url'] as $store_id => $language) { + foreach ($language as $language_id => $keyword) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "seo_url` SET `store_id` = '" . (int)$store_id . "', `language_id` = '" . (int)$language_id . "', `key` = 'manufacturer_id', `value` = '" . (int)$manufacturer_id . "', `keyword` = '" . $this->db->escape($keyword) . "'"); + } + } + } + + $this->db->query("DELETE FROM `" . DB_PREFIX . "manufacturer_to_layout` WHERE `manufacturer_id` = '" . (int)$manufacturer_id . "'"); + + if (isset($data['manufacturer_layout'])) { + foreach ($data['manufacturer_layout'] as $store_id => $layout_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "manufacturer_to_layout` SET `manufacturer_id` = '" . (int)$manufacturer_id . "', `store_id` = '" . (int)$store_id . "', `layout_id` = '" . (int)$layout_id . "'"); + } + } + + $this->cache->delete('manufacturer'); + } + + /** + * @param int $manufacturer_id + * + * @return void + */ + public function deleteManufacturer(int $manufacturer_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "manufacturer` WHERE `manufacturer_id` = '" . (int)$manufacturer_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "manufacturer_to_store` WHERE `manufacturer_id` = '" . (int)$manufacturer_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "manufacturer_to_layout` WHERE `manufacturer_id` = '" . (int)$manufacturer_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "seo_url` WHERE `key` = 'manufacturer_id' AND `value` = '" . (int)$manufacturer_id . "'"); + + $this->cache->delete('manufacturer'); + } + + /** + * @param int $manufacturer_id + * + * @return array + */ + public function getManufacturer(int $manufacturer_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "manufacturer` WHERE `manufacturer_id` = '" . (int)$manufacturer_id . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getManufacturers(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "manufacturer`"; + + if (!empty($data['filter_name'])) { + $sql .= " WHERE `name` LIKE '" . $this->db->escape((string)$data['filter_name'] . '%') . "'"; + } + + $sort_data = [ + 'name', + 'sort_order' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `name`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param int $manufacturer_id + * + * @return array + */ + public function getStores(int $manufacturer_id): array { + $manufacturer_store_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "manufacturer_to_store` WHERE `manufacturer_id` = '" . (int)$manufacturer_id . "'"); + + foreach ($query->rows as $result) { + $manufacturer_store_data[] = $result['store_id']; + } + + return $manufacturer_store_data; + } + + /** + * @param int $manufacturer_id + * + * @return array + */ + public function getSeoUrls(int $manufacturer_id): array { + $manufacturer_seo_url_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "seo_url` WHERE `key` = 'manufacturer_id' AND `value` = '" . (int)$manufacturer_id . "'"); + + foreach ($query->rows as $result) { + $manufacturer_seo_url_data[$result['store_id']][$result['language_id']] = $result['keyword']; + } + + return $manufacturer_seo_url_data; + } + + /** + * @param int $manufacturer_id + * + * @return array + */ + public function getLayouts(int $manufacturer_id): array { + $manufacturer_layout_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "manufacturer_to_layout` WHERE `manufacturer_id` = '" . (int)$manufacturer_id . "'"); + + foreach ($query->rows as $result) { + $manufacturer_layout_data[$result['store_id']] = $result['layout_id']; + } + + return $manufacturer_layout_data; + } + + /** + * @return int + */ + public function getTotalManufacturers(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "manufacturer`"); + + return (int)$query->row['total']; + } + + /** + * @param int $layout_id + * + * @return int + */ + public function getTotalManufacturersByLayoutId(int $layout_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "manufacturer_to_layout` WHERE `layout_id` = '" . (int)$layout_id . "'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/catalog/option.php b/admininistrator/model/catalog/option.php new file mode 100644 index 0000000..7916a3b --- /dev/null +++ b/admininistrator/model/catalog/option.php @@ -0,0 +1,231 @@ +db->query("INSERT INTO `" . DB_PREFIX . "option` SET `type` = '" . $this->db->escape((string)$data['type']) . "', `sort_order` = '" . (int)$data['sort_order'] . "'"); + + $option_id = $this->db->getLastId(); + + foreach ($data['option_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "option_description` SET `option_id` = '" . (int)$option_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } + + if (isset($data['option_value'])) { + foreach ($data['option_value'] as $option_value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "option_value` SET `option_id` = '" . (int)$option_id . "', `image` = '" . $this->db->escape(html_entity_decode($option_value['image'], ENT_QUOTES, 'UTF-8')) . "', `sort_order` = '" . (int)$option_value['sort_order'] . "'"); + + $option_value_id = $this->db->getLastId(); + + foreach ($option_value['option_value_description'] as $language_id => $option_value_description) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "option_value_description` SET `option_value_id` = '" . (int)$option_value_id . "', `language_id` = '" . (int)$language_id . "', `option_id` = '" . (int)$option_id . "', `name` = '" . $this->db->escape($option_value_description['name']) . "'"); + } + } + } + + return $option_id; + } + + /** + * @param int $option_id + * @param array $data + * + * @return void + */ + public function editOption(int $option_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "option` SET `type` = '" . $this->db->escape((string)$data['type']) . "', `sort_order` = '" . (int)$data['sort_order'] . "' WHERE `option_id` = '" . (int)$option_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "option_description` WHERE `option_id` = '" . (int)$option_id . "'"); + + foreach ($data['option_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "option_description` SET `option_id` = '" . (int)$option_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } + + $this->db->query("DELETE FROM `" . DB_PREFIX . "option_value` WHERE `option_id` = '" . (int)$option_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "option_value_description` WHERE `option_id` = '" . (int)$option_id . "'"); + + if (isset($data['option_value'])) { + foreach ($data['option_value'] as $option_value) { + if ($option_value['option_value_id']) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "option_value` SET `option_value_id` = '" . (int)$option_value['option_value_id'] . "', `option_id` = '" . (int)$option_id . "', `image` = '" . $this->db->escape(html_entity_decode($option_value['image'], ENT_QUOTES, 'UTF-8')) . "', `sort_order` = '" . (int)$option_value['sort_order'] . "'"); + } else { + $this->db->query("INSERT INTO `" . DB_PREFIX . "option_value` SET `option_id` = '" . (int)$option_id . "', `image` = '" . $this->db->escape(html_entity_decode($option_value['image'], ENT_QUOTES, 'UTF-8')) . "', `sort_order` = '" . (int)$option_value['sort_order'] . "'"); + } + + $option_value_id = $this->db->getLastId(); + + foreach ($option_value['option_value_description'] as $language_id => $option_value_description) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "option_value_description` SET `option_value_id` = '" . (int)$option_value_id . "', `language_id` = '" . (int)$language_id . "', `option_id` = '" . (int)$option_id . "', `name` = '" . $this->db->escape($option_value_description['name']) . "'"); + } + } + } + } + + /** + * @param int $option_id + * + * @return void + */ + public function deleteOption(int $option_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "option` WHERE `option_id` = '" . (int)$option_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "option_description` WHERE `option_id` = '" . (int)$option_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "option_value` WHERE `option_id` = '" . (int)$option_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "option_value_description` WHERE `option_id` = '" . (int)$option_id . "'"); + } + + /** + * @param int $option_id + * + * @return array + */ + public function getOption(int $option_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "option` o LEFT JOIN `" . DB_PREFIX . "option_description` od ON (o.`option_id` = od.`option_id`) WHERE o.`option_id` = '" . (int)$option_id . "' AND od.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getOptions(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "option` o LEFT JOIN `" . DB_PREFIX . "option_description` od ON (o.`option_id` = od.`option_id`) WHERE od.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"; + + if (!empty($data['filter_name'])) { + $sql .= " AND od.`name` LIKE '" . $this->db->escape((string)$data['filter_name'] . '%') . "'"; + } + + $sort_data = [ + 'od.name', + 'o.type', + 'o.sort_order' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `od`.`name`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param int $option_id + * + * @return array + */ + public function getDescriptions(int $option_id): array { + $option_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "option_description` WHERE `option_id` = '" . (int)$option_id . "'"); + + foreach ($query->rows as $result) { + $option_data[$result['language_id']] = ['name' => $result['name']]; + } + + return $option_data; + } + + /** + * @param int $option_value_id + * + * @return array + */ + public function getValue(int $option_value_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "option_value` ov LEFT JOIN `" . DB_PREFIX . "option_value_description` ovd ON (ov.`option_value_id` = ovd.`option_value_id`) WHERE ov.`option_value_id` = '" . (int)$option_value_id . "' AND ovd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return $query->row; + } + + /** + * @param int $option_id + * + * @return array + */ + public function getValues(int $option_id): array { + $option_value_data = []; + + $option_value_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "option_value` ov LEFT JOIN `" . DB_PREFIX . "option_value_description` ovd ON (ov.`option_value_id` = ovd.`option_value_id`) WHERE ov.`option_id` = '" . (int)$option_id . "' AND ovd.`language_id` = '" . (int)$this->config->get('config_language_id') . "' ORDER BY ov.`sort_order`, ovd.`name`"); + + foreach ($option_value_query->rows as $option_value) { + $option_value_data[] = [ + 'option_value_id' => $option_value['option_value_id'], + 'name' => $option_value['name'], + 'image' => $option_value['image'], + 'sort_order' => $option_value['sort_order'] + ]; + } + + return $option_value_data; + } + + /** + * @param int $option_id + * + * @return array + */ + public function getValueDescriptions(int $option_id): array { + $option_value_data = []; + + $option_value_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "option_value` WHERE `option_id` = '" . (int)$option_id . "' ORDER BY `sort_order`"); + + foreach ($option_value_query->rows as $option_value) { + $option_value_description_data = []; + + $option_value_description_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "option_value_description` WHERE `option_value_id` = '" . (int)$option_value['option_value_id'] . "'"); + + foreach ($option_value_description_query->rows as $option_value_description) { + $option_value_description_data[$option_value_description['language_id']] = ['name' => $option_value_description['name']]; + } + + $option_value_data[] = [ + 'option_value_id' => $option_value['option_value_id'], + 'option_value_description' => $option_value_description_data, + 'image' => $option_value['image'], + 'sort_order' => $option_value['sort_order'] + ]; + } + + return $option_value_data; + } + + /** + * @return int + */ + public function getTotalOptions(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "option`"); + + return (int)$query->row['total']; + } +} \ No newline at end of file diff --git a/admininistrator/model/catalog/product.php b/admininistrator/model/catalog/product.php new file mode 100644 index 0000000..273bad8 --- /dev/null +++ b/admininistrator/model/catalog/product.php @@ -0,0 +1,1407 @@ +db->query("INSERT INTO `" . DB_PREFIX . "product` SET `master_id` = '" . (int)$data['master_id'] . "', `model` = '" . $this->db->escape((string)$data['model']) . "', `sku` = '" . $this->db->escape((string)$data['sku']) . "', `upc` = '" . $this->db->escape((string)$data['upc']) . "', `ean` = '" . $this->db->escape((string)$data['ean']) . "', `jan` = '" . $this->db->escape((string)$data['jan']) . "', `isbn` = '" . $this->db->escape((string)$data['isbn']) . "', `mpn` = '" . $this->db->escape((string)$data['mpn']) . "', `location` = '" . $this->db->escape((string)$data['location']) . "', `variant` = '" . $this->db->escape(!empty($data['variant']) ? json_encode($data['variant']) : '') . "', `override` = '" . $this->db->escape(!empty($data['override']) ? json_encode($data['override']) : '') . "', `quantity` = '" . (int)$data['quantity'] . "', `minimum` = '" . (int)$data['minimum'] . "', `subtract` = '" . (isset($data['subtract']) ? (bool)$data['subtract'] : 0) . "', `stock_status_id` = '" . (int)$data['stock_status_id'] . "', `date_available` = '" . $this->db->escape((string)$data['date_available']) . "', `manufacturer_id` = '" . (int)$data['manufacturer_id'] . "', `shipping` = '" . (isset($data['shipping']) ? (bool)$data['shipping'] : 0) . "', `price` = '" . (float)$data['price'] . "', `points` = '" . (int)$data['points'] . "', `weight` = '" . (float)$data['weight'] . "', `weight_class_id` = '" . (int)$data['weight_class_id'] . "', `length` = '" . (float)$data['length'] . "', `width` = '" . (float)$data['width'] . "', `height` = '" . (float)$data['height'] . "', `length_class_id` = '" . (int)$data['length_class_id'] . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "', `tax_class_id` = '" . (int)$data['tax_class_id'] . "', `sort_order` = '" . (int)$data['sort_order'] . "', `date_added` = NOW(), `date_modified` = NOW()"); + + $product_id = $this->db->getLastId(); + + if ($data['image']) { + $this->db->query("UPDATE `" . DB_PREFIX . "product` SET `image` = '" . $this->db->escape((string)$data['image']) . "' WHERE `product_id` = '" . (int)$product_id . "'"); + } + + // Description + foreach ($data['product_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_description` SET `product_id` = '" . (int)$product_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "', `description` = '" . $this->db->escape($value['description']) . "', `tag` = '" . $this->db->escape($value['tag']) . "', `meta_title` = '" . $this->db->escape($value['meta_title']) . "', `meta_description` = '" . $this->db->escape($value['meta_description']) . "', `meta_keyword` = '" . $this->db->escape($value['meta_keyword']) . "'"); + } + + // Categories + if (isset($data['product_category'])) { + foreach ($data['product_category'] as $category_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_to_category` SET `product_id` = '" . (int)$product_id . "', `category_id` = '" . (int)$category_id . "'"); + } + } + + // Filters + if (isset($data['product_filter'])) { + foreach ($data['product_filter'] as $filter_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_filter` SET `product_id` = '" . (int)$product_id . "', `filter_id` = '" . (int)$filter_id . "'"); + } + } + + // Stores + if (isset($data['product_store'])) { + foreach ($data['product_store'] as $store_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_to_store` SET `product_id` = '" . (int)$product_id . "', `store_id` = '" . (int)$store_id . "'"); + } + } + + // Downloads + if (isset($data['product_download'])) { + foreach ($data['product_download'] as $download_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_to_download` SET `product_id` = '" . (int)$product_id . "', `download_id` = '" . (int)$download_id . "'"); + } + } + + // Related + if (isset($data['product_related'])) { + foreach ($data['product_related'] as $related_id) { + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_related` WHERE `product_id` = '" . (int)$product_id . "' AND `related_id` = '" . (int)$related_id . "'"); + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_related` SET `product_id` = '" . (int)$product_id . "', `related_id` = '" . (int)$related_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_related` WHERE `product_id` = '" . (int)$related_id . "' AND `related_id` = '" . (int)$product_id . "'"); + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_related` SET `product_id` = '" . (int)$related_id . "', `related_id` = '" . (int)$product_id . "'"); + } + } + + // Attributes + if (isset($data['product_attribute'])) { + foreach ($data['product_attribute'] as $product_attribute) { + if ($product_attribute['attribute_id']) { + // Removes duplicates + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_attribute` WHERE `product_id` = '" . (int)$product_id . "' AND `attribute_id` = '" . (int)$product_attribute['attribute_id'] . "'"); + + foreach ($product_attribute['product_attribute_description'] as $language_id => $product_attribute_description) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_attribute` SET `product_id` = '" . (int)$product_id . "', `attribute_id` = '" . (int)$product_attribute['attribute_id'] . "', `language_id` = '" . (int)$language_id . "', `text` = '" . $this->db->escape($product_attribute_description['text']) . "'"); + } + } + } + } + + // Options + if (isset($data['product_option'])) { + foreach ($data['product_option'] as $product_option) { + if ($product_option['type'] == 'select' || $product_option['type'] == 'radio' || $product_option['type'] == 'checkbox' || $product_option['type'] == 'image') { + if (isset($product_option['product_option_value'])) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_option` SET `product_id` = '" . (int)$product_id . "', `option_id` = '" . (int)$product_option['option_id'] . "', `required` = '" . (int)$product_option['required'] . "'"); + + $product_option_id = $this->db->getLastId(); + + foreach ($product_option['product_option_value'] as $product_option_value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_option_value` SET `product_option_id` = '" . (int)$product_option_id . "', `product_id` = '" . (int)$product_id . "', `option_id` = '" . (int)$product_option['option_id'] . "', `option_value_id` = '" . (int)$product_option_value['option_value_id'] . "', `quantity` = '" . (int)$product_option_value['quantity'] . "', `subtract` = '" . (int)$product_option_value['subtract'] . "', `price` = '" . (float)$product_option_value['price'] . "', `price_prefix` = '" . $this->db->escape($product_option_value['price_prefix']) . "', `points` = '" . (int)$product_option_value['points'] . "', `points_prefix` = '" . $this->db->escape($product_option_value['points_prefix']) . "', `weight` = '" . (float)$product_option_value['weight'] . "', `weight_prefix` = '" . $this->db->escape($product_option_value['weight_prefix']) . "'"); + } + } + } else { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_option` SET `product_id` = '" . (int)$product_id . "', `option_id` = '" . (int)$product_option['option_id'] . "', `value` = '" . $this->db->escape($product_option['value']) . "', `required` = '" . (int)$product_option['required'] . "'"); + } + } + } + + // Subscription + if (isset($data['product_subscription'])) { + foreach ($data['product_subscription'] as $product_subscription) { + $query = $this->db->query("SELECT `product_id` FROM `" . DB_PREFIX . "product_subscription` WHERE `product_id` = '" . (int)$product_id . "' AND `customer_group_id` = '" . (int)$product_subscription['customer_group_id'] . "' AND `subscription_plan_id` = '" . (int)$product_subscription['subscription_plan_id'] . "'"); + + if (!$query->num_rows) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_subscription` SET `product_id` = '" . (int)$product_id . "', `customer_group_id` = '" . (int)$product_subscription['customer_group_id'] . "', `subscription_plan_id` = '" . (int)$product_subscription['subscription_plan_id'] . "', `trial_price` = '" . (float)$product_subscription['trial_price'] . "', `price` = '" . (float)$product_subscription['price'] . "'"); + } + } + } + + // Discounts + if (isset($data['product_discount'])) { + foreach ($data['product_discount'] as $product_discount) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_discount` SET `product_id` = '" . (int)$product_id . "', `customer_group_id` = '" . (int)$product_discount['customer_group_id'] . "', `quantity` = '" . (int)$product_discount['quantity'] . "', `priority` = '" . (int)$product_discount['priority'] . "', `price` = '" . (float)$product_discount['price'] . "', `date_start` = '" . $this->db->escape($product_discount['date_start']) . "', `date_end` = '" . $this->db->escape($product_discount['date_end']) . "'"); + } + } + + // Specials + if (isset($data['product_special'])) { + foreach ($data['product_special'] as $product_special) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_special` SET `product_id` = '" . (int)$product_id . "', `customer_group_id` = '" . (int)$product_special['customer_group_id'] . "', `priority` = '" . (int)$product_special['priority'] . "', `price` = '" . (float)$product_special['price'] . "', `date_start` = '" . $this->db->escape($product_special['date_start']) . "', `date_end` = '" . $this->db->escape($product_special['date_end']) . "'"); + } + } + + // Images + if (isset($data['product_image'])) { + foreach ($data['product_image'] as $product_image) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_image` SET `product_id` = '" . (int)$product_id . "', `image` = '" . $this->db->escape($product_image['image']) . "', `sort_order` = '" . (int)$product_image['sort_order'] . "'"); + } + } + + // Reward + if (isset($data['product_reward'])) { + foreach ($data['product_reward'] as $customer_group_id => $product_reward) { + if ((int)$product_reward['points'] > 0) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_reward` SET `product_id` = '" . (int)$product_id . "', `customer_group_id` = '" . (int)$customer_group_id . "', `points` = '" . (int)$product_reward['points'] . "'"); + } + } + } + + // SEO URL + if (isset($data['product_seo_url'])) { + foreach ($data['product_seo_url'] as $store_id => $language) { + foreach ($language as $language_id => $keyword) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "seo_url` SET `store_id` = '" . (int)$store_id . "', `language_id` = '" . (int)$language_id . "', `key` = 'product_id', `value` = '" . (int)$product_id . "', `keyword` = '" . $this->db->escape($keyword) . "'"); + } + } + } + + // Layout + if (isset($data['product_layout'])) { + foreach ($data['product_layout'] as $store_id => $layout_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_to_layout` SET `product_id` = '" . (int)$product_id . "', `store_id` = '" . (int)$store_id . "', `layout_id` = '" . (int)$layout_id . "'"); + } + } + + $this->cache->delete('product'); + + return $product_id; + } + + /** + * @param int $product_id + * @param array $data + * + * @return void + */ + public function editProduct(int $product_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "product` SET `model` = '" . $this->db->escape((string)$data['model']) . "', `sku` = '" . $this->db->escape((string)$data['sku']) . "', `upc` = '" . $this->db->escape((string)$data['upc']) . "', `ean` = '" . $this->db->escape((string)$data['ean']) . "', `jan` = '" . $this->db->escape((string)$data['jan']) . "', `isbn` = '" . $this->db->escape((string)$data['isbn']) . "', `mpn` = '" . $this->db->escape((string)$data['mpn']) . "', `location` = '" . $this->db->escape((string)$data['location']) . "', `variant` = '" . $this->db->escape(!empty($data['variant']) ? json_encode($data['variant']) : '') . "', `override` = '" . $this->db->escape(!empty($data['override']) ? json_encode($data['override']) : '') . "', `quantity` = '" . (int)$data['quantity'] . "', `minimum` = '" . (int)$data['minimum'] . "', `subtract` = '" . (isset($data['subtract']) ? (bool)$data['subtract'] : 0) . "', `stock_status_id` = '" . (int)$data['stock_status_id'] . "', `date_available` = '" . $this->db->escape((string)$data['date_available']) . "', `manufacturer_id` = '" . (int)$data['manufacturer_id'] . "', `shipping` = '" . (isset($data['shipping']) ? (bool)$data['shipping'] : 0) . "', `price` = '" . (float)$data['price'] . "', `points` = '" . (int)$data['points'] . "', `weight` = '" . (float)$data['weight'] . "', `weight_class_id` = '" . (int)$data['weight_class_id'] . "', `length` = '" . (float)$data['length'] . "', `width` = '" . (float)$data['width'] . "', `height` = '" . (float)$data['height'] . "', `length_class_id` = '" . (int)$data['length_class_id'] . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "', `tax_class_id` = '" . (int)$data['tax_class_id'] . "', `sort_order` = '" . (int)$data['sort_order'] . "', `date_modified` = NOW() WHERE `product_id` = '" . (int)$product_id . "'"); + + if ($data['image']) { + $this->db->query("UPDATE `" . DB_PREFIX . "product` SET `image` = '" . $this->db->escape((string)$data['image']) . "' WHERE `product_id` = '" . (int)$product_id . "'"); + } + + // Description + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_description` WHERE `product_id` = '" . (int)$product_id . "'"); + + foreach ($data['product_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_description` SET `product_id` = '" . (int)$product_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "', `description` = '" . $this->db->escape($value['description']) . "', `tag` = '" . $this->db->escape($value['tag']) . "', `meta_title` = '" . $this->db->escape($value['meta_title']) . "', `meta_description` = '" . $this->db->escape($value['meta_description']) . "', `meta_keyword` = '" . $this->db->escape($value['meta_keyword']) . "'"); + } + + // Categories + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_to_category` WHERE `product_id` = '" . (int)$product_id . "'"); + + if (isset($data['product_category'])) { + foreach ($data['product_category'] as $category_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_to_category` SET `product_id` = '" . (int)$product_id . "', `category_id` = '" . (int)$category_id . "'"); + } + } + + // Filters + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_filter` WHERE `product_id` = '" . (int)$product_id . "'"); + + if (isset($data['product_filter'])) { + foreach ($data['product_filter'] as $filter_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_filter` SET `product_id` = '" . (int)$product_id . "', `filter_id` = '" . (int)$filter_id . "'"); + } + } + + // Stores + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_to_store` WHERE `product_id` = '" . (int)$product_id . "'"); + + if (isset($data['product_store'])) { + foreach ($data['product_store'] as $store_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_to_store` SET `product_id` = '" . (int)$product_id . "', `store_id` = '" . (int)$store_id . "'"); + } + } + + // Downloads + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_to_download` WHERE `product_id` = '" . (int)$product_id . "'"); + + if (isset($data['product_download'])) { + foreach ($data['product_download'] as $download_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_to_download` SET `product_id` = '" . (int)$product_id . "', `download_id` = '" . (int)$download_id . "'"); + } + } + + // Related + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_related` WHERE `product_id` = '" . (int)$product_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_related` WHERE `related_id` = '" . (int)$product_id . "'"); + + if (isset($data['product_related'])) { + foreach ($data['product_related'] as $related_id) { + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_related` WHERE `product_id` = '" . (int)$product_id . "' AND `related_id` = '" . (int)$related_id . "'"); + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_related` SET `product_id` = '" . (int)$product_id . "', `related_id` = '" . (int)$related_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_related` WHERE `product_id` = '" . (int)$related_id . "' AND `related_id` = '" . (int)$product_id . "'"); + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_related` SET `product_id` = '" . (int)$related_id . "', `related_id` = '" . (int)$product_id . "'"); + } + } + + // Attributes + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_attribute` WHERE `product_id` = '" . (int)$product_id . "'"); + + if (!empty($data['product_attribute'])) { + foreach ($data['product_attribute'] as $product_attribute) { + if ($product_attribute['attribute_id']) { + // Removes duplicates + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_attribute` WHERE `product_id` = '" . (int)$product_id . "' AND `attribute_id` = '" . (int)$product_attribute['attribute_id'] . "'"); + + foreach ($product_attribute['product_attribute_description'] as $language_id => $product_attribute_description) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_attribute` SET `product_id` = '" . (int)$product_id . "', `attribute_id` = '" . (int)$product_attribute['attribute_id'] . "', `language_id` = '" . (int)$language_id . "', `text` = '" . $this->db->escape($product_attribute_description['text']) . "'"); + } + } + } + } + + // Options + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_option` WHERE `product_id` = '" . (int)$product_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_option_value` WHERE `product_id` = '" . (int)$product_id . "'"); + + if (isset($data['product_option'])) { + foreach ($data['product_option'] as $product_option) { + if ($product_option['type'] == 'select' || $product_option['type'] == 'radio' || $product_option['type'] == 'checkbox' || $product_option['type'] == 'image') { + if (isset($product_option['product_option_value'])) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_option` SET `product_option_id` = '" . (int)$product_option['product_option_id'] . "', `product_id` = '" . (int)$product_id . "', `option_id` = '" . (int)$product_option['option_id'] . "', `required` = '" . (int)$product_option['required'] . "'"); + + $product_option_id = $this->db->getLastId(); + + foreach ($product_option['product_option_value'] as $product_option_value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_option_value` SET `product_option_value_id` = '" . (int)$product_option_value['product_option_value_id'] . "', `product_option_id` = '" . (int)$product_option_id . "', `product_id` = '" . (int)$product_id . "', `option_id` = '" . (int)$product_option['option_id'] . "', `option_value_id` = '" . (int)$product_option_value['option_value_id'] . "', `quantity` = '" . (int)$product_option_value['quantity'] . "', `subtract` = '" . (int)$product_option_value['subtract'] . "', `price` = '" . (float)$product_option_value['price'] . "', `price_prefix` = '" . $this->db->escape($product_option_value['price_prefix']) . "', `points` = '" . (int)$product_option_value['points'] . "', `points_prefix` = '" . $this->db->escape($product_option_value['points_prefix']) . "', `weight` = '" . (float)$product_option_value['weight'] . "', `weight_prefix` = '" . $this->db->escape($product_option_value['weight_prefix']) . "'"); + } + } + } else { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_option` SET `product_option_id` = '" . (int)$product_option['product_option_id'] . "', `product_id` = '" . (int)$product_id . "', `option_id` = '" . (int)$product_option['option_id'] . "', `value` = '" . $this->db->escape($product_option['value']) . "', `required` = '" . (int)$product_option['required'] . "'"); + } + } + } + + // Subscription + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_subscription` WHERE `product_id` = '" . (int)$product_id . "'"); + + if (isset($data['product_subscription'])) { + foreach ($data['product_subscription'] as $product_subscription) { + $query = $this->db->query("SELECT `product_id` FROM `" . DB_PREFIX . "product_subscription` WHERE `product_id` = '" . (int)$product_id . "' AND `customer_group_id` = '" . (int)$product_subscription['customer_group_id'] . "' AND `subscription_plan_id` = '" . (int)$product_subscription['subscription_plan_id'] . "'"); + + if (!$query->num_rows) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_subscription` SET `product_id` = '" . (int)$product_id . "', `customer_group_id` = '" . (int)$product_subscription['customer_group_id'] . "', `subscription_plan_id` = '" . (int)$product_subscription['subscription_plan_id'] . "', `trial_price` = '" . (float)$product_subscription['trial_price'] . "', `price` = '" . (float)$product_subscription['price'] . "'"); + } + } + } + + // Discounts + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_discount` WHERE `product_id` = '" . (int)$product_id . "'"); + + if (isset($data['product_discount'])) { + foreach ($data['product_discount'] as $product_discount) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_discount` SET `product_id` = '" . (int)$product_id . "', `customer_group_id` = '" . (int)$product_discount['customer_group_id'] . "', `quantity` = '" . (int)$product_discount['quantity'] . "', `priority` = '" . (int)$product_discount['priority'] . "', `price` = '" . (float)$product_discount['price'] . "', `date_start` = '" . $this->db->escape($product_discount['date_start']) . "', `date_end` = '" . $this->db->escape($product_discount['date_end']) . "'"); + } + } + + // Specials + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_special` WHERE `product_id` = '" . (int)$product_id . "'"); + + if (isset($data['product_special'])) { + foreach ($data['product_special'] as $product_special) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_special` SET `product_id` = '" . (int)$product_id . "', `customer_group_id` = '" . (int)$product_special['customer_group_id'] . "', `priority` = '" . (int)$product_special['priority'] . "', `price` = '" . (float)$product_special['price'] . "', `date_start` = '" . $this->db->escape($product_special['date_start']) . "', `date_end` = '" . $this->db->escape($product_special['date_end']) . "'"); + } + } + + // Images + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_image` WHERE `product_id` = '" . (int)$product_id . "'"); + + if (isset($data['product_image'])) { + foreach ($data['product_image'] as $product_image) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_image` SET `product_id` = '" . (int)$product_id . "', `image` = '" . $this->db->escape($product_image['image']) . "', `sort_order` = '" . (int)$product_image['sort_order'] . "'"); + } + } + + // Rewards + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_reward` WHERE `product_id` = '" . (int)$product_id . "'"); + + if (isset($data['product_reward'])) { + foreach ($data['product_reward'] as $customer_group_id => $value) { + if ((int)$value['points'] > 0) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_reward` SET `product_id` = '" . (int)$product_id . "', `customer_group_id` = '" . (int)$customer_group_id . "', `points` = '" . (int)$value['points'] . "'"); + } + } + } + + // SEO URL + $this->db->query("DELETE FROM `" . DB_PREFIX . "seo_url` WHERE `key` = 'product_id' AND `value` = '" . (int)$product_id . "'"); + + if (isset($data['product_seo_url'])) { + foreach ($data['product_seo_url'] as $store_id => $language) { + foreach ($language as $language_id => $keyword) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "seo_url` SET `store_id` = '" . (int)$store_id . "', `language_id` = '" . (int)$language_id . "', `key` = 'product_id', `value` = '" . (int)$product_id . "', `keyword` = '" . $this->db->escape($keyword) . "'"); + } + } + } + + // Layout + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_to_layout` WHERE `product_id` = '" . (int)$product_id . "'"); + + if (isset($data['product_layout'])) { + foreach ($data['product_layout'] as $store_id => $layout_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_to_layout` SET `product_id` = '" . (int)$product_id . "', `store_id` = '" . (int)$store_id . "', `layout_id` = '" . (int)$layout_id . "'"); + } + } + + $this->cache->delete('product'); + } + + /** + * @param int $product_id + * + * @return void + */ + public function copyProduct(int $product_id): void { + $product_info = $this->model_catalog_product->getProduct($product_id); + + if ($product_info) { + $product_data = $product_info; + + $product_data['sku'] = ''; + $product_data['upc'] = ''; + $product_data['status'] = '0'; + + $product_data['variant'] = json_decode($product_info['variant'], true); + $product_data['override'] = json_decode($product_info['override'], true); + + $product_data['product_attribute'] = $this->model_catalog_product->getAttributes($product_id); + $product_data['product_category'] = $this->model_catalog_product->getCategories($product_id); + $product_data['product_description'] = $this->model_catalog_product->getDescriptions($product_id); + $product_data['product_discount'] = $this->model_catalog_product->getDiscounts($product_id); + $product_data['product_download'] = $this->model_catalog_product->getDownloads($product_id); + $product_data['product_filter'] = $this->model_catalog_product->getFilters($product_id); + $product_data['product_image'] = $this->model_catalog_product->getImages($product_id); + $product_data['product_layout'] = $this->model_catalog_product->getLayouts($product_id); + $product_data['product_option'] = $this->model_catalog_product->getOptions($product_id); + $product_data['product_subscription'] = $this->model_catalog_product->getSubscriptions($product_id); + $product_data['product_related'] = $this->model_catalog_product->getRelated($product_id); + $product_data['product_reward'] = $this->model_catalog_product->getRewards($product_id); + $product_data['product_special'] = $this->model_catalog_product->getSpecials($product_id); + $product_data['product_store'] = $this->model_catalog_product->getStores($product_id); + + $this->model_catalog_product->addProduct($product_data); + } + } + + /** + * @param int $product_id + * + * @return void + */ + public function deleteProduct(int $product_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "product` WHERE `product_id` = '" . (int)$product_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_attribute` WHERE `product_id` = '" . (int)$product_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_description` WHERE `product_id` = '" . (int)$product_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_discount` WHERE `product_id` = '" . (int)$product_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_filter` WHERE `product_id` = '" . (int)$product_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_image` WHERE `product_id` = '" . (int)$product_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_option` WHERE `product_id` = '" . (int)$product_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_option_value` WHERE `product_id` = '" . (int)$product_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_subscription` WHERE `product_id` = '" . (int)$product_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_related` WHERE `product_id` = '" . (int)$product_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_related` WHERE `related_id` = '" . (int)$product_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_report` WHERE `product_id` = '" . (int)$product_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_reward` WHERE `product_id` = '" . (int)$product_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_special` WHERE `product_id` = '" . (int)$product_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_to_category` WHERE `product_id` = '" . (int)$product_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_to_download` WHERE `product_id` = '" . (int)$product_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_to_layout` WHERE `product_id` = '" . (int)$product_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_to_store` WHERE `product_id` = '" . (int)$product_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "review` WHERE `product_id` = '" . (int)$product_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "seo_url` WHERE `key` = 'product_id' AND `value` = '" . (int)$product_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "coupon_product` WHERE `product_id` = '" . (int)$product_id . "'"); + + $this->db->query("UPDATE `" . DB_PREFIX . "product` SET `master_id` = '0' WHERE `master_id` = '" . (int)$product_id . "'"); + + $this->cache->delete('product'); + } + + /** + * @param int $master_id + * @param array $data + * + * @return int + */ + public function addVariant(int $master_id, array $data): int { + $product_data = []; + + // Use master values to override the values + $master_info = $this->model_catalog_product->getProduct($master_id); + + if ($master_info) { + // We use the override to override the master product values + if (isset($data['override'])) { + $override = (array)$data['override']; + } else { + $override = []; + } + + $ignore = [ + 'product_id', + 'master_id', + 'quantity', + 'override', + 'variant' + ]; + + foreach ($master_info as $key => $value) { + // So if key not in override or ignore list we replace with master value + if (!array_key_exists($key, $override) && !in_array($key, $ignore)) { + $product_data[$key] = $value; + } + } + + // Descriptions + $product_descriptions = $this->model_catalog_product->getDescriptions($master_id); + + foreach ($product_descriptions as $language_id => $product_description) { + foreach ($product_description as $key => $value) { + // If an override has been found, we use the POST data values + if (!isset($override['product_description'][$language_id][$key])) { + $product_data['product_description'][$language_id][$key] = $value; + } + } + } + + // Attributes + if (!isset($override['product_attribute'])) { + $product_data['product_attribute'] = $this->model_catalog_product->getAttributes($master_id); + } + + // Category + if (!isset($override['product_category'])) { + $product_data['product_category'] = $this->model_catalog_product->getCategories($master_id); + } + + // Discounts + if (!isset($override['product_discount'])) { + $product_data['product_discount'] = $this->model_catalog_product->getDiscounts($master_id); + } + + // Downloads + if (!isset($override['product_download'])) { + $product_data['product_download'] = $this->model_catalog_product->getDownloads($master_id); + } + + // Filters + if (!isset($override['product_filter'])) { + $product_data['product_filter'] = $this->model_catalog_product->getFilters($master_id); + } + + // Images + if (!isset($override['product_image'])) { + $product_data['product_image'] = $this->model_catalog_product->getImages($master_id); + } + + // Layouts + if (!isset($override['product_layout'])) { + $product_data['product_layout'] = $this->model_catalog_product->getLayouts($master_id); + } + + // Options + // product_option should not be used if variant product + + // Subscriptions + if (!isset($override['product_subscription'])) { + $product_data['product_subscription'] = $this->model_catalog_product->getSubscriptions($master_id); + } + + // Related + if (!isset($override['product_related'])) { + $product_data['product_related'] = $this->model_catalog_product->getRelated($master_id); + } + + // Rewards + if (!isset($override['product_reward'])) { + $product_data['product_reward'] = $this->model_catalog_product->getRewards($master_id); + } + + // SEO + // product_seo table is not overwritten because that needs to have unique seo keywords for every product + + // Specials + if (!isset($override['product_special'])) { + $product_data['product_special'] = $this->model_catalog_product->getSpecials($master_id); + } + + // Stores + if (!isset($override['product_store'])) { + $product_data['product_store'] = $this->model_catalog_product->getStores($master_id); + } + } + + // If override set the POST data values + foreach ($data as $key => $value) { + if (!isset($product_data[$key])) { + $product_data[$key] = $value; + } + } + + // Product Description + if (isset($data['product_description'])) { + foreach ($data['product_description'] as $language_id => $product_description) { + foreach ($product_description as $key => $value) { + if (!isset($product_data['product_description'][$language_id][$key])) { + $product_data['product_description'][$language_id][$key] = $value; + } + } + } + } + + // Product add with master product overridden values + return $this->model_catalog_product->addProduct($product_data); + } + + /** + * @param int $master_id + * @param int $product_id + * @param array $data + * + * @return void + */ + public function editVariant(int $master_id, int $product_id, array $data): void { + $product_data = []; + + // Use master values to override the values + $master_info = $this->model_catalog_product->getProduct($master_id); + + if ($master_info) { + // We use the override to override the master product values + if (isset($data['override'])) { + $override = (array)$data['override']; + } else { + $override = []; + } + + $ignore = [ + 'product_id', + 'master_id', + 'quantity', + 'override', + 'variant' + ]; + + foreach ($master_info as $key => $value) { + // So if key not in override or ignore list we replace with master value + if (!array_key_exists($key, $override) && !in_array($key, $ignore)) { + $product_data[$key] = $value; + } + } + + // Description + $product_descriptions = $this->model_catalog_product->getDescriptions($master_id); + + foreach ($product_descriptions as $language_id => $product_description) { + foreach ($product_description as $key => $value) { + if (!isset($override['product_description'][$language_id][$key])) { + $product_data['product_description'][$language_id][$key] = $value; + } + } + } + + // Attributes + if (!isset($override['product_attribute'])) { + $product_data['product_attribute'] = $this->model_catalog_product->getAttributes($master_id); + } + + // Category + if (!isset($override['product_category'])) { + $product_data['product_category'] = $this->model_catalog_product->getCategories($master_id); + } + + // Discounts + if (!isset($override['product_discount'])) { + $product_data['product_discount'] = $this->model_catalog_product->getDiscounts($master_id); + } + + // Downloads + if (!isset($override['product_download'])) { + $product_data['product_download'] = $this->model_catalog_product->getDownloads($master_id); + } + + // Filters + if (!isset($override['product_filter'])) { + $product_data['product_filter'] = $this->model_catalog_product->getFilters($master_id); + } + + // Images + if (!isset($override['product_image'])) { + $product_data['product_image'] = $this->model_catalog_product->getImages($master_id); + } + + // Layouts + if (!isset($override['product_layout'])) { + $product_data['product_layout'] = $this->model_catalog_product->getLayouts($master_id); + } + + // Options + // product_option should not be used if variant product + + // Subscription + if (!isset($override['product_subscription'])) { + $product_data['product_subscription'] = $this->model_catalog_product->getSubscriptions($master_id); + } + + // Related + if (!isset($override['product_related'])) { + $product_data['product_related'] = $this->model_catalog_product->getRelated($master_id); + } + + // Rewards + if (!isset($override['product_reward'])) { + $product_data['product_reward'] = $this->model_catalog_product->getRewards($master_id); + } + + // SEO + // product_seo table is not overwritten because that needs to have unique seo keywords for every product + + // Specials + if (!isset($override['product_special'])) { + $product_data['product_special'] = $this->model_catalog_product->getSpecials($master_id); + } + + // Stores + if (!isset($override['product_store'])) { + $product_data['product_store'] = $this->model_catalog_product->getStores($master_id); + } + } + + // If override set the POST data values + foreach ($data as $key => $value) { + if (!isset($product_data[$key])) { + $product_data[$key] = $value; + } + } + + // Product Description + if (isset($data['product_description'])) { + foreach ($data['product_description'] as $language_id => $product_description) { + foreach ($product_description as $key => $value) { + if (!isset($product_data['product_description'][$language_id][$key])) { + $product_data['product_description'][$language_id][$key] = $value; + } + } + } + } + + // Override the variant product data with the master product values + $this->model_catalog_product->editProduct($product_id, $product_data); + } + + /** + * @param int $master_id + * @param array $data + * + * @return void + */ + public function editVariants(int $master_id, array $data): void { + // product_option should not be passed to product variants + unset($data['product_option']); + + // If product is master update variants + $products = $this->model_catalog_product->getProducts(['filter_master_id' => $master_id]); + + foreach ($products as $product) { + $product_data = []; + + // We need to convert JSON strings back into an array so they can be re-encoded to a string to go back into the database. + $product['override'] = (array)json_decode($product['override'], true); + $product['variant'] = (array)json_decode($product['variant'], true); + + // We use the override to override the master product values + if ($product['override']) { + $override = $product['override']; + } else { + $override = []; + } + + $replace = [ + 'product_id', + 'master_id', + 'quantity', + 'override', + 'variant' + ]; + + // Now we want to + foreach ($product as $key => $value) { + // So if key not in override or ignore list we replace with master value + if (array_key_exists($key, $override) || in_array($key, $replace)) { + $product_data[$key] = $value; + } + } + + // Descriptions + $product_descriptions = $this->model_catalog_product->getDescriptions($product['product_id']); + + foreach ($product_descriptions as $language_id => $product_description) { + foreach ($product_description as $key => $value) { + // If override set use the POST data values + if (isset($override['product_description'][$language_id][$key])) { + $product_data['product_description'][$language_id][$key] = $value; + } + } + } + + // Attributes + if (isset($override['product_attribute'])) { + $product_data['product_attribute'] = $this->model_catalog_product->getAttributes($product['product_id']); + } + + // Category + if (isset($override['product_category'])) { + $product_data['product_category'] = $this->model_catalog_product->getCategories($product['product_id']); + } + + // Discounts + if (isset($override['product_discount'])) { + $product_data['product_discount'] = $this->model_catalog_product->getDiscounts($product['product_id']); + } + + // Downloads + if (isset($override['product_download'])) { + $product_data['product_download'] = $this->model_catalog_product->getDownloads($product['product_id']); + } + + // Filters + if (isset($override['product_filter'])) { + $product_data['product_filter'] = $this->model_catalog_product->getFilters($product['product_id']); + } + + // Images + if (isset($override['product_image'])) { + $product_data['product_image'] = $this->model_catalog_product->getImages($product['product_id']); + } + + // Layouts + if (isset($override['product_layout'])) { + $product_data['product_layout'] = $this->model_catalog_product->getLayouts($product['product_id']); + } + + // Subscription + if (isset($override['product_subscription'])) { + $product_data['product_subscription'] = $this->model_catalog_product->getSubscriptions($product['product_id']); + } + + // Related + if (isset($override['product_related'])) { + $product_data['product_related'] = $this->model_catalog_product->getRelated($product['product_id']); + } + + // Rewards + if (isset($override['product_reward'])) { + $product_data['product_reward'] = $this->model_catalog_product->getRewards($product['product_id']); + } + + // SEO + $product_data['product_seo_url'] = $this->model_catalog_product->getSeoUrls($product['product_id']); + + // Specials + if (isset($override['product_special'])) { + $product_data['product_special'] = $this->model_catalog_product->getSpecials($product['product_id']); + } + + // Stores + if (isset($override['product_store'])) { + $product_data['product_store'] = $this->model_catalog_product->getStores($product['product_id']); + } + + // If override set the POST data values + foreach ($data as $key => $value) { + if (!isset($product_data[$key])) { + $product_data[$key] = $value; + } + } + + // Descriptions + if (isset($data['product_description'])) { + foreach ($data['product_description'] as $language_id => $product_description) { + foreach ($product_description as $key => $value) { + // If override set use the POST data values + if (!isset($product_data['product_description'][$language_id][$key])) { + $product_data['product_description'][$language_id][$key] = $value; + } + } + } + } + + $this->model_catalog_product->editProduct($product['product_id'], $product_data); + } + } + + /** + * @param int $product_id + * @param int $rating + * + * @return void + */ + public function editRating(int $product_id, int $rating): void { + $this->db->query("UPDATE `" . DB_PREFIX . "product` SET `rating` = '" . (int)$rating . "', `date_modified` = NOW() WHERE `product_id` = '" . (int)$product_id . "'"); + } + + /** + * @param int $product_id + * + * @return array + */ + public function getProduct(int $product_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "product` p LEFT JOIN `" . DB_PREFIX . "product_description` pd ON (p.`product_id` = pd.`product_id`) WHERE p.`product_id` = '" . (int)$product_id . "' AND pd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getProducts(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "product` p LEFT JOIN `" . DB_PREFIX . "product_description` pd ON (p.`product_id` = pd.`product_id`) WHERE pd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"; + + if (!empty($data['filter_master_id'])) { + $sql .= " AND p.`master_id` = '" . (int)$data['filter_master_id'] . "'"; + } + + if (!empty($data['filter_name'])) { + $sql .= " AND pd.`name` LIKE '" . $this->db->escape((string)$data['filter_name'] . '%') . "'"; + } + + if (!empty($data['filter_model'])) { + $sql .= " AND p.`model` LIKE '" . $this->db->escape((string)$data['filter_model'] . '%') . "'"; + } + + if (!empty($data['filter_price'])) { + $sql .= " AND p.`price` LIKE '" . $this->db->escape((string)$data['filter_price'] . '%') . "'"; + } + + if (isset($data['filter_quantity']) && $data['filter_quantity'] !== '') { + $sql .= " AND p.`quantity` = '" . (int)$data['filter_quantity'] . "'"; + } + + if (isset($data['filter_status']) && $data['filter_status'] !== '') { + $sql .= " AND p.`status` = '" . (int)$data['filter_status'] . "'"; + } + + $sql .= " GROUP BY p.`product_id`"; + + $sort_data = [ + 'pd.name', + 'p.model', + 'p.price', + 'p.quantity', + 'p.status', + 'p.sort_order' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY pd.`name`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param int $product_id + * + * @return array + */ + public function getDescriptions(int $product_id): array { + $product_description_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_description` WHERE `product_id` = '" . (int)$product_id . "'"); + + foreach ($query->rows as $result) { + $product_description_data[$result['language_id']] = [ + 'name' => $result['name'], + 'description' => $result['description'], + 'meta_title' => $result['meta_title'], + 'meta_description' => $result['meta_description'], + 'meta_keyword' => $result['meta_keyword'], + 'tag' => $result['tag'] + ]; + } + + return $product_description_data; + } + + /** + * @param int $product_id + * + * @return array + */ + public function getCategories(int $product_id): array { + $product_category_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_to_category` WHERE `product_id` = '" . (int)$product_id . "'"); + + foreach ($query->rows as $result) { + $product_category_data[] = $result['category_id']; + } + + return $product_category_data; + } + + /** + * @param int $product_id + * + * @return array + */ + public function getFilters(int $product_id): array { + $product_filter_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_filter` WHERE `product_id` = '" . (int)$product_id . "'"); + + foreach ($query->rows as $result) { + $product_filter_data[] = $result['filter_id']; + } + + return $product_filter_data; + } + + /** + * @param int $product_id + * + * @return array + */ + public function getAttributes(int $product_id): array { + $product_attribute_data = []; + + $product_attribute_query = $this->db->query("SELECT attribute_id FROM `" . DB_PREFIX . "product_attribute` WHERE `product_id` = '" . (int)$product_id . "' GROUP BY `attribute_id`"); + + foreach ($product_attribute_query->rows as $product_attribute) { + $product_attribute_description_data = []; + + $product_attribute_description_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_attribute` WHERE `product_id` = '" . (int)$product_id . "' AND `attribute_id` = '" . (int)$product_attribute['attribute_id'] . "'"); + + foreach ($product_attribute_description_query->rows as $product_attribute_description) { + $product_attribute_description_data[$product_attribute_description['language_id']] = ['text' => $product_attribute_description['text']]; + } + + $product_attribute_data[] = [ + 'attribute_id' => $product_attribute['attribute_id'], + 'product_attribute_description' => $product_attribute_description_data + ]; + } + + return $product_attribute_data; + } + + /** + * @param int $product_id + * + * @return array + */ + public function getOptions(int $product_id): array { + $product_option_data = []; + + $product_option_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_option` po LEFT JOIN `" . DB_PREFIX . "option` o ON (po.`option_id` = o.`option_id`) LEFT JOIN `" . DB_PREFIX . "option_description` od ON (o.`option_id` = od.`option_id`) WHERE po.`product_id` = '" . (int)$product_id . "' AND od.`language_id` = '" . (int)$this->config->get('config_language_id') . "' ORDER BY o.`sort_order` ASC"); + + foreach ($product_option_query->rows as $product_option) { + $product_option_value_data = []; + + $product_option_value_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_option_value` pov LEFT JOIN `" . DB_PREFIX . "option_value` ov ON (pov.`option_value_id` = ov.`option_value_id`) WHERE pov.`product_option_id` = '" . (int)$product_option['product_option_id'] . "' ORDER BY ov.`sort_order` ASC"); + + foreach ($product_option_value_query->rows as $product_option_value) { + $product_option_value_data[] = [ + 'product_option_value_id' => $product_option_value['product_option_value_id'], + 'option_value_id' => $product_option_value['option_value_id'], + 'quantity' => $product_option_value['quantity'], + 'subtract' => $product_option_value['subtract'], + 'price' => $product_option_value['price'], + 'price_prefix' => $product_option_value['price_prefix'], + 'points' => $product_option_value['points'], + 'points_prefix' => $product_option_value['points_prefix'], + 'weight' => $product_option_value['weight'], + 'weight_prefix' => $product_option_value['weight_prefix'] + ]; + } + + $product_option_data[] = [ + 'product_option_id' => $product_option['product_option_id'], + 'product_option_value' => $product_option_value_data, + 'option_id' => $product_option['option_id'], + 'name' => $product_option['name'], + 'type' => $product_option['type'], + 'value' => $product_option['value'], + 'required' => $product_option['required'] + ]; + } + + return $product_option_data; + } + + /** + * @param int $product_id + * @param int $product_option_value_id + * + * @return array + */ + public function getOptionValue(int $product_id, int $product_option_value_id): array { + $query = $this->db->query("SELECT pov.`option_value_id`, ovd.`name`, pov.`quantity`, pov.`subtract`, pov.`price`, pov.`price_prefix`, pov.`points`, pov.`points_prefix`, pov.`weight`, pov.`weight_prefix` FROM `" . DB_PREFIX . "product_option_value` pov LEFT JOIN `" . DB_PREFIX . "option_value` ov ON (pov.`option_value_id` = ov.`option_value_id`) LEFT JOIN `" . DB_PREFIX . "option_value_description` ovd ON (ov.`option_value_id` = ovd.`option_value_id`) WHERE pov.`product_id` = '" . (int)$product_id . "' AND pov.`product_option_value_id` = '" . (int)$product_option_value_id . "' AND ovd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return $query->row; + } + + /** + * @param int $option_id + * + * @return array + */ + public function getOptionValuesByOptionId(int $option_id): array { + $query = $this->db->query("SELECT DISTINCT `option_value_id` FROM `" . DB_PREFIX . "product_option_value` WHERE `option_id` = '" . (int)$option_id . "'"); + + return $query->rows; + } + + /** + * @param int $product_id + * + * @return array + */ + public function getImages(int $product_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_image` WHERE `product_id` = '" . (int)$product_id . "' ORDER BY `sort_order` ASC"); + + return $query->rows; + } + + /** + * @param int $product_id + * + * @return array + */ + public function getDiscounts(int $product_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_discount` WHERE `product_id` = '" . (int)$product_id . "' ORDER BY `quantity`, `priority`, `price`"); + + return $query->rows; + } + + /** + * @param int $product_id + * + * @return array + */ + public function getSpecials(int $product_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_special` WHERE `product_id` = '" . (int)$product_id . "' ORDER BY `priority`, `price`"); + + return $query->rows; + } + + /** + * @param int $product_id + * + * @return array + */ + public function getRewards(int $product_id): array { + $product_reward_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_reward` WHERE `product_id` = '" . (int)$product_id . "'"); + + foreach ($query->rows as $result) { + $product_reward_data[$result['customer_group_id']] = ['points' => $result['points']]; + } + + return $product_reward_data; + } + + /** + * @param int $product_id + * + * @return array + */ + public function getDownloads(int $product_id): array { + $product_download_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_to_download` WHERE `product_id` = '" . (int)$product_id . "'"); + + foreach ($query->rows as $result) { + $product_download_data[] = $result['download_id']; + } + + return $product_download_data; + } + + /** + * @param int $product_id + * + * @return array + */ + public function getStores(int $product_id): array { + $product_store_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_to_store` WHERE `product_id` = '" . (int)$product_id . "'"); + + foreach ($query->rows as $result) { + $product_store_data[] = $result['store_id']; + } + + return $product_store_data; + } + + /** + * @param int $product_id + * + * @return array + */ + public function getSeoUrls(int $product_id): array { + $product_seo_url_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "seo_url` WHERE `key` = 'product_id' AND `value` = '" . (int)$product_id . "'"); + + foreach ($query->rows as $result) { + $product_seo_url_data[$result['store_id']][$result['language_id']] = $result['keyword']; + } + + return $product_seo_url_data; + } + + /** + * @param int $product_id + * + * @return array + */ + public function getLayouts(int $product_id): array { + $product_layout_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_to_layout` WHERE `product_id` = '" . (int)$product_id . "'"); + + foreach ($query->rows as $result) { + $product_layout_data[$result['store_id']] = $result['layout_id']; + } + + return $product_layout_data; + } + + /** + * @param int $product_id + * + * @return array + */ + public function getRelated(int $product_id): array { + $product_related_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_related` WHERE `product_id` = '" . (int)$product_id . "'"); + + foreach ($query->rows as $result) { + $product_related_data[] = $result['related_id']; + } + + return $product_related_data; + } + + /** + * @param int $product_id + * + * @return array + */ + public function getSubscriptions(int $product_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_subscription` WHERE `product_id` = '" . (int)$product_id . "'"); + + return $query->rows; + } + + /** + * @param array $data + * + * @return int + */ + public function getTotalProducts(array $data = []): int { + $sql = "SELECT COUNT(DISTINCT p.`product_id`) AS `total` FROM `" . DB_PREFIX . "product` p LEFT JOIN `" . DB_PREFIX . "product_description` pd ON (p.`product_id` = pd.`product_id`) WHERE pd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"; + + if (!empty($data['filter_master_id'])) { + $sql .= " AND p.`master_id` = '" . (int)$data['filter_master_id'] . "'"; + } + + if (!empty($data['filter_name'])) { + $sql .= " AND pd.`name` LIKE '" . $this->db->escape((string)$data['filter_name'] . '%') . "'"; + } + + if (!empty($data['filter_model'])) { + $sql .= " AND p.`model` LIKE '" . $this->db->escape((string)$data['filter_model'] . '%') . "'"; + } + + if (isset($data['filter_price']) && $data['filter_price'] !== '') { + $sql .= " AND p.`price` LIKE '" . $this->db->escape((string)$data['filter_price'] . '%') . "'"; + } + + if (isset($data['filter_quantity']) && $data['filter_quantity'] !== '') { + $sql .= " AND p.`quantity` = '" . (int)$data['filter_quantity'] . "'"; + } + + if (isset($data['filter_status']) && $data['filter_status'] !== '') { + $sql .= " AND p.`status` = '" . (int)$data['filter_status'] . "'"; + } + + $query = $this->db->query($sql); + + return (int)$query->row['total']; + } + + /** + * @param int $tax_class_id + * + * @return int + */ + public function getTotalProductsByTaxClassId(int $tax_class_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "product` WHERE `tax_class_id` = '" . (int)$tax_class_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $stock_status_id + * + * @return int + */ + public function getTotalProductsByStockStatusId(int $stock_status_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "product` WHERE `stock_status_id` = '" . (int)$stock_status_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $weight_class_id + * + * @return int + */ + public function getTotalProductsByWeightClassId(int $weight_class_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "product` WHERE `weight_class_id` = '" . (int)$weight_class_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $length_class_id + * + * @return int + */ + public function getTotalProductsByLengthClassId(int $length_class_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "product` WHERE `length_class_id` = '" . (int)$length_class_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $download_id + * + * @return int + */ + public function getTotalProductsByDownloadId(int $download_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "product_to_download` WHERE `download_id` = '" . (int)$download_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $manufacturer_id + * + * @return int + */ + public function getTotalProductsByManufacturerId(int $manufacturer_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "product` WHERE `manufacturer_id` = '" . (int)$manufacturer_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $attribute_id + * + * @return int + */ + public function getTotalProductsByAttributeId(int $attribute_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "product_attribute` WHERE `attribute_id` = '" . (int)$attribute_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $subscription_plan_id + * + * @return int + */ + public function getTotalProductsBySubscriptionPlanId(int $subscription_plan_id): int { + $query = $this->db->query("SELECT COUNT(DISTINCT `product_id`) AS `total` FROM `" . DB_PREFIX . "product_subscription` WHERE `subscription_plan_id` = '" . (int)$subscription_plan_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $layout_id + * + * @return int + */ + public function getTotalProductsByLayoutId(int $layout_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "product_to_layout` WHERE `layout_id` = '" . (int)$layout_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $option_id + * + * @return int + */ + public function getTotalProductsByOptionId(int $option_id): int { + $query = $this->db->query("SELECT COUNT(DISTINCT `product_id`) AS `total` FROM `" . DB_PREFIX . "product_option` WHERE `option_id` = '" . (int)$option_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $option_value_id + * + * @return int + */ + public function getTotalProductsByOptionValueId(int $option_value_id): int { + $query = $this->db->query("SELECT COUNT(DISTINCT `product_id`) AS `total` FROM `" . DB_PREFIX . "product_option_value` WHERE `option_value_id` = '" . (int)$option_value_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $product_id + * @param int $start + * @param int $limit + * + * @return array + */ + public function getReports(int $product_id, int $start = 0, int $limit = 10): array { + if ($start < 0) { + $start = 0; + } + + if ($limit < 1) { + $limit = 10; + } + + $query = $this->db->query("SELECT `ip`, `store_id`, `country`, `date_added` FROM `" . DB_PREFIX . "product_report` WHERE `product_id` = '" . (int)$product_id . "' ORDER BY `date_added` ASC LIMIT " . (int)$start . "," . (int)$limit); + + return $query->rows; + } + + /** + * @param int $product_id + * + * @return int + */ + public function getTotalReports(int $product_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "product_report` WHERE `product_id` = '" . (int)$product_id . "'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/catalog/review.php b/admininistrator/model/catalog/review.php new file mode 100644 index 0000000..eaa41ac --- /dev/null +++ b/admininistrator/model/catalog/review.php @@ -0,0 +1,198 @@ +db->query("INSERT INTO `" . DB_PREFIX . "review` SET `author` = '" . $this->db->escape((string)$data['author']) . "', `product_id` = '" . (int)$data['product_id'] . "', `text` = '" . $this->db->escape(strip_tags((string)$data['text'])) . "', `rating` = '" . (int)$data['rating'] . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "', `date_added` = '" . $this->db->escape((string)$data['date_added']) . "'"); + + $review_id = $this->db->getLastId(); + + // Update product rating + $this->load->model('catalog/product'); + + $this->model_catalog_product->editRating($data['product_id'], $this->getRating($data['product_id'])); + + $this->cache->delete('product'); + + return $review_id; + } + + /** + * @param int $review_id + * @param array $data + * + * @return void + */ + public function editReview(int $review_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "review` SET `author` = '" . $this->db->escape((string)$data['author']) . "', `product_id` = '" . (int)$data['product_id'] . "', `text` = '" . $this->db->escape(strip_tags((string)$data['text'])) . "', `rating` = '" . (int)$data['rating'] . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "', `date_added` = '" . $this->db->escape((string)$data['date_added']) . "', `date_modified` = NOW() WHERE `review_id` = '" . (int)$review_id . "'"); + + // Update product rating + $this->load->model('catalog/product'); + + $this->model_catalog_product->editRating($data['product_id'], $this->getRating($data['product_id'])); + + $this->cache->delete('product'); + } + + /** + * @param int $review_id + * + * @return void + */ + public function deleteReview(int $review_id): void { + $review_info = $this->getReview($review_id); + + if ($review_info) { + $this->db->query("DELETE FROM `" . DB_PREFIX . "review` WHERE `review_id` = '" . (int)$review_info['review_id'] . "'"); + + // Update product rating + $this->load->model('catalog/product'); + + $this->model_catalog_product->editRating($review_info['product_id'], $this->getRating($review_info['product_id'])); + + $this->cache->delete('product'); + } + } + + /** + * @param int $review_id + * + * @return array + */ + public function getReview(int $review_id): array { + $query = $this->db->query("SELECT DISTINCT *, (SELECT pd.`name` FROM `" . DB_PREFIX . "product_description` pd WHERE pd.`product_id` = r.`product_id` AND pd.`language_id` = '" . (int)$this->config->get('config_language_id') . "') AS product FROM `" . DB_PREFIX . "review` r WHERE r.`review_id` = '" . (int)$review_id . "'"); + + return $query->row; + } + + /** + * @param int $product_id + * + * @return int + */ + public function getRating(int $product_id): int { + $query = $this->db->query("SELECT AVG(`rating`) AS `total` FROM `" . DB_PREFIX . "review` WHERE `product_id` = '" . (int)$product_id . "' AND `status` = '1'"); + + if ($query->num_rows) { + return (int)$query->row['total']; + } else { + return 0; + } + } + + /** + * @param array $data + * + * @return array + */ + public function getReviews(array $data = []): array { + $sql = "SELECT r.`review_id`, pd.`name`, r.`author`, r.`rating`, r.`status`, r.`date_added` FROM `" . DB_PREFIX . "review` r LEFT JOIN `" . DB_PREFIX . "product_description` pd ON (r.`product_id` = pd.`product_id`) WHERE pd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"; + + if (!empty($data['filter_product'])) { + $sql .= " AND pd.`name` LIKE '" . $this->db->escape((string)$data['filter_product'] . '%') . "'"; + } + + if (!empty($data['filter_author'])) { + $sql .= " AND r.`author` LIKE '" . $this->db->escape((string)$data['filter_author'] . '%') . "'"; + } + + if (isset($data['filter_status']) && $data['filter_status'] !== '') { + $sql .= " AND r.`status` = '" . (int)$data['filter_status'] . "'"; + } + + if (!empty($data['filter_date_from'])) { + $sql .= " AND DATE(r.`date_added`) >= DATE('" . $this->db->escape((string)$data['filter_date_from']) . "')"; + } + + if (!empty($data['filter_date_to'])) { + $sql .= " AND DATE(r.`date_added`) <= DATE('" . $this->db->escape((string)$data['filter_date_to']) . "')"; + } + + $sort_data = [ + 'pd.name', + 'r.author', + 'r.rating', + 'r.status', + 'r.date_added' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY r.`date_added`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param array $data + * + * @return int + */ + public function getTotalReviews(array $data = []): int { + $sql = "SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "review` r LEFT JOIN `" . DB_PREFIX . "product_description` pd ON (r.`product_id` = pd.`product_id`) WHERE pd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"; + + if (!empty($data['filter_product'])) { + $sql .= " AND pd.`name` LIKE '" . $this->db->escape((string)$data['filter_product'] . '%') . "'"; + } + + if (!empty($data['filter_author'])) { + $sql .= " AND r.`author` LIKE '" . $this->db->escape((string)$data['filter_author'] . '%') . "'"; + } + + if (isset($data['filter_status']) && $data['filter_status'] !== '') { + $sql .= " AND r.`status` = '" . (int)$data['filter_status'] . "'"; + } + + if (!empty($data['filter_date_from'])) { + $sql .= " AND DATE(r.`date_added`) >= DATE('" . $this->db->escape((string)$data['filter_date_from']) . "')"; + } + + if (!empty($data['filter_date_to'])) { + $sql .= " AND DATE(r.`date_added`) <= DATE('" . $this->db->escape((string)$data['filter_date_to']) . "')"; + } + + $query = $this->db->query($sql); + + return (int)$query->row['total']; + } + + /** + * @return int + */ + public function getTotalReviewsAwaitingApproval(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "review` WHERE `status` = '0'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/catalog/subscription_plan.php b/admininistrator/model/catalog/subscription_plan.php new file mode 100644 index 0000000..6695014 --- /dev/null +++ b/admininistrator/model/catalog/subscription_plan.php @@ -0,0 +1,149 @@ +db->query("INSERT INTO `" . DB_PREFIX . "subscription_plan` SET `trial_frequency` = '" . $this->db->escape((string)$data['trial_frequency']) . "', `trial_duration` = '" . (int)$data['trial_duration'] . "', `trial_cycle` = '" . (int)$data['trial_cycle'] . "', `trial_status` = '" . (int)$data['trial_status'] . "', `frequency` = '" . $this->db->escape((string)$data['frequency']) . "', `duration` = '" . (int)$data['duration'] . "', `cycle` = '" . (int)$data['cycle'] . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "', `sort_order` = '" . (int)$data['sort_order'] . "'"); + + $subscription_plan_id = $this->db->getLastId(); + + foreach ($data['subscription_plan_description'] as $language_id => $subscription_plan_description) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "subscription_plan_description` SET `subscription_plan_id` = '" . (int)$subscription_plan_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($subscription_plan_description['name']) . "'"); + } + + return $subscription_plan_id; + } + + /** + * @param int $subscription_plan_id + * @param array $data + * + * @return void + */ + public function editSubscriptionPlan(int $subscription_plan_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "subscription_plan` SET `trial_frequency` = '" . $this->db->escape((string)$data['trial_frequency']) . "', `trial_duration` = '" . (int)$data['trial_duration'] . "', `trial_cycle` = '" . (int)$data['trial_cycle'] . "', `trial_status` = '" . (int)$data['trial_status'] . "', `frequency` = '" . $this->db->escape((string)$data['frequency']) . "', `duration` = '" . (int)$data['duration'] . "', `cycle` = '" . (int)$data['cycle'] . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "', `sort_order` = '" . (int)$data['sort_order'] . "' WHERE `subscription_plan_id` = '" . (int)$subscription_plan_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "subscription_plan_description` WHERE `subscription_plan_id` = '" . (int)$subscription_plan_id . "'"); + + foreach ($data['subscription_plan_description'] as $language_id => $subscription_plan_description) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "subscription_plan_description` SET `subscription_plan_id` = '" . (int)$subscription_plan_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($subscription_plan_description['name']) . "'"); + } + } + + /** + * @param int $subscription_plan_id + * + * @return void + */ + public function copySubscriptionPlan(int $subscription_plan_id): void { + $data = $this->getSubscriptionPlan($subscription_plan_id); + + $data['subscription_plan_description'] = $this->getDescription($subscription_plan_id); + + $this->addSubscriptionPlan($data); + } + + /** + * @param int $subscription_plan_id + * + * @return void + */ + public function deleteSubscriptionPlan(int $subscription_plan_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "subscription_plan` WHERE `subscription_plan_id` = '" . (int)$subscription_plan_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "subscription_plan_description` WHERE `subscription_plan_id` = '" . (int)$subscription_plan_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_subscription` WHERE `subscription_plan_id` = '" . (int)$subscription_plan_id . "'"); + $this->db->query("UPDATE `" . DB_PREFIX . "subscription` SET `subscription_plan_id` = '0' WHERE `subscription_plan_id` = '" . (int)$subscription_plan_id . "'"); + } + + /** + * @param int $subscription_plan_id + * + * @return array + */ + public function getSubscriptionPlan(int $subscription_plan_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "subscription_plan` sp LEFT JOIN `" . DB_PREFIX . "subscription_plan_description` spd ON (sp.`subscription_plan_id` = spd.`subscription_plan_id`) WHERE sp.`subscription_plan_id` = '" . (int)$subscription_plan_id . "' AND spd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return $query->row; + } + + /** + * @param int $subscription_plan_id + * + * @return array + */ + public function getDescription(int $subscription_plan_id): array { + $subscription_plan_description_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "subscription_plan_description` WHERE `subscription_plan_id` = '" . (int)$subscription_plan_id . "'"); + + foreach ($query->rows as $result) { + $subscription_plan_description_data[$result['language_id']] = ['name' => $result['name']]; + } + + return $subscription_plan_description_data; + } + + /** + * @param array $data + * + * @return array + */ + public function getSubscriptionPlans(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "subscription_plan` sp LEFT JOIN `" . DB_PREFIX . "subscription_plan_description` spd ON (sp.`subscription_plan_id` = spd.`subscription_plan_id`) WHERE spd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"; + + if (!empty($data['filter_name'])) { + $sql .= " AND spd.`name` LIKE '" . $this->db->escape((string)$data['filter_name'] . '%') . "'"; + } + + $sort_data = [ + 'spd.name', + 'sp.sort_order' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `spd`.`name`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @return int + */ + public function getTotalSubscriptionPlans(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "subscription_plan`"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/cms/antispam.php b/admininistrator/model/cms/antispam.php new file mode 100644 index 0000000..47411b8 --- /dev/null +++ b/admininistrator/model/cms/antispam.php @@ -0,0 +1,120 @@ +db->query("INSERT INTO `" . DB_PREFIX . "antispam` SET `keyword` = '" . $this->db->escape((string)$data['keyword']) . "'"); + + return $this->db->getLastId(); + } + + /** + * @param array $data + * + * @return int + */ + public function editAntispam(int $antispam_id, array $data = []): void { + $this->db->query("UPDATE `" . DB_PREFIX . "antispam` SET `keyword` = '" . $this->db->escape((string)$data['keyword']) . "' WHERE `antispam_id` = '" . (int)$antispam_id . "'"); + } + + /** + * @param int $antispam_id + * + * @return void + */ + public function deleteAntispam(int $antispam_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "antispam` WHERE `antispam_id` = '" . (int)$antispam_id . "'"); + } + + /** + * @param int $antispam_id + * + * @return array + */ + public function getAntispam(int $antispam_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "antispam` WHERE `antispam_id` = '" . (int)$antispam_id . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getAntispams(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "antispam`"; + + $implode = []; + + if (!empty($data['filter_keyword'])) { + $implode[] = "`keyword` LIKE '" . $this->db->escape((string)$data['filter_keyword']) . "'"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $sort_data = ['keyword']; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `keyword`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param array $data + * + * @return int + */ + public function getTotalAntispams(array $data = []): int { + $sql = "SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "antispam`"; + + $implode = []; + + if (!empty($data['filter_keyword'])) { + $implode[] = "`keyword` LIKE '" . $this->db->escape((string)$data['filter_keyword']) . "'"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $query = $this->db->query($sql); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/cms/article.php b/admininistrator/model/cms/article.php new file mode 100644 index 0000000..52b510a --- /dev/null +++ b/admininistrator/model/cms/article.php @@ -0,0 +1,365 @@ +db->query("INSERT INTO `" . DB_PREFIX . "article` SET `topic_id` = '" . (int)$data['topic_id'] . "', `author` = '" . $this->db->escape($data['author']) . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "', `date_added` = NOW(), `date_modified` = NOW()"); + + $article_id = $this->db->getLastId(); + + foreach ($data['article_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "article_description` SET `article_id` = '" . (int)$article_id . "', `language_id` = '" . (int)$language_id . "', `image` = '" . $this->db->escape($value['image']) . "', `name` = '" . $this->db->escape($value['name']) . "', `description` = '" . $this->db->escape($value['description']) . "', `tag` = '" . $this->db->escape($value['tag']) . "', `meta_title` = '" . $this->db->escape($value['meta_title']) . "', `meta_description` = '" . $this->db->escape($value['meta_description']) . "', `meta_keyword` = '" . $this->db->escape($value['meta_keyword']) . "'"); + } + + if (isset($data['article_store'])) { + foreach ($data['article_store'] as $store_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "article_to_store` SET `article_id` = '" . (int)$article_id . "', `store_id` = '" . (int)$store_id . "'"); + } + } + + foreach ($data['article_seo_url'] as $store_id => $language) { + foreach ($language as $language_id => $keyword) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "seo_url` SET `store_id` = '" . (int)$store_id . "', `language_id` = '" . (int)$language_id . "', `key` = 'article_id', `value`= '" . (int)$article_id . "', `keyword` = '" . $this->db->escape($keyword) . "'"); + } + } + + // Set which layout to use with this article + if (isset($data['article_layout'])) { + foreach ($data['article_layout'] as $store_id => $layout_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "article_to_layout` SET `article_id` = '" . (int)$article_id . "', `store_id` = '" . (int)$store_id . "', `layout_id` = '" . (int)$layout_id . "'"); + } + } + + $this->cache->delete('article'); + + return $article_id; + } + + /** + * @param int $article_id + * @param array $data + * + * @return void + */ + public function editArticle(int $article_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "article` SET `topic_id` = '" . (int)$data['topic_id'] . "', `author` = '" . $this->db->escape($data['author']) . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "', `date_modified` = NOW() WHERE `article_id` = '" . (int)$article_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "article_description` WHERE `article_id` = '" . (int)$article_id . "'"); + + foreach ($data['article_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "article_description` SET `article_id` = '" . (int)$article_id . "', `language_id` = '" . (int)$language_id . "', `image` = '" . $this->db->escape($value['image']) . "', `name` = '" . $this->db->escape($value['name']) . "', `description` = '" . $this->db->escape($value['description']) . "', `tag` = '" . $this->db->escape($value['tag']) . "', `meta_title` = '" . $this->db->escape($value['meta_title']) . "', `meta_description` = '" . $this->db->escape($value['meta_description']) . "', `meta_keyword` = '" . $this->db->escape($value['meta_keyword']) . "'"); + } + + $this->db->query("DELETE FROM `" . DB_PREFIX . "article_to_store` WHERE `article_id` = '" . (int)$article_id . "'"); + + if (isset($data['article_store'])) { + foreach ($data['article_store'] as $store_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "article_to_store` SET `article_id` = '" . (int)$article_id . "', `store_id` = '" . (int)$store_id . "'"); + } + } + + $this->db->query("DELETE FROM `" . DB_PREFIX . "seo_url` WHERE `key` = 'article_id' AND `value` = '" . (int)$article_id . "'"); + + foreach ($data['article_seo_url'] as $store_id => $language) { + foreach ($language as $language_id => $keyword) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "seo_url` SET `store_id` = '" . (int)$store_id . "', `language_id` = '" . (int)$language_id . "', `key` = 'article_id', `value` = '" . (int)$article_id . "', `keyword` = '" . $this->db->escape($keyword) . "'"); + } + } + + // Layouts + $this->db->query("DELETE FROM `" . DB_PREFIX . "article_to_layout` WHERE `article_id` = '" . (int)$article_id . "'"); + + if (isset($data['article_layout'])) { + foreach ($data['article_layout'] as $store_id => $layout_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "article_to_layout` SET `article_id` = '" . (int)$article_id . "', `store_id` = '" . (int)$store_id . "', `layout_id` = '" . (int)$layout_id . "'"); + } + } + + $this->cache->delete('article'); + } + + /** + * @param int $article_id + * + * @return void + */ + public function deleteArticle(int $article_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "article` WHERE `article_id` = '" . (int)$article_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "article_comment` WHERE `article_id` = '" . (int)$article_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "article_description` WHERE `article_id` = '" . (int)$article_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "article_to_store` WHERE `article_id` = '" . (int)$article_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "article_to_layout` WHERE `article_id` = '" . (int)$article_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "seo_url` WHERE `key` = 'article_id' AND `value` = '" . (int)$article_id . "'"); + + $this->cache->delete('article'); + } + + /** + * @param int $article_id + * + * @return array + */ + public function getArticle(int $article_id): array { + $sql = "SELECT DISTINCT * FROM `" . DB_PREFIX . "article` `a` LEFT JOIN `" . DB_PREFIX . "article_description` `ad` ON (`a`.`article_id` = `ad`.`article_id`) WHERE `a`.`article_id` = '" . (int)$article_id . "' AND `ad`.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"; + + $article_data = $this->cache->get('article.'. md5($sql)); + + if (!$article_data) { + $query = $this->db->query($sql); + + $article_data = $query->row; + + $this->cache->set('article.'. md5($sql), $article_data); + } + + return $article_data; + } + + /** + * @param array $data + * + * @return array + */ + public function getArticles(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "article` `a` LEFT JOIN `" . DB_PREFIX . "article_description` `ad` ON (`a`.`article_id` = `ad`.`article_id`) WHERE `ad`.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"; + + if (!empty($data['filter_name'])) { + $sql .= " AND `ad`.`name` LIKE '" . $this->db->escape((string)$data['filter_name']) . "'"; + } + + $sort_data = [ + 'ad.name', + 'a.date_added' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `a`.`date_added`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $article_data = $this->cache->get('article.'. md5($sql)); + + if (!$article_data) { + $query = $this->db->query($sql); + + $article_data = $query->rows; + + $this->cache->set('article.'. md5($sql), $article_data); + } + + return $article_data; + } + + /** + * @param int $article_id + * + * @return array + */ + public function getDescriptions(int $article_id): array { + $article_description_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "article_description` WHERE `article_id` = '" . (int)$article_id . "'"); + + foreach ($query->rows as $result) { + $article_description_data[$result['language_id']] = [ + 'image' => $result['image'], + 'name' => $result['name'], + 'description' => $result['description'], + 'tag' => $result['tag'], + 'meta_title' => $result['meta_title'], + 'meta_description' => $result['meta_description'], + 'meta_keyword' => $result['meta_keyword'] + ]; + } + + return $article_description_data; + } + + /** + * @param int $article_id + * + * @return array + */ + public function getSeoUrls(int $article_id): array { + $article_seo_url_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "seo_url` WHERE `key` = 'article_id' AND `value` = '" . (int)$article_id . "'"); + + foreach ($query->rows as $result) { + $article_seo_url_data[$result['store_id']][$result['language_id']] = $result['keyword']; + } + + return $article_seo_url_data; + } + + /** + * @param int $article_id + * + * @return array + */ + public function getStores(int $article_id): array { + $article_store_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "article_to_store` WHERE `article_id` = '" . (int)$article_id . "'"); + + foreach ($query->rows as $result) { + $article_store_data[] = $result['store_id']; + } + + return $article_store_data; + } + + /** + * @param int $article_id + * + * @return array + */ + public function getLayouts(int $article_id): array { + $article_layout_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "article_to_layout` WHERE `article_id` = '" . (int)$article_id . "'"); + + foreach ($query->rows as $result) { + $article_layout_data[$result['store_id']] = $result['layout_id']; + } + + return $article_layout_data; + } + + /** + * @return int + */ + public function getTotalArticles(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "article`"); + + return (int)$query->row['total']; + } + + /** + * @param int $layout_id + * + * @return int + */ + public function getTotalArticlesByLayoutId(int $layout_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "article_to_layout` WHERE `layout_id` = '" . (int)$layout_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $article_comment_id + * + * @return void + */ + public function deleteComment(int $article_comment_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "article_comment` WHERE `article_comment_id` = '" . (int)$article_comment_id . "'"); + } + + /** + * @param int $customer_id + * + * @return void + */ + public function deleteCommentsByCustomerId(int $customer_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "article_comment` WHERE `customer_id` = '" . (int)$customer_id . "'"); + } + + /** + * @param int $article_comment_id + * + * @return array + */ + public function getComment(int $article_comment_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "article_comment` WHERE `article_comment_id` = '" . (int)$article_comment_id . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getComments(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "article_comment`"; + + $implode = []; + + if (!empty($data['filter_keyword'])) { + $implode[] = "LCASE(`comment`) LIKE '" . $this->db->escape('%' . (string)$data['filter_keyword'] . '%') . "'"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $sql .= " ORDER BY `date_added` DESC"; + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param array $data + * + * @return int + */ + public function getTotalComments(array $data = []): int { + $sql = "SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "article_comment`"; + + $implode = []; + + if (!empty($data['filter_keyword'])) { + $implode[] = "LCASE(`comment`) LIKE '" . $this->db->escape('%' . (string)$data['filter_keyword'] . '%') . "'"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $query = $this->db->query($sql); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/cms/topic.php b/admininistrator/model/cms/topic.php new file mode 100644 index 0000000..32a643c --- /dev/null +++ b/admininistrator/model/cms/topic.php @@ -0,0 +1,225 @@ +db->query("INSERT INTO `" . DB_PREFIX . "topic` SET `sort_order` = '" . (int)$data['sort_order'] . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "'"); + + $topic_id = $this->db->getLastId(); + + foreach ($data['topic_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "topic_description` SET `topic_id` = '" . (int)$topic_id . "', `language_id` = '" . (int)$language_id . "', `image` = '" . $this->db->escape((string)$value['image']) . "', `name` = '" . $this->db->escape($value['name']) . "', `description` = '" . $this->db->escape($value['description']) . "', `meta_title` = '" . $this->db->escape($value['meta_title']) . "', `meta_description` = '" . $this->db->escape($value['meta_description']) . "', `meta_keyword` = '" . $this->db->escape($value['meta_keyword']) . "'"); + } + + if (isset($data['topic_store'])) { + foreach ($data['topic_store'] as $store_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "topic_to_store` SET `topic_id` = '" . (int)$topic_id . "', `store_id` = '" . (int)$store_id . "'"); + } + } + + foreach ($data['topic_seo_url'] as $store_id => $language) { + foreach ($language as $language_id => $keyword) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "seo_url` SET `store_id` = '" . (int)$store_id . "', `language_id` = '" . (int)$language_id . "', `key` = 'topic_id', `value`= '" . (int)$topic_id . "', `keyword` = '" . $this->db->escape($keyword) . "'"); + } + } + + $this->cache->delete('topic'); + + return $topic_id; + } + + /** + * @param int $topic_id + * @param array $data + * + * @return void + */ + public function editTopic(int $topic_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "topic` SET `sort_order` = '" . (int)$data['sort_order'] . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "' WHERE `topic_id` = '" . (int)$topic_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "topic_description` WHERE `topic_id` = '" . (int)$topic_id . "'"); + + foreach ($data['topic_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "topic_description` SET `topic_id` = '" . (int)$topic_id . "', `language_id` = '" . (int)$language_id . "', `image` = '" . $this->db->escape((string)$value['image']) . "', `name` = '" . $this->db->escape($value['name']) . "', `description` = '" . $this->db->escape($value['description']) . "', `meta_title` = '" . $this->db->escape($value['meta_title']) . "', `meta_description` = '" . $this->db->escape($value['meta_description']) . "', `meta_keyword` = '" . $this->db->escape($value['meta_keyword']) . "'"); + } + + $this->db->query("DELETE FROM `" . DB_PREFIX . "topic_to_store` WHERE `topic_id` = '" . (int)$topic_id . "'"); + + if (isset($data['topic_store'])) { + foreach ($data['topic_store'] as $store_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "topic_to_store` SET `topic_id` = '" . (int)$topic_id . "', `store_id` = '" . (int)$store_id . "'"); + } + } + + $this->db->query("DELETE FROM `" . DB_PREFIX . "seo_url` WHERE `key` = 'topic_id' AND `value` = '" . (int)$topic_id . "'"); + + foreach ($data['topic_seo_url'] as $store_id => $language) { + foreach ($language as $language_id => $keyword) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "seo_url` SET `store_id` = '" . (int)$store_id . "', `language_id` = '" . (int)$language_id . "', `key` = 'topic_id', `value` = '" . (int)$topic_id . "', `keyword` = '" . $this->db->escape($keyword) . "'"); + } + } + + $this->cache->delete('topic'); + } + + /** + * @param int $topic_id + * + * @return void + */ + public function deleteTopic(int $topic_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "topic` WHERE `topic_id` = '" . (int)$topic_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "topic_description` WHERE `topic_id` = '" . (int)$topic_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "topic_to_store` WHERE `topic_id` = '" . (int)$topic_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "seo_url` WHERE `key` = 'topic_id' AND `value` = '" . (int)$topic_id . "'"); + + $this->cache->delete('topic'); + } + + /** + * @param int $topic_id + * + * @return array + */ + public function getTopic(int $topic_id): array { + $sql = "SELECT DISTINCT * FROM `" . DB_PREFIX . "topic` `t` LEFT JOIN `" . DB_PREFIX . "topic_description` `td` ON (`t`.`topic_id` = `td`.`topic_id`) WHERE `t`.`topic_id` = '" . (int)$topic_id . "' AND `td`.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"; + + $topic_data = $this->cache->get('topic.'. md5($sql)); + + if (!$topic_data) { + $query = $this->db->query($sql); + + $topic_data = $query->row; + + $this->cache->set('topic.'. md5($sql), $topic_data); + } + + return $topic_data; + } + + /** + * @param array $data + * + * @return array + */ + public function getTopics(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "topic` `t` LEFT JOIN `" . DB_PREFIX . "topic_description` `td` ON (`t`.`topic_id` = `td`.`topic_id`) WHERE `td`.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"; + + $sort_data = [ + 'td.name', + 't.sort_order' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `t`.`sort_order`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $topic_data = $this->cache->get('topic.'. md5($sql)); + + if (!$topic_data) { + $query = $this->db->query($sql); + + $topic_data = $query->rows; + + $this->cache->set('topic.'. md5($sql), $topic_data); + } + + return $topic_data; + } + + /** + * @param int $topic_id + * + * @return array + */ + public function getDescriptions(int $topic_id): array { + $topic_description_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "topic_description` WHERE `topic_id` = '" . (int)$topic_id . "'"); + + foreach ($query->rows as $result) { + $topic_description_data[$result['language_id']] = [ + 'image' => $result['image'], + 'name' => $result['name'], + 'description' => $result['description'], + 'meta_title' => $result['meta_title'], + 'meta_description' => $result['meta_description'], + 'meta_keyword' => $result['meta_keyword'] + ]; + } + + return $topic_description_data; + } + + /** + * @param int $topic_id + * + * @return array + */ + public function getSeoUrls(int $topic_id): array { + $topic_seo_url_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "seo_url` WHERE `key` = 'topic_id' AND `value` = '" . (int)$topic_id . "'"); + + foreach ($query->rows as $result) { + $topic_seo_url_data[$result['store_id']][$result['language_id']] = $result['keyword']; + } + + return $topic_seo_url_data; + } + + /** + * @param int $topic_id + * + * @return array + */ + public function getStores(int $topic_id): array { + $topic_store_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "topic_to_store` WHERE `topic_id` = '" . (int)$topic_id . "'"); + + foreach ($query->rows as $result) { + $topic_store_data[] = $result['store_id']; + } + + return $topic_store_data; + } + + /** + * @return int + */ + public function getTotalTopics(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "topic`"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/customer/custom_field.php b/admininistrator/model/customer/custom_field.php new file mode 100644 index 0000000..3528ad7 --- /dev/null +++ b/admininistrator/model/customer/custom_field.php @@ -0,0 +1,276 @@ +db->query("INSERT INTO `" . DB_PREFIX . "custom_field` SET `type` = '" . $this->db->escape((string)$data['type']) . "', `value` = '" . $this->db->escape((string)$data['value']) . "', `validation` = '" . $this->db->escape((string)$data['validation']) . "', `location` = '" . $this->db->escape((string)$data['location']) . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "', `sort_order` = '" . (int)$data['sort_order'] . "'"); + + $custom_field_id = $this->db->getLastId(); + + foreach ($data['custom_field_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "custom_field_description` SET `custom_field_id` = '" . (int)$custom_field_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } + + if (isset($data['custom_field_customer_group'])) { + foreach ($data['custom_field_customer_group'] as $custom_field_customer_group) { + if (isset($custom_field_customer_group['customer_group_id'])) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "custom_field_customer_group` SET `custom_field_id` = '" . (int)$custom_field_id . "', `customer_group_id` = '" . (int)$custom_field_customer_group['customer_group_id'] . "', `required` = '" . (int)(isset($custom_field_customer_group['required']) ? 1 : 0) . "'"); + } + } + } + + if (isset($data['custom_field_value'])) { + foreach ($data['custom_field_value'] as $custom_field_value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "custom_field_value` SET `custom_field_id` = '" . (int)$custom_field_id . "', `sort_order` = '" . (int)$custom_field_value['sort_order'] . "'"); + + $custom_field_value_id = $this->db->getLastId(); + + foreach ($custom_field_value['custom_field_value_description'] as $language_id => $custom_field_value_description) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "custom_field_value_description` SET `custom_field_value_id` = '" . (int)$custom_field_value_id . "', `language_id` = '" . (int)$language_id . "', `custom_field_id` = '" . (int)$custom_field_id . "', `name` = '" . $this->db->escape($custom_field_value_description['name']) . "'"); + } + } + } + + return $custom_field_id; + } + + /** + * @param int $custom_field_id + * @param array $data + * + * @return void + */ + public function editCustomField(int $custom_field_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "custom_field` SET `type` = '" . $this->db->escape((string)$data['type']) . "', `value` = '" . $this->db->escape((string)$data['value']) . "', `validation` = '" . $this->db->escape((string)$data['validation']) . "', `location` = '" . $this->db->escape((string)$data['location']) . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "', `sort_order` = '" . (int)$data['sort_order'] . "' WHERE `custom_field_id` = '" . (int)$custom_field_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "custom_field_description` WHERE `custom_field_id` = '" . (int)$custom_field_id . "'"); + + foreach ($data['custom_field_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "custom_field_description` SET `custom_field_id` = '" . (int)$custom_field_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } + + $this->db->query("DELETE FROM `" . DB_PREFIX . "custom_field_customer_group` WHERE `custom_field_id` = '" . (int)$custom_field_id . "'"); + + if (isset($data['custom_field_customer_group'])) { + foreach ($data['custom_field_customer_group'] as $custom_field_customer_group) { + if (isset($custom_field_customer_group['customer_group_id'])) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "custom_field_customer_group` SET `custom_field_id` = '" . (int)$custom_field_id . "', `customer_group_id` = '" . (int)$custom_field_customer_group['customer_group_id'] . "', `required` = '" . (int)(isset($custom_field_customer_group['required']) ? 1 : 0) . "'"); + } + } + } + + $this->db->query("DELETE FROM `" . DB_PREFIX . "custom_field_value` WHERE `custom_field_id` = '" . (int)$custom_field_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "custom_field_value_description` WHERE `custom_field_id` = '" . (int)$custom_field_id . "'"); + + if (isset($data['custom_field_value'])) { + foreach ($data['custom_field_value'] as $custom_field_value) { + if ($custom_field_value['custom_field_value_id']) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "custom_field_value` SET `custom_field_value_id` = '" . (int)$custom_field_value['custom_field_value_id'] . "', `custom_field_id` = '" . (int)$custom_field_id . "', `sort_order` = '" . (int)$custom_field_value['sort_order'] . "'"); + } else { + $this->db->query("INSERT INTO `" . DB_PREFIX . "custom_field_value` SET `custom_field_id` = '" . (int)$custom_field_id . "', `sort_order` = '" . (int)$custom_field_value['sort_order'] . "'"); + } + + $custom_field_value_id = $this->db->getLastId(); + + foreach ($custom_field_value['custom_field_value_description'] as $language_id => $custom_field_value_description) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "custom_field_value_description` SET `custom_field_value_id` = '" . (int)$custom_field_value_id . "', `language_id` = '" . (int)$language_id . "', `custom_field_id` = '" . (int)$custom_field_id . "', `name` = '" . $this->db->escape($custom_field_value_description['name']) . "'"); + } + } + } + } + + /** + * @param int $custom_field_id + * + * @return void + */ + public function deleteCustomField(int $custom_field_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "custom_field` WHERE `custom_field_id` = '" . (int)$custom_field_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "custom_field_description` WHERE `custom_field_id` = '" . (int)$custom_field_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "custom_field_customer_group` WHERE `custom_field_id` = '" . (int)$custom_field_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "custom_field_value` WHERE `custom_field_id` = '" . (int)$custom_field_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "custom_field_value_description` WHERE `custom_field_id` = '" . (int)$custom_field_id . "'"); + } + + /** + * @param int $custom_field_id + * + * @return array + */ + public function getCustomField(int $custom_field_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "custom_field` cf LEFT JOIN `" . DB_PREFIX . "custom_field_description` cfd ON (cf.`custom_field_id` = cfd.`custom_field_id`) WHERE cf.`custom_field_id` = '" . (int)$custom_field_id . "' AND cfd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getCustomFields(array $data = []): array { + if (empty($data['filter_customer_group_id'])) { + $sql = "SELECT * FROM `" . DB_PREFIX . "custom_field` cf LEFT JOIN `" . DB_PREFIX . "custom_field_description` cfd ON (cf.`custom_field_id` = cfd.`custom_field_id`) WHERE cfd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"; + } else { + $sql = "SELECT * FROM `" . DB_PREFIX . "custom_field_customer_group` cfcg LEFT JOIN `" . DB_PREFIX . "custom_field` cf ON (cfcg.`custom_field_id` = cf.`custom_field_id`) LEFT JOIN `" . DB_PREFIX . "custom_field_description` cfd ON (cf.`custom_field_id` = cfd.`custom_field_id`) WHERE cfd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"; + } + + if (!empty($data['filter_name'])) { + $sql .= " AND cfd.`name` LIKE '" . $this->db->escape((string)$data['filter_name'] . '%') . "'"; + } + + if (isset($data['filter_status'])) { + $sql .= " AND cf.`status` = '" . (int)$data['filter_status'] . "'"; + } + + if (isset($data['filter_location'])) { + $sql .= " AND cf.`location` = '" . $this->db->escape((string)$data['filter_location']) . "'"; + } + + if (!empty($data['filter_customer_group_id'])) { + $sql .= " AND cfcg.`customer_group_id` = '" . (int)$data['filter_customer_group_id'] . "'"; + } + + $sort_data = [ + 'cfd.name', + 'cf.type', + 'cf.location', + 'cf.status', + 'cf.sort_order' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY cfd.`name`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param int $custom_field_id + * + * @return array + */ + public function getDescriptions(int $custom_field_id): array { + $custom_field_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "custom_field_description` WHERE `custom_field_id` = '" . (int)$custom_field_id . "'"); + + foreach ($query->rows as $result) { + $custom_field_data[$result['language_id']] = ['name' => $result['name']]; + } + + return $custom_field_data; + } + + /** + * @param int $custom_field_value_id + * + * @return array + */ + public function getValue(int $custom_field_value_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "custom_field_value` cfv LEFT JOIN `" . DB_PREFIX . "custom_field_value_description` cfvd ON (cfv.`custom_field_value_id` = cfvd.`custom_field_value_id`) WHERE cfv.`custom_field_value_id` = '" . (int)$custom_field_value_id . "' AND cfvd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return $query->row; + } + + /** + * @param int $custom_field_id + * + * @return array + */ + public function getValues(int $custom_field_id): array { + $custom_field_value_data = []; + + $custom_field_value_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "custom_field_value` cfv LEFT JOIN `" . DB_PREFIX . "custom_field_value_description` cfvd ON (cfv.`custom_field_value_id` = cfvd.`custom_field_value_id`) WHERE cfv.`custom_field_id` = '" . (int)$custom_field_id . "' AND cfvd.`language_id` = '" . (int)$this->config->get('config_language_id') . "' ORDER BY cfv.`sort_order` ASC"); + + foreach ($custom_field_value_query->rows as $custom_field_value) { + $custom_field_value_data[$custom_field_value['custom_field_value_id']] = [ + 'custom_field_value_id' => $custom_field_value['custom_field_value_id'], + 'name' => $custom_field_value['name'] + ]; + } + + return $custom_field_value_data; + } + + /** + * @param int $custom_field_id + * + * @return array + */ + public function getCustomerGroups(int $custom_field_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "custom_field_customer_group` WHERE `custom_field_id` = '" . (int)$custom_field_id . "'"); + + return $query->rows; + } + + /** + * @param int $custom_field_id + * + * @return array + */ + public function getValueDescriptions(int $custom_field_id): array { + $custom_field_value_data = []; + + $custom_field_value_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "custom_field_value` WHERE `custom_field_id` = '" . (int)$custom_field_id . "'"); + + foreach ($custom_field_value_query->rows as $custom_field_value) { + $custom_field_value_description_data = []; + + $custom_field_value_description_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "custom_field_value_description` WHERE `custom_field_value_id` = '" . (int)$custom_field_value['custom_field_value_id'] . "'"); + + foreach ($custom_field_value_description_query->rows as $custom_field_value_description) { + $custom_field_value_description_data[$custom_field_value_description['language_id']] = ['name' => $custom_field_value_description['name']]; + } + + $custom_field_value_data[] = [ + 'custom_field_value_id' => $custom_field_value['custom_field_value_id'], + 'custom_field_value_description' => $custom_field_value_description_data, + 'sort_order' => $custom_field_value['sort_order'] + ]; + } + + return $custom_field_value_data; + } + + /** + * @return int + */ + public function getTotalCustomFields(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "custom_field`"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/customer/customer.php b/admininistrator/model/customer/customer.php new file mode 100644 index 0000000..ce68670 --- /dev/null +++ b/admininistrator/model/customer/customer.php @@ -0,0 +1,613 @@ +db->query("INSERT INTO `" . DB_PREFIX . "customer` SET `store_id` = '" . (int)$data['store_id'] . "', `customer_group_id` = '" . (int)$data['customer_group_id'] . "', `firstname` = '" . $this->db->escape((string)$data['firstname']) . "', `lastname` = '" . $this->db->escape((string)$data['lastname']) . "', `email` = '" . $this->db->escape((string)$data['email']) . "', `telephone` = '" . $this->db->escape((string)$data['telephone']) . "', `custom_field` = '" . $this->db->escape(isset($data['custom_field']) ? json_encode($data['custom_field']) : json_encode([])) . "', `newsletter` = '" . (isset($data['newsletter']) ? (bool)$data['newsletter'] : 0) . "', `password` = '" . $this->db->escape(password_hash(html_entity_decode($data['password'], ENT_QUOTES, 'UTF-8'), PASSWORD_DEFAULT)) . "', `status` = '" . (isset($data['status']) ? (bool)$data['status'] : 0) . "', `safe` = '" . (isset($data['safe']) ? (bool)$data['safe'] : 0) . "', `date_added` = NOW()"); + + $customer_id = $this->db->getLastId(); + + if (isset($data['address'])) { + foreach ($data['address'] as $address) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "address` SET `customer_id` = '" . (int)$customer_id . "', `firstname` = '" . $this->db->escape($address['firstname']) . "', `lastname` = '" . $this->db->escape($address['lastname']) . "', `company` = '" . $this->db->escape($address['company']) . "', `address_1` = '" . $this->db->escape($address['address_1']) . "', `address_2` = '" . $this->db->escape($address['address_2']) . "', `city` = '" . $this->db->escape($address['city']) . "', `postcode` = '" . $this->db->escape($address['postcode']) . "', `country_id` = '" . (int)$address['country_id'] . "', `zone_id` = '" . (int)$address['zone_id'] . "', `custom_field` = '" . $this->db->escape(isset($address['custom_field']) ? json_encode($address['custom_field']) : json_encode([])) . "', `default` = '" . (isset($address['default']) ? (int)$address['default'] : 0) . "'"); + } + } + + return $customer_id; + } + + /** + * @param int $customer_id + * @param array $data + * + * @return void + */ + public function editCustomer(int $customer_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "customer` SET `store_id` = '" . (int)$data['store_id'] . "', `customer_group_id` = '" . (int)$data['customer_group_id'] . "', `firstname` = '" . $this->db->escape((string)$data['firstname']) . "', `lastname` = '" . $this->db->escape((string)$data['lastname']) . "', `email` = '" . $this->db->escape((string)$data['email']) . "', `telephone` = '" . $this->db->escape((string)$data['telephone']) . "', `custom_field` = '" . $this->db->escape(isset($data['custom_field']) ? json_encode($data['custom_field']) : json_encode([])) . "', `newsletter` = '" . (isset($data['newsletter']) ? (bool)$data['newsletter'] : 0) . "', `status` = '" . (isset($data['status']) ? (bool)$data['status'] : 0) . "', `safe` = '" . (isset($data['safe']) ? (bool)$data['safe'] : 0) . "' WHERE `customer_id` = '" . (int)$customer_id . "'"); + + if ($data['password']) { + $this->db->query("UPDATE `" . DB_PREFIX . "customer` SET `password` = '" . $this->db->escape(password_hash(html_entity_decode($data['password'], ENT_QUOTES, 'UTF-8'), PASSWORD_DEFAULT)) . "' WHERE `customer_id` = '" . (int)$customer_id . "'"); + } + + $this->db->query("DELETE FROM `" . DB_PREFIX . "address` WHERE `customer_id` = '" . (int)$customer_id . "'"); + + if (isset($data['address'])) { + foreach ($data['address'] as $address) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "address` SET `address_id` = '" . (int)$address['address_id'] . "', `customer_id` = '" . (int)$customer_id . "', `firstname` = '" . $this->db->escape($address['firstname']) . "', `lastname` = '" . $this->db->escape($address['lastname']) . "', `company` = '" . $this->db->escape($address['company']) . "', `address_1` = '" . $this->db->escape($address['address_1']) . "', `address_2` = '" . $this->db->escape($address['address_2']) . "', `city` = '" . $this->db->escape($address['city']) . "', `postcode` = '" . $this->db->escape($address['postcode']) . "', `country_id` = '" . (int)$address['country_id'] . "', `zone_id` = '" . (int)$address['zone_id'] . "', `custom_field` = '" . $this->db->escape(isset($address['custom_field']) ? json_encode($address['custom_field']) : json_encode([])) . "', `default` = '" . (isset($address['default']) ? (int)$address['default'] : 0) . "'"); + } + } + } + + /** + * @param int $customer_id + * @param string $token + * + * @return void + */ + public function editToken(int $customer_id, string $token): void { + $this->db->query("UPDATE `" . DB_PREFIX . "customer` SET `token` = '" . $this->db->escape($token) . "' WHERE `customer_id` = '" . (int)$customer_id . "'"); + } + + /** + * @param int $customer_id + * + * @return void + */ + public function deleteCustomer(int $customer_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer` WHERE `customer_id` = '" . (int)$customer_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_activity` WHERE `customer_id` = '" . (int)$customer_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_affiliate` WHERE `customer_id` = '" . (int)$customer_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_affiliate_report` WHERE `customer_id` = '" . (int)$customer_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_approval` WHERE `customer_id` = '" . (int)$customer_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_history` WHERE `customer_id` = '" . (int)$customer_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_reward` WHERE `customer_id` = '" . (int)$customer_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_transaction` WHERE `customer_id` = '" . (int)$customer_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_wishlist` WHERE `customer_id` = '" . (int)$customer_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_ip` WHERE `customer_id` = '" . (int)$customer_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "address` WHERE `customer_id` = '" . (int)$customer_id . "'"); + } + + /** + * @param int $customer_id + * + * @return array + */ + public function getCustomer(int $customer_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "customer` WHERE `customer_id` = '" . (int)$customer_id . "'"); + + return $query->row; + } + + /** + * @param string $email + * + * @return array + */ + public function getCustomerByEmail(string $email): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "customer` WHERE LCASE(`email`) = '" . $this->db->escape(oc_strtolower($email)) . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getCustomers(array $data = []): array { + $sql = "SELECT *, CONCAT(c.`firstname`, ' ', c.`lastname`) AS `name`, cgd.`name` AS `customer_group` FROM `" . DB_PREFIX . "customer` c LEFT JOIN `" . DB_PREFIX . "customer_group_description` cgd ON (c.`customer_group_id` = cgd.`customer_group_id`)"; + + $sql .= " WHERE cgd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"; + + if (!empty($data['filter_name'])) { + $sql .= " AND CONCAT(c.`firstname`, ' ', c.`lastname`) LIKE '" . $this->db->escape('%' . (string)$data['filter_name'] . '%') . "'"; + } + + if (!empty($data['filter_email'])) { + $sql .= " AND c.`email` LIKE '" . $this->db->escape((string)$data['filter_email'] . '%') . "'"; + } + + if (isset($data['filter_newsletter']) && $data['filter_newsletter'] !== '') { + $sql .= " AND c.`newsletter` = '" . (int)$data['filter_newsletter'] . "'"; + } + + if (!empty($data['filter_customer_group_id'])) { + $sql .= " AND c.`customer_group_id` = '" . (int)$data['filter_customer_group_id'] . "'"; + } + + if (!empty($data['filter_ip'])) { + $sql .= " AND c.`customer_id` IN (SELECT `customer_id` FROM `" . DB_PREFIX . "customer_ip` WHERE `ip` = '" . $this->db->escape((string)$data['filter_ip']) . "')"; + } + + if (isset($data['filter_status']) && $data['filter_status'] !== '') { + $sql .= " AND c.`status` = '" . (int)$data['filter_status'] . "'"; + } + + if (!empty($data['filter_date_from'])) { + $sql .= " AND DATE(c.`date_added`) >= DATE('" . $this->db->escape((string)$data['filter_date_from']) . "')"; + } + + if (!empty($data['filter_date_to'])) { + $sql .= " AND DATE(c.`date_added`) <= DATE('" . $this->db->escape((string)$data['filter_date_to']) . "')"; + } + + $sort_data = [ + 'name', + 'c.email', + 'customer_group', + 'c.status', + 'c.ip', + 'c.date_added' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY name"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param array $data + * + * @return int + */ + public function getTotalCustomers(array $data = []): int { + $sql = "SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "customer` c"; + + $implode = []; + + if (!empty($data['filter_name'])) { + $implode[] = "CONCAT(c.`firstname`, ' ', c.`lastname`) LIKE '" . $this->db->escape('%' . (string)$data['filter_name'] . '%') . "'"; + } + + if (!empty($data['filter_email'])) { + $implode[] = "c.`email` LIKE '" . $this->db->escape((string)$data['filter_email'] . '%') . "'"; + } + + if (isset($data['filter_newsletter']) && $data['filter_newsletter'] !== '') { + $implode[] = "c.`newsletter` = '" . (int)$data['filter_newsletter'] . "'"; + } + + if (!empty($data['filter_customer_group_id'])) { + $implode[] = "c.`customer_group_id` = '" . (int)$data['filter_customer_group_id'] . "'"; + } + + if (!empty($data['filter_ip'])) { + $implode[] = "c.`customer_id` IN (SELECT `customer_id` FROM " . DB_PREFIX . "customer_ip WHERE `ip` = '" . $this->db->escape((string)$data['filter_ip']) . "')"; + } + + if (isset($data['filter_status']) && $data['filter_status'] !== '') { + $implode[] = "c.`status` = '" . (int)$data['filter_status'] . "'"; + } + + if (!empty($data['filter_date_from'])) { + $implode[] = "DATE(c.`date_added`) >= DATE('" . $this->db->escape((string)$data['filter_date_from']) . "')"; + } + + if (!empty($data['filter_date_to'])) { + $implode[] = "DATE(c.`date_added`) <= DATE('" . $this->db->escape((string)$data['filter_date_to']) . "')"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $query = $this->db->query($sql); + + return (int)$query->row['total']; + } + + /** + * @param int $address_id + * + * @return array + */ + public function getAddress(int $address_id): array { + $address_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "address` WHERE `address_id` = '" . (int)$address_id . "'"); + + if ($address_query->num_rows) { + $country_query = $this->db->query("SELECT *, c.name FROM `" . DB_PREFIX . "country` c LEFT JOIN `" . DB_PREFIX . "address_format` af ON (c.`address_format_id` = af.`address_format_id`) WHERE `country_id` = '" . (int)$address_query->row['country_id'] . "'"); + + if ($country_query->num_rows) { + $country = $country_query->row['name']; + $iso_code_2 = $country_query->row['iso_code_2']; + $iso_code_3 = $country_query->row['iso_code_3']; + $address_format = $country_query->row['address_format']; + } else { + $country = ''; + $iso_code_2 = ''; + $iso_code_3 = ''; + $address_format = ''; + } + + $zone_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "zone` WHERE `zone_id` = '" . (int)$address_query->row['zone_id'] . "'"); + + if ($zone_query->num_rows) { + $zone = $zone_query->row['name']; + $zone_code = $zone_query->row['code']; + } else { + $zone = ''; + $zone_code = ''; + } + + return [ + 'address_id' => $address_query->row['address_id'], + 'customer_id' => $address_query->row['customer_id'], + 'firstname' => $address_query->row['firstname'], + 'lastname' => $address_query->row['lastname'], + 'company' => $address_query->row['company'], + 'address_1' => $address_query->row['address_1'], + 'address_2' => $address_query->row['address_2'], + 'postcode' => $address_query->row['postcode'], + 'city' => $address_query->row['city'], + 'zone_id' => $address_query->row['zone_id'], + 'zone' => $zone, + 'zone_code' => $zone_code, + 'country_id' => $address_query->row['country_id'], + 'country' => $country, + 'iso_code_2' => $iso_code_2, + 'iso_code_3' => $iso_code_3, + 'address_format' => $address_format, + 'custom_field' => json_decode($address_query->row['custom_field'], true), + 'default' => $address_query->row['default'] + ]; + } + + return []; + } + + /** + * @param int $customer_id + * + * @return array + */ + public function getAddresses(int $customer_id): array { + $address_data = []; + + $query = $this->db->query("SELECT `address_id` FROM `" . DB_PREFIX . "address` WHERE `customer_id` = '" . (int)$customer_id . "'"); + + foreach ($query->rows as $result) { + $address_info = $this->getAddress($result['address_id']); + + if ($address_info) { + $address_data[] = $address_info; + } + } + + return $address_data; + } + + /** + * @param int $customer_id + * + * @return int + */ + public function getTotalAddressesByCustomerId(int $customer_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "address` WHERE `customer_id` = '" . (int)$customer_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $country_id + * + * @return int + */ + public function getTotalAddressesByCountryId(int $country_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "address` WHERE `country_id` = '" . (int)$country_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $zone_id + * + * @return int + */ + public function getTotalAddressesByZoneId(int $zone_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "address` WHERE `zone_id` = '" . (int)$zone_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $customer_group_id + * + * @return int + */ + public function getTotalCustomersByCustomerGroupId(int $customer_group_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "customer` WHERE `customer_group_id` = '" . (int)$customer_group_id . "'"); + + if ($query->num_rows) { + return (int)$query->row['total']; + } else { + return 0; + } + } + + /** + * @param int $customer_id + * @param string $comment + * + * @return void + */ + public function addHistory(int $customer_id, string $comment): void { + $this->db->query("INSERT INTO `" . DB_PREFIX . "customer_history` SET `customer_id` = '" . (int)$customer_id . "', `comment` = '" . $this->db->escape(strip_tags($comment)) . "', `date_added` = NOW()"); + } + + /** + * @param int $customer_id + * @param int $start + * @param int $limit + * + * @return array + */ + public function getHistories(int $customer_id, int $start = 0, int $limit = 10): array { + if ($start < 0) { + $start = 0; + } + + if ($limit < 1) { + $limit = 10; + } + + $query = $this->db->query("SELECT `comment`, `date_added` FROM `" . DB_PREFIX . "customer_history` WHERE `customer_id` = '" . (int)$customer_id . "' ORDER BY `date_added` DESC LIMIT " . (int)$start . "," . (int)$limit); + + return $query->rows; + } + + /** + * @param int $customer_id + * + * @return int + */ + public function getTotalHistories(int $customer_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "customer_history` WHERE `customer_id` = '" . (int)$customer_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $customer_id + * @param string $description + * @param float $amount + * @param int $order_id + * + * @return void + */ + public function addTransaction(int $customer_id, string $description = '', float $amount = 0, int $order_id = 0): void { + $this->db->query("INSERT INTO `" . DB_PREFIX . "customer_transaction` SET `customer_id` = '" . (int)$customer_id . "', `order_id` = '" . (int)$order_id . "', `description` = '" . $this->db->escape($description) . "', `amount` = '" . (float)$amount . "', `date_added` = NOW()"); + } + + /** + * @param int $order_id + * + * @return void + */ + public function deleteTransactionByOrderId(int $order_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_transaction` WHERE `order_id` = '" . (int)$order_id . "'"); + } + + /** + * @param int $customer_id + * @param int $start + * @param int $limit + * + * @return array + */ + public function getTransactions(int $customer_id, int $start = 0, int $limit = 10): array { + if ($start < 0) { + $start = 0; + } + + if ($limit < 1) { + $limit = 10; + } + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "customer_transaction` WHERE `customer_id` = '" . (int)$customer_id . "' ORDER BY `date_added` DESC LIMIT " . (int)$start . "," . (int)$limit); + + return $query->rows; + } + + /** + * @param int $customer_id + * + * @return int + */ + public function getTotalTransactions(int $customer_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "customer_transaction` WHERE `customer_id` = '" . (int)$customer_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $customer_id + * + * @return float + */ + public function getTransactionTotal(int $customer_id): float { + $query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "customer_transaction` WHERE `customer_id` = '" . (int)$customer_id . "'"); + + return (float)$query->row['total']; + } + + /** + * @param int $order_id + * + * @return int + */ + public function getTotalTransactionsByOrderId(int $order_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "customer_transaction` WHERE `order_id` = '" . (int)$order_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $customer_id + * @param string $description + * @param int $points + * @param int $order_id + * + * @return void + */ + public function addReward(int $customer_id, string $description = '', int $points = 0, int $order_id = 0): void { + $this->db->query("INSERT INTO `" . DB_PREFIX . "customer_reward` SET `customer_id` = '" . (int)$customer_id . "', `order_id` = '" . (int)$order_id . "', `points` = '" . (int)$points . "', `description` = '" . $this->db->escape($description) . "', `date_added` = NOW()"); + } + + /** + * @param int $order_id + * + * @return void + */ + public function deleteReward(int $order_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_reward` WHERE `order_id` = '" . (int)$order_id . "' AND `points` > '0'"); + } + + /** + * @param int $customer_id + * @param int $start + * @param int $limit + * + * @return array + */ + public function getRewards(int $customer_id, int $start = 0, int $limit = 10): array { + if ($start < 0) { + $start = 0; + } + + if ($limit < 1) { + $limit = 10; + } + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "customer_reward` WHERE `customer_id` = '" . (int)$customer_id . "' ORDER BY `date_added` DESC LIMIT " . (int)$start . "," . (int)$limit); + + return $query->rows; + } + + /** + * @param int $customer_id + * + * @return int + */ + public function getTotalRewards(int $customer_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "customer_reward` WHERE `customer_id` = '" . (int)$customer_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $customer_id + * + * @return int + */ + public function getRewardTotal(int $customer_id): int { + $query = $this->db->query("SELECT SUM(points) AS `total` FROM `" . DB_PREFIX . "customer_reward` WHERE `customer_id` = '" . (int)$customer_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $order_id + * + * @return int + */ + public function getTotalRewardsByOrderId(int $order_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "customer_reward` WHERE `order_id` = '" . (int)$order_id . "' AND `points` > '0'"); + + return (int)$query->row['total']; + } + + /** + * @param int $customer_id + * @param int $start + * @param int $limit + * + * @return array + */ + public function getIps(int $customer_id, int $start = 0, int $limit = 10): array { + if ($start < 0) { + $start = 0; + } + if ($limit < 1) { + $limit = 10; + } + + $query = $this->db->query("SELECT `ip`, `store_id`, `country`, `date_added` FROM `" . DB_PREFIX . "customer_ip` WHERE `customer_id` = '" . (int)$customer_id . "' ORDER BY `date_added` DESC LIMIT " . (int)$start . "," . (int)$limit); + + return $query->rows; + } + + /** + * @param int $customer_id + * + * @return int + */ + public function getTotalIps(int $customer_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "customer_ip` WHERE `customer_id` = '" . (int)$customer_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param string $ip + * + * @return int + */ + public function getTotalCustomersByIp(string $ip): int { + $query = $this->db->query("SELECT COUNT(DISTINCT `customer_id`) AS `total` FROM `" . DB_PREFIX . "customer_ip` WHERE `ip` = '" . $this->db->escape($ip) . "'"); + + return (int)$query->row['total']; + } + + /** + * @param string $email + * + * @return array + */ + public function getTotalLoginAttempts(string $email): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "customer_login` WHERE `email` = '" . $this->db->escape(oc_strtolower($email)) . "'"); + + return $query->row; + } + + /** + * @param string $email + * + * @return void + */ + public function deleteLoginAttempts(string $email): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_login` WHERE `email` = '" . $this->db->escape(oc_strtolower($email)) . "'"); + } +} diff --git a/admininistrator/model/customer/customer_approval.php b/admininistrator/model/customer/customer_approval.php new file mode 100644 index 0000000..83c1543 --- /dev/null +++ b/admininistrator/model/customer/customer_approval.php @@ -0,0 +1,151 @@ +config->get('config_language_id') . "'"; + + if (!empty($data['filter_customer'])) { + $sql .= " AND CONCAT(c.`firstname`, ' ', c.`lastname`) LIKE '" . $this->db->escape('%' . (string)$data['filter_customer'] . '%') . "'"; + } + + if (!empty($data['filter_email'])) { + $sql .= " AND c.`email` LIKE '" . $this->db->escape((string)$data['filter_email'] . '%') . "'"; + } + + if (!empty($data['filter_customer_group_id'])) { + $sql .= " AND c.`customer_group_id` = '" . (int)$data['filter_customer_group_id'] . "'"; + } + + if (!empty($data['filter_type'])) { + $sql .= " AND ca.`type` = '" . $this->db->escape((string)$data['filter_type']) . "'"; + } + + if (!empty($data['filter_date_from'])) { + $sql .= " AND DATE(c.`date_added`) >= DATE('" . $this->db->escape((string)$data['filter_date_from']) . "')"; + } + + if (!empty($data['filter_date_to'])) { + $sql .= " AND DATE(c.`date_added`) <= DATE('" . $this->db->escape((string)$data['filter_date_to']) . "')"; + } + + $sql .= " ORDER BY c.`date_added` DESC"; + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param int $customer_approval_id + * + * @return array + */ + public function getCustomerApproval(int $customer_approval_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "customer_approval` WHERE `customer_approval_id` = '" . (int)$customer_approval_id . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return int + */ + public function getTotalCustomerApprovals(array $data = []): int { + $sql = "SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "customer_approval` ca LEFT JOIN `" . DB_PREFIX . "customer` c ON (ca.`customer_id` = c.`customer_id`)"; + + $implode = []; + + if (!empty($data['filter_customer'])) { + $implode[] = "CONCAT(c.`firstname`, ' ', c.`lastname`) LIKE '" . $this->db->escape('%' . (string)$data['filter_customer'] . '%') . "'"; + } + + if (!empty($data['filter_email'])) { + $implode[] = "c.`email` LIKE '" . $this->db->escape((string)$data['filter_email'] . '%') . "'"; + } + + if (!empty($data['filter_customer_group_id'])) { + $implode[] = "c.`customer_group_id` = '" . (int)$data['filter_customer_group_id'] . "'"; + } + + if (!empty($data['filter_type'])) { + $implode[] = "ca.`type` = '" . $this->db->escape((string)$data['filter_type']) . "'"; + } + + if (!empty($data['filter_date_from'])) { + $implode[] = "DATE(c.`date_added`) >= DATE('" . $this->db->escape((string)$data['filter_date_from']) . "')"; + } + + if (!empty($data['filter_date_to'])) { + $implode[] = "DATE(c.`date_added`) <= DATE('" . $this->db->escape((string)$data['filter_date_to']) . "')"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $query = $this->db->query($sql); + + return (int)$query->row['total']; + } + + /** + * @param int $customer_id + * + * @return void + */ + public function approveCustomer(int $customer_id): void { + $this->db->query("UPDATE `" . DB_PREFIX . "customer` SET `status` = '1' WHERE `customer_id` = '" . (int)$customer_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_approval` WHERE `customer_id` = '" . (int)$customer_id . "' AND `type` = 'customer'"); + } + + /** + * @param int $customer_id + * + * @return void + */ + public function denyCustomer(int $customer_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_approval` WHERE `customer_id` = '" . (int)$customer_id . "' AND `type` = 'customer'"); + } + + /** + * @param int $customer_id + * + * @return void + */ + public function approveAffiliate(int $customer_id): void { + $this->db->query("UPDATE `" . DB_PREFIX . "customer_affiliate` SET `status` = '1' WHERE `customer_id` = '" . (int)$customer_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_approval` WHERE `customer_id` = '" . (int)$customer_id . "' AND `type` = 'affiliate'"); + } + + /** + * @param int $customer_id + * + * @return void + */ + public function denyAffiliate(int $customer_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_approval` WHERE `customer_id` = '" . (int)$customer_id . "' AND `type` = 'affiliate'"); + } +} diff --git a/admininistrator/model/customer/customer_group.php b/admininistrator/model/customer/customer_group.php new file mode 100644 index 0000000..5cb5900 --- /dev/null +++ b/admininistrator/model/customer/customer_group.php @@ -0,0 +1,137 @@ +db->query("INSERT INTO `" . DB_PREFIX . "customer_group` SET `approval` = '" . (isset($data['approval']) ? (bool)$data['approval'] : 0) . "', `sort_order` = '" . (int)$data['sort_order'] . "'"); + + $customer_group_id = $this->db->getLastId(); + + foreach ($data['customer_group_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "customer_group_description` SET `customer_group_id` = '" . (int)$customer_group_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "', `description` = '" . $this->db->escape($value['description']) . "'"); + } + + return $customer_group_id; + } + + /** + * @param int $customer_group_id + * @param array $data + * + * @return void + */ + public function editCustomerGroup(int $customer_group_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "customer_group` SET `approval` = '" . (isset($data['approval']) ? (bool)$data['approval'] : 0) . "', `sort_order` = '" . (int)$data['sort_order'] . "' WHERE `customer_group_id` = '" . (int)$customer_group_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_group_description` WHERE `customer_group_id` = '" . (int)$customer_group_id . "'"); + + foreach ($data['customer_group_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "customer_group_description` SET `customer_group_id` = '" . (int)$customer_group_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "', `description` = '" . $this->db->escape($value['description']) . "'"); + } + } + + /** + * @param int $customer_group_id + * + * @return void + */ + public function deleteCustomerGroup(int $customer_group_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_group` WHERE `customer_group_id` = '" . (int)$customer_group_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_group_description` WHERE `customer_group_id` = '" . (int)$customer_group_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_discount` WHERE `customer_group_id` = '" . (int)$customer_group_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_special` WHERE `customer_group_id` = '" . (int)$customer_group_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_reward` WHERE `customer_group_id` = '" . (int)$customer_group_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "tax_rate_to_customer_group` WHERE `customer_group_id` = '" . (int)$customer_group_id . "'"); + } + + /** + * @param int $customer_group_id + * + * @return array + */ + public function getCustomerGroup(int $customer_group_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "customer_group` cg LEFT JOIN `" . DB_PREFIX . "customer_group_description` cgd ON (cg.`customer_group_id` = cgd.`customer_group_id`) WHERE cg.`customer_group_id` = '" . (int)$customer_group_id . "' AND cgd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getCustomerGroups(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "customer_group` cg LEFT JOIN `" . DB_PREFIX . "customer_group_description` cgd ON (cg.`customer_group_id` = cgd.`customer_group_id`) WHERE cgd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"; + + $sort_data = [ + 'cgd.name', + 'cg.sort_order' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY cgd.`name`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param int $customer_group_id + * + * @return array + */ + public function getDescriptions(int $customer_group_id): array { + $customer_group_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "customer_group_description` WHERE `customer_group_id` = '" . (int)$customer_group_id . "'"); + + foreach ($query->rows as $result) { + $customer_group_data[$result['language_id']] = [ + 'name' => $result['name'], + 'description' => $result['description'] + ]; + } + + return $customer_group_data; + } + + /** + * @return int + */ + public function getTotalCustomerGroups(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "customer_group`"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/customer/gdpr.php b/admininistrator/model/customer/gdpr.php new file mode 100644 index 0000000..8db2c58 --- /dev/null +++ b/admininistrator/model/customer/gdpr.php @@ -0,0 +1,139 @@ +db->query("UPDATE `" . DB_PREFIX . "gdpr` SET `status` = '" . (int)$status . "' WHERE `gdpr_id` = '" . (int)$gdpr_id . "'"); + } + + /** + * @param int $gdpr_id + * + * @return void + */ + public function deleteGdpr(int $gdpr_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "gdpr` WHERE `gdpr_id` = '" . (int)$gdpr_id . "'"); + } + + /** + * @param array $data + * + * @return array + */ + public function getGdprs(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "gdpr`"; + + $implode = []; + + if (!empty($data['filter_email'])) { + $implode[] = "`email` LIKE '" . $this->db->escape((string)$data['filter_email']) . "'"; + } + + if (!empty($data['filter_action'])) { + $implode[] = "`action` = '" . $this->db->escape((string)$data['filter_action']) . "'"; + } + + if (isset($data['filter_status']) && $data['filter_status'] !== '') { + $implode[] = "`status` = '" . (int)$data['filter_status'] . "'"; + } + + if (!empty($data['filter_date_from'])) { + $implode[] = "DATE(`date_added`) >= DATE('" . $this->db->escape((string)$data['filter_date_from']) . "')"; + } + + if (!empty($data['filter_date_to'])) { + $implode[] = "DATE(`date_added`) <= DATE('" . $this->db->escape((string)$data['filter_date_to']) . "')"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $sql .= " ORDER BY `date_added` DESC"; + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param int $gdpr_id + * + * @return array + */ + public function getGdpr(int $gdpr_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "gdpr` WHERE `gdpr_id` = '" . (int)$gdpr_id . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return int + */ + public function getTotalGdprs(array $data = []): int { + $sql = "SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "gdpr`"; + + $implode = []; + + if (!empty($data['filter_email'])) { + $implode[] = "`email` LIKE '" . $this->db->escape((string)$data['filter_email']) . "'"; + } + + if (!empty($data['filter_action'])) { + $implode[] = "`action` = '" . $this->db->escape((string)$data['filter_action']) . "'"; + } + + if (isset($data['filter_status']) && $data['filter_status'] !== '') { + $implode[] = "`status` = '" . (int)$data['filter_status'] . "'"; + } + + if (!empty($data['filter_date_from'])) { + $implode[] = "DATE(`date_added`) >= DATE('" . $this->db->escape((string)$data['filter_date_from']) . "')"; + } + + if (!empty($data['filter_date_to'])) { + $implode[] = "DATE(`date_added`) <= DATE('" . $this->db->escape((string)$data['filter_date_to']) . "')"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $query = $this->db->query($sql); + + return (int)$query->row['total']; + } + + /** + * @return array + */ + public function getExpires(): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "gdpr` WHERE `status` = '2' AND DATE(`date_added`) <= DATE('" . $this->db->escape(date('Y-m-d', strtotime('+' . (int)$this->config->get('config_gdpr_limit') . ' days'))) . "') ORDER BY `date_added` DESC"); + + return $query->rows; + } +} diff --git a/admininistrator/model/design/banner.php b/admininistrator/model/design/banner.php new file mode 100644 index 0000000..288cb2a --- /dev/null +++ b/admininistrator/model/design/banner.php @@ -0,0 +1,143 @@ +db->query("INSERT INTO `" . DB_PREFIX . "banner` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "'"); + + $banner_id = $this->db->getLastId(); + + if (isset($data['banner_image'])) { + foreach ($data['banner_image'] as $language_id => $value) { + foreach ($value as $banner_image) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "banner_image` SET `banner_id` = '" . (int)$banner_id . "', `language_id` = '" . (int)$language_id . "', `title` = '" . $this->db->escape($banner_image['title']) . "', `link` = '" . $this->db->escape($banner_image['link']) . "', `image` = '" . $this->db->escape($banner_image['image']) . "', `sort_order` = '" . (int)$banner_image['sort_order'] . "'"); + } + } + } + + return $banner_id; + } + + /** + * @param int $banner_id + * @param array $data + * + * @return void + */ + public function editBanner(int $banner_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "banner` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "' WHERE `banner_id` = '" . (int)$banner_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "banner_image` WHERE `banner_id` = '" . (int)$banner_id . "'"); + + if (isset($data['banner_image'])) { + foreach ($data['banner_image'] as $language_id => $value) { + foreach ($value as $banner_image) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "banner_image` SET `banner_id` = '" . (int)$banner_id . "', `language_id` = '" . (int)$language_id . "', `title` = '" . $this->db->escape($banner_image['title']) . "', `link` = '" . $this->db->escape($banner_image['link']) . "', `image` = '" . $this->db->escape($banner_image['image']) . "', `sort_order` = '" . (int)$banner_image['sort_order'] . "'"); + } + } + } + } + + /** + * @param int $banner_id + * + * @return void + */ + public function deleteBanner(int $banner_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "banner` WHERE `banner_id` = '" . (int)$banner_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "banner_image` WHERE `banner_id` = '" . (int)$banner_id . "'"); + } + + /** + * @param int $banner_id + * + * @return array + */ + public function getBanner(int $banner_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "banner` WHERE `banner_id` = '" . (int)$banner_id . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getBanners(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "banner`"; + + $sort_data = [ + 'name', + 'status' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `name`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param int $banner_id + * + * @return array + */ + public function getImages(int $banner_id): array { + $banner_image_data = []; + + $banner_image_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "banner_image` WHERE `banner_id` = '" . (int)$banner_id . "' ORDER BY `sort_order` ASC"); + + foreach ($banner_image_query->rows as $banner_image) { + $banner_image_data[$banner_image['language_id']][] = [ + 'title' => $banner_image['title'], + 'link' => $banner_image['link'], + 'image' => $banner_image['image'], + 'sort_order' => $banner_image['sort_order'] + ]; + } + + return $banner_image_data; + } + + /** + * @return int + */ + public function getTotalBanners(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "banner`"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/design/layout.php b/admininistrator/model/design/layout.php new file mode 100644 index 0000000..6f7b2f4 --- /dev/null +++ b/admininistrator/model/design/layout.php @@ -0,0 +1,156 @@ +db->query("INSERT INTO `" . DB_PREFIX . "layout` SET `name` = '" . $this->db->escape((string)$data['name']) . "'"); + + $layout_id = $this->db->getLastId(); + + if (isset($data['layout_route'])) { + foreach ($data['layout_route'] as $layout_route) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "layout_route` SET `layout_id` = '" . (int)$layout_id . "', `store_id` = '" . (int)$layout_route['store_id'] . "', `route` = '" . $this->db->escape($layout_route['route']) . "'"); + } + } + + if (isset($data['layout_module'])) { + foreach ($data['layout_module'] as $layout_module) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "layout_module` SET `layout_id` = '" . (int)$layout_id . "', `code` = '" . $this->db->escape($layout_module['code']) . "', `position` = '" . $this->db->escape($layout_module['position']) . "', `sort_order` = '" . (int)$layout_module['sort_order'] . "'"); + } + } + + return $layout_id; + } + + /** + * @param int $layout_id + * @param array $data + * + * @return void + */ + public function editLayout(int $layout_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "layout` SET `name` = '" . $this->db->escape((string)$data['name']) . "' WHERE `layout_id` = '" . (int)$layout_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "layout_route` WHERE `layout_id` = '" . (int)$layout_id . "'"); + + if (isset($data['layout_route'])) { + foreach ($data['layout_route'] as $layout_route) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "layout_route` SET `layout_id` = '" . (int)$layout_id . "', `store_id` = '" . (int)$layout_route['store_id'] . "', `route` = '" . $this->db->escape($layout_route['route']) . "'"); + } + } + + $this->db->query("DELETE FROM `" . DB_PREFIX . "layout_module` WHERE `layout_id` = '" . (int)$layout_id . "'"); + + if (isset($data['layout_module'])) { + foreach ($data['layout_module'] as $layout_module) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "layout_module` SET `layout_id` = '" . (int)$layout_id . "', `code` = '" . $this->db->escape($layout_module['code']) . "', `position` = '" . $this->db->escape($layout_module['position']) . "', `sort_order` = '" . (int)$layout_module['sort_order'] . "'"); + } + } + } + + /** + * @param int $layout_id + * + * @return void + */ + public function deleteLayout(int $layout_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "layout` WHERE `layout_id` = '" . (int)$layout_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "layout_route` WHERE `layout_id` = '" . (int)$layout_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "layout_module` WHERE `layout_id` = '" . (int)$layout_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "category_to_layout` WHERE `layout_id` = '" . (int)$layout_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_to_layout` WHERE `layout_id` = '" . (int)$layout_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "information_to_layout` WHERE `layout_id` = '" . (int)$layout_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "blog_to_layout` WHERE `layout_id` = '" . (int)$layout_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "blog_category_to_layout` WHERE `layout_id` = '" . (int)$layout_id . "'"); + } + + /** + * @param int $layout_id + * + * @return array + */ + public function getLayout(int $layout_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "layout` WHERE `layout_id` = '" . (int)$layout_id . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getLayouts(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "layout`"; + + $sort_data = ['name']; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `name`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param int $layout_id + * + * @return array + */ + public function getRoutes(int $layout_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "layout_route` WHERE `layout_id` = '" . (int)$layout_id . "'"); + + return $query->rows; + } + + /** + * @param int $layout_id + * + * @return array + */ + public function getModules(int $layout_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "layout_module` WHERE `layout_id` = '" . (int)$layout_id . "' ORDER BY `position` ASC, `sort_order` ASC"); + + return $query->rows; + } + + /** + * @return int + */ + public function getTotalLayouts(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "layout`"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/design/seo_url.php b/admininistrator/model/design/seo_url.php new file mode 100644 index 0000000..7c88d48 --- /dev/null +++ b/admininistrator/model/design/seo_url.php @@ -0,0 +1,193 @@ +db->query("INSERT INTO `" . DB_PREFIX . "seo_url` SET `store_id` = '" . (int)$data['store_id'] . "', `language_id` = '" . (int)$data['language_id'] . "', `key` = '" . $this->db->escape((string)$data['key']) . "', `value` = '" . $this->db->escape((string)$data['value']) . "', `keyword` = '" . $this->db->escape((string)$data['keyword']) . "', `sort_order` = '" . (int)$data['sort_order'] . "'"); + + return $this->db->getLastId(); + } + + /** + * @param int $seo_url_id + * @param array $data + * + * @return void + */ + public function editSeoUrl(int $seo_url_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "seo_url` SET `store_id` = '" . (int)$data['store_id'] . "', `language_id` = '" . (int)$data['language_id'] . "', `key` = '" . $this->db->escape((string)$data['key']) . "', `value` = '" . $this->db->escape((string)$data['value']) . "', `keyword` = '" . $this->db->escape((string)$data['keyword']) . "', `sort_order` = '" . (int)$data['sort_order'] . "' WHERE `seo_url_id` = '" . (int)$seo_url_id . "'"); + } + + /** + * @param int $seo_url_id + * + * @return void + */ + public function deleteSeoUrl(int $seo_url_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "seo_url` WHERE `seo_url_id` = '" . (int)$seo_url_id . "'"); + } + + /** + * @param int $seo_url_id + * + * @return array + */ + public function getSeoUrl(int $seo_url_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "seo_url` WHERE `seo_url_id` = '" . (int)$seo_url_id . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getSeoUrls(array $data = []): array { + $sql = "SELECT *, (SELECT `name` FROM `" . DB_PREFIX . "store` s WHERE s.`store_id` = su.`store_id`) AS `store`, (SELECT `name` FROM `" . DB_PREFIX . "language` l WHERE l.`language_id` = su.`language_id`) AS `language` FROM `" . DB_PREFIX . "seo_url` su"; + + $implode = []; + + if (!empty($data['filter_keyword'])) { + $implode[] = "`keyword` LIKE '" . $this->db->escape((string)$data['filter_keyword']) . "'"; + } + + if (!empty($data['filter_key'])) { + $implode[] = "`key` = '" . $this->db->escape((string)$data['filter_key']) . "'"; + } + + if (!empty($data['filter_value'])) { + $implode[] = "`value` LIKE '" . $this->db->escape((string)$data['filter_value']) . "'"; + } + + if (isset($data['filter_store_id']) && $data['filter_store_id'] !== '') { + $implode[] = "`store_id` = '" . (int)$data['filter_store_id'] . "'"; + } + + if (!empty($data['filter_language_id']) && $data['filter_language_id'] !== '') { + $implode[] = "`language_id` = '" . (int)$data['filter_language_id'] . "'"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $sort_data = [ + 'keyword', + 'key', + 'value', + 'sort_order', + 'store_id', + 'language_id' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY `" . $data['sort'] . "`"; + } else { + $sql .= " ORDER BY `key`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param array $data + * + * @return int + */ + public function getTotalSeoUrls(array $data = []): int { + $sql = "SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "seo_url`"; + + $implode = []; + + if (!empty($data['filter_keyword'])) { + $implode[] = "`keyword` LIKE '" . $this->db->escape((string)$data['filter_keyword']) . "'"; + } + + if (!empty($data['filter_key'])) { + $implode[] = "`key` = '" . $this->db->escape((string)$data['filter_key']) . "'"; + } + + if (!empty($data['filter_value'])) { + $implode[] = "`value` LIKE '" . $this->db->escape((string)$data['filter_value']) . "'"; + } + + if (!empty($data['filter_store_id']) && $data['filter_store_id'] !== '') { + $implode[] = "`store_id` = '" . (int)$data['filter_store_id'] . "'"; + } + + if (!empty($data['filter_language_id']) && $data['filter_language_id'] !== '') { + $implode[] = "`language_id` = '" . (int)$data['filter_language_id'] . "'"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $query = $this->db->query($sql); + + return (int)$query->row['total']; + } + + /** + * @param string $key + * @param string $value + * @param int $store_id + * @param int $language_id + * + * @return array + */ + public function getSeoUrlByKeyValue(string $key, string $value, int $store_id, int $language_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "seo_url` WHERE `key` = '" . $this->db->escape($key) . "' AND `value` = '" . $this->db->escape($value) . "' AND `store_id` = '" . (int)$store_id . "' AND `language_id` = '" . (int)$language_id . "'"); + + return $query->row; + } + + /** + * @param string $keyword + * @param int $store_id + * @param int $language_id + * + * @return array + */ + public function getSeoUrlByKeyword(string $keyword, int $store_id, int $language_id = 0): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "seo_url` WHERE (`keyword` = '" . $this->db->escape($keyword) . "' OR `keyword` LIKE '" . $this->db->escape('%/' . $keyword) . "') AND `store_id` = '" . (int)$store_id . "'"; + + if ($language_id) { + $sql .= " AND `language_id` = '" . (int)$language_id . "'"; + } + + $query = $this->db->query($sql); + + return $query->row; + } +} diff --git a/admininistrator/model/design/theme.php b/admininistrator/model/design/theme.php new file mode 100644 index 0000000..f789fa8 --- /dev/null +++ b/admininistrator/model/design/theme.php @@ -0,0 +1,71 @@ +db->query("DELETE FROM `" . DB_PREFIX . "theme` WHERE `store_id` = '" . (int)$store_id . "' AND `route` = '" . $this->db->escape($route) . "'"); + + $this->db->query("INSERT INTO `" . DB_PREFIX . "theme` SET `store_id` = '" . (int)$store_id . "', `route` = '" . $this->db->escape($route) . "', `code` = '" . $this->db->escape($code) . "', `date_added` = NOW()"); + } + + /** + * @param int $theme_id + * + * @return void + */ + public function deleteTheme(int $theme_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "theme` WHERE `theme_id` = '" . (int)$theme_id . "'"); + } + + /** + * @param int $store_id + * @param string $route + * + * @return array + */ + public function getTheme(int $store_id, string $route): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "theme` WHERE `store_id` = '" . (int)$store_id . "' AND `route` = '" . $this->db->escape($route) . "'"); + + return $query->row; + } + + /** + * @param int $start + * @param int $limit + * + * @return array + */ + public function getThemes(int $start = 0, int $limit = 10): array { + if ($start < 0) { + $start = 0; + } + + if ($limit < 1) { + $limit = 10; + } + + $query = $this->db->query("SELECT *, (SELECT `name` FROM `" . DB_PREFIX . "store` s WHERE s.`store_id` = t.`store_id`) AS `store` FROM `" . DB_PREFIX . "theme` t ORDER BY t.`date_added` DESC LIMIT " . (int)$start . "," . (int)$limit); + + return $query->rows; + } + + /** + * @return int + */ + public function getTotalThemes(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "theme`"); + + return (int)$query->row['total']; + } +} \ No newline at end of file diff --git a/admininistrator/model/design/translation.php b/admininistrator/model/design/translation.php new file mode 100644 index 0000000..6f7058a --- /dev/null +++ b/admininistrator/model/design/translation.php @@ -0,0 +1,101 @@ +db->query("INSERT INTO `" . DB_PREFIX . "translation` SET `store_id` = '" . (int)$data['store_id'] . "', `language_id` = '" . (int)$data['language_id'] . "', `route` = '" . $this->db->escape((string)$data['route']) . "', `key` = '" . $this->db->escape((string)$data['key']) . "', `value` = '" . $this->db->escape((string)$data['value']) . "', `date_added` = NOW()"); + } + + /** + * @param int $translation_id + * @param array $data + * + * @return void + */ + public function editTranslation(int $translation_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "translation` SET `store_id` = '" . (int)$data['store_id'] . "', `language_id` = '" . (int)$data['language_id'] . "', `route` = '" . $this->db->escape((string)$data['route']) . "', `key` = '" . $this->db->escape((string)$data['key']) . "', `value` = '" . $this->db->escape((string)$data['value']) . "' WHERE `translation_id` = '" . (int)$translation_id . "'"); + } + + /** + * @param int $translation_id + * + * @return void + */ + public function deleteTranslation(int $translation_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "translation` WHERE `translation_id` = '" . (int)$translation_id . "'"); + } + + /** + * @param int $translation_id + * + * @return array + */ + public function getTranslation(int $translation_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "translation` WHERE `translation_id` = '" . (int)$translation_id . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getTranslations(array $data = []): array { + $sql = "SELECT *, (SELECT s.`name` FROM `" . DB_PREFIX . "store` s WHERE s.`store_id` = t.`store_id`) AS store, (SELECT l.`name` FROM `" . DB_PREFIX . "language` l WHERE l.`language_id` = t.`language_id`) AS language FROM `" . DB_PREFIX . "translation` t"; + + $sort_data = [ + 'store', + 'language', + 'route', + 'key', + 'value' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY store"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @return int + */ + public function getTotalTranslations(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "translation`"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/localisation/address_format.php b/admininistrator/model/localisation/address_format.php new file mode 100644 index 0000000..17a9032 --- /dev/null +++ b/admininistrator/model/localisation/address_format.php @@ -0,0 +1,85 @@ +db->query("INSERT INTO `" . DB_PREFIX . "address_format` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `address_format` = '" . $this->db->escape((string)$data['address_format']) . "'"); + + return $this->db->getLastId(); + } + + /** + * @param int $address_format_id + * @param array $data + * + * @return void + */ + public function editAddressFormat(int $address_format_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "address_format` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `address_format` = '" . $this->db->escape((string)$data['address_format']) . "' WHERE `address_format_id` = '" . (int)$address_format_id . "'"); + } + + /** + * @param int $address_format_id + * + * @return void + */ + public function deleteAddressFormat(int $address_format_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "address_format` WHERE `address_format_id` = '" . (int)$address_format_id . "'"); + } + + /** + * @param int $address_format_id + * + * @return array + */ + public function getAddressFormat(int $address_format_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "address_format` WHERE `address_format_id` = '" . (int)$address_format_id . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getAddressFormats(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "address_format`"; + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param array $data + * + * @return int + */ + public function getTotalAddressFormats(array $data = []): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "address_format`"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/localisation/country.php b/admininistrator/model/localisation/country.php new file mode 100644 index 0000000..56789a5 --- /dev/null +++ b/admininistrator/model/localisation/country.php @@ -0,0 +1,188 @@ +db->query("INSERT INTO `" . DB_PREFIX . "country` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `iso_code_2` = '" . $this->db->escape((string)$data['iso_code_2']) . "', `iso_code_3` = '" . $this->db->escape((string)$data['iso_code_3']) . "', `address_format_id` = '" . (int)$data['address_format_id'] . "', `postcode_required` = '" . (int)$data['postcode_required'] . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "'"); + + $this->cache->delete('country'); + + return $this->db->getLastId(); + } + + /** + * @param int $country_id + * @param array $data + * + * @return void + */ + public function editCountry(int $country_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "country` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `iso_code_2` = '" . $this->db->escape((string)$data['iso_code_2']) . "', `iso_code_3` = '" . $this->db->escape((string)$data['iso_code_3']) . "', `address_format_id` = '" . (int)$data['address_format_id'] . "', `postcode_required` = '" . (int)$data['postcode_required'] . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "' WHERE `country_id` = '" . (int)$country_id . "'"); + + $this->cache->delete('country'); + } + + /** + * @param int $country_id + * + * @return void + */ + public function deleteCountry(int $country_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "country` WHERE `country_id` = '" . (int)$country_id . "'"); + + $this->cache->delete('country'); + } + + /** + * @param int $country_id + * + * @return array + */ + public function getCountry(int $country_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "country` WHERE `country_id` = '" . (int)$country_id . "'"); + + return $query->row; + } + + /** + * @param $iso_code_2 + * + * @return array + */ + public function getCountryByIsoCode2($iso_code_2): array { + $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "country WHERE `iso_code_2` = '" . $this->db->escape($iso_code_2) . "' AND `status` = '1'"); + + return $query->row; + } + + /** + * @param $iso_code_3 + * + * @return array + */ + public function getCountryByIsoCode3($iso_code_3): array { + $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "country WHERE `iso_code_3` = '" . $this->db->escape($iso_code_3) . "' AND `status` = '1'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getCountries(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "country`"; + + $implode = []; + + if (!empty($data['filter_name'])) { + $implode[] = "`name` LIKE '" . $this->db->escape((string)$data['filter_name'] . '%') . "'"; + } + + if (!empty($data['filter_iso_code_2'])) { + $implode[] = "`iso_code_2` LIKE '" . $this->db->escape((string)$data['filter_iso_code_2'] . '%') . "'"; + } + + if (!empty($data['filter_iso_code_3'])) { + $implode[] = "`iso_code_3` LIKE '" . $this->db->escape((string)$data['filter_iso_code_3'] . '%') . "'"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $sort_data = [ + 'name', + 'iso_code_2', + 'iso_code_3' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `name`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $country_data = $this->cache->get('country.' . md5($sql)); + + if (!$country_data) { + $query = $this->db->query($sql); + + $country_data = $query->rows; + + $this->cache->set('country.' . md5($sql), $country_data); + } + + return $country_data; + } + + /** + * @param array $data + * + * @return int + */ + public function getTotalCountries(array $data = []): int { + $sql = "SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "country`"; + + $implode = []; + + if (!empty($data['filter_name'])) { + $implode[] = "`name` LIKE '" . $this->db->escape((string)$data['filter_name'] . '%') . "'"; + } + + if (!empty($data['filter_iso_code_2'])) { + $implode[] = "`iso_code_2` LIKE '" . $this->db->escape((string)$data['filter_iso_code_2'] . '%') . "'"; + } + + if (!empty($data['filter_iso_code_3'])) { + $implode[] = "`iso_code_3` LIKE '" . $this->db->escape((string)$data['filter_iso_code_3'] . '%') . "'"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $query = $this->db->query($sql); + + return (int)$query->row['total']; + } + + /** + * @param int $address_format_id + * + * @return int + */ + public function getTotalCountriesByAddressFormatId(int $address_format_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "country` WHERE `address_format_id` = '" . (int)$address_format_id . "'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/localisation/currency.php b/admininistrator/model/localisation/currency.php new file mode 100644 index 0000000..20e7ffc --- /dev/null +++ b/admininistrator/model/localisation/currency.php @@ -0,0 +1,155 @@ +db->query("INSERT INTO `" . DB_PREFIX . "currency` SET `title` = '" . $this->db->escape((string)$data['title']) . "', `code` = '" . $this->db->escape((string)$data['code']) . "', `symbol_left` = '" . $this->db->escape((string)$data['symbol_left']) . "', `symbol_right` = '" . $this->db->escape((string)$data['symbol_right']) . "', `decimal_place` = '" . (int)$data['decimal_place'] . "', `value` = '" . (float)$data['value'] . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "', `date_modified` = NOW()"); + + $this->cache->delete('currency'); + + return $this->db->getLastId(); + } + + /** + * @param int $currency_id + * @param array $data + * + * @return void + */ + public function editCurrency(int $currency_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "currency` SET `title` = '" . $this->db->escape((string)$data['title']) . "', `code` = '" . $this->db->escape((string)$data['code']) . "', `symbol_left` = '" . $this->db->escape((string)$data['symbol_left']) . "', `symbol_right` = '" . $this->db->escape((string)$data['symbol_right']) . "', `decimal_place` = '" . (int)$data['decimal_place'] . "', `value` = '" . (float)$data['value'] . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "', `date_modified` = NOW() WHERE `currency_id` = '" . (int)$currency_id . "'"); + + $this->cache->delete('currency'); + } + + /** + * @param string $code + * @param float $value + * + * @return void + */ + public function editValueByCode(string $code, float $value): void { + $this->db->query("UPDATE `" . DB_PREFIX . "currency` SET `value` = '" . (float)$value . "', `date_modified` = NOW() WHERE `code` = '" . $this->db->escape($code) . "'"); + + $this->cache->delete('currency'); + } + + /** + * @param int $currency_id + * + * @return void + */ + public function deleteCurrency(int $currency_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "currency` WHERE `currency_id` = '" . (int)$currency_id . "'"); + + $this->cache->delete('currency'); + } + + /** + * @param int $currency_id + * + * @return array + */ + public function getCurrency(int $currency_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "currency` WHERE `currency_id` = '" . (int)$currency_id . "'"); + + return $query->row; + } + + /** + * @param string $currency + * + * @return array + */ + public function getCurrencyByCode(string $currency): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "currency` WHERE `code` = '" . $this->db->escape($currency) . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getCurrencies(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "currency`"; + + $sort_data = [ + 'title', + 'code', + 'value', + 'date_modified' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `title`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $results = (array)$this->cache->get('currency.' . md5($sql)); + + if (!$results) { + $query = $this->db->query($sql); + + $results = $query->rows; + + $this->cache->set('currency.' . md5($sql), $results); + } + + $currency_data = []; + + foreach ($results as $result) { + $currency_data[$result['code']] = [ + 'currency_id' => $result['currency_id'], + 'title' => $result['title'], + 'code' => $result['code'], + 'symbol_left' => $result['symbol_left'], + 'symbol_right' => $result['symbol_right'], + 'decimal_place' => $result['decimal_place'], + 'value' => $result['value'], + 'status' => $result['status'], + 'date_modified' => $result['date_modified'] + ]; + } + + return $currency_data; + } + + /** + * @return int + */ + public function getTotalCurrencies(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "currency`"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/localisation/geo_zone.php b/admininistrator/model/localisation/geo_zone.php new file mode 100644 index 0000000..7ed7979 --- /dev/null +++ b/admininistrator/model/localisation/geo_zone.php @@ -0,0 +1,179 @@ +db->query("INSERT INTO `" . DB_PREFIX . "geo_zone` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `description` = '" . $this->db->escape((string)$data['description']) . "', `date_added` = NOW()"); + + $geo_zone_id = $this->db->getLastId(); + + if (isset($data['zone_to_geo_zone'])) { + foreach ($data['zone_to_geo_zone'] as $value) { + $this->db->query("DELETE FROM `" . DB_PREFIX . "zone_to_geo_zone` WHERE `geo_zone_id` = '" . (int)$geo_zone_id . "' AND `country_id` = '" . (int)$value['country_id'] . "' AND `zone_id` = '" . (int)$value['zone_id'] . "'"); + + $this->db->query("INSERT INTO `" . DB_PREFIX . "zone_to_geo_zone` SET `country_id` = '" . (int)$value['country_id'] . "', `zone_id` = '" . (int)$value['zone_id'] . "', `geo_zone_id` = '" . (int)$geo_zone_id . "', `date_added` = NOW()"); + } + } + + $this->cache->delete('geo_zone'); + + return $geo_zone_id; + } + + /** + * @param int $geo_zone_id + * @param array $data + * + * @return void + */ + public function editGeoZone(int $geo_zone_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "geo_zone` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `description` = '" . $this->db->escape((string)$data['description']) . "', `date_modified` = NOW() WHERE `geo_zone_id` = '" . (int)$geo_zone_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "zone_to_geo_zone` WHERE `geo_zone_id` = '" . (int)$geo_zone_id . "'"); + + if (isset($data['zone_to_geo_zone'])) { + foreach ($data['zone_to_geo_zone'] as $value) { + $this->db->query("DELETE FROM `" . DB_PREFIX . "zone_to_geo_zone` WHERE `geo_zone_id` = '" . (int)$geo_zone_id . "' AND `country_id` = '" . (int)$value['country_id'] . "' AND `zone_id` = '" . (int)$value['zone_id'] . "'"); + + $this->db->query("INSERT INTO `" . DB_PREFIX . "zone_to_geo_zone` SET `country_id` = '" . (int)$value['country_id'] . "', `zone_id` = '" . (int)$value['zone_id'] . "', `geo_zone_id` = '" . (int)$geo_zone_id . "', `date_added` = NOW()"); + } + } + + $this->cache->delete('geo_zone'); + } + + /** + * @param int $geo_zone_id + * + * @return void + */ + public function deleteGeoZone(int $geo_zone_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "geo_zone` WHERE `geo_zone_id` = '" . (int)$geo_zone_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "zone_to_geo_zone` WHERE `geo_zone_id` = '" . (int)$geo_zone_id . "'"); + + $this->cache->delete('geo_zone'); + } + + /** + * @param int $geo_zone_id + * + * @return array + */ + public function getGeoZone(int $geo_zone_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "geo_zone` WHERE `geo_zone_id` = '" . (int)$geo_zone_id . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getGeoZones(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "geo_zone`"; + + $sort_data = [ + 'name', + 'description' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `name`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $geo_zone_data = $this->cache->get('geo_zone.' . md5($sql)); + + if (!$geo_zone_data) { + $query = $this->db->query($sql); + + $geo_zone_data = $query->rows; + + $this->cache->set('geo_zone.' . md5($sql), $geo_zone_data); + } + + return $geo_zone_data; + } + + /** + * @return int + */ + public function getTotalGeoZones(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "geo_zone`"); + + return (int)$query->row['total']; + } + + /** + * @param int $geo_zone_id + * + * @return array + */ + public function getZoneToGeoZones(int $geo_zone_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "zone_to_geo_zone` WHERE `geo_zone_id` = '" . (int)$geo_zone_id . "'"); + + return $query->rows; + } + + /** + * @param int $geo_zone_id + * + * @return int + */ + public function getTotalZoneToGeoZoneByGeoZoneId(int $geo_zone_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "zone_to_geo_zone` WHERE `geo_zone_id` = '" . (int)$geo_zone_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $country_id + * + * @return int + */ + public function getTotalZoneToGeoZoneByCountryId(int $country_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "zone_to_geo_zone` WHERE `country_id` = '" . (int)$country_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $zone_id + * + * @return int + */ + public function getTotalZoneToGeoZoneByZoneId(int $zone_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "zone_to_geo_zone` WHERE `zone_id` = '" . (int)$zone_id . "'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/localisation/language.php b/admininistrator/model/localisation/language.php new file mode 100644 index 0000000..c5e8626 --- /dev/null +++ b/admininistrator/model/localisation/language.php @@ -0,0 +1,428 @@ +db->query("INSERT INTO `" . DB_PREFIX . "language` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `code` = '" . $this->db->escape((string)$data['code']) . "', `locale` = '" . $this->db->escape((string)$data['locale']) . "', `extension` = '" . $this->db->escape((string)$data['extension']) . "', `sort_order` = '" . (int)$data['sort_order'] . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "'"); + + $this->cache->delete('language'); + + $language_id = $this->db->getLastId(); + + // Attribute + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "attribute_description` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $attribute) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "attribute_description` SET `attribute_id` = '" . (int)$attribute['attribute_id'] . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($attribute['name']) . "'"); + } + + // Attribute Group + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "attribute_group_description` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $attribute_group) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "attribute_group_description` SET `attribute_group_id` = '" . (int)$attribute_group['attribute_group_id'] . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($attribute_group['name']) . "'"); + } + + $this->cache->delete('attribute'); + + // Banner + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "banner_image` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $banner_image) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "banner_image` SET `banner_id` = '" . (int)$banner_image['banner_id'] . "', `language_id` = '" . (int)$language_id . "', `title` = '" . $this->db->escape($banner_image['title']) . "', `link` = '" . $this->db->escape($banner_image['link']) . "', `image` = '" . $this->db->escape($banner_image['image']) . "', `sort_order` = '" . (int)$banner_image['sort_order'] . "'"); + } + + $this->cache->delete('banner'); + + // Category + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "category_description` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $category) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "category_description` SET `category_id` = '" . (int)$category['category_id'] . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($category['name']) . "', `description` = '" . $this->db->escape($category['description']) . "', `meta_title` = '" . $this->db->escape($category['meta_title']) . "', `meta_description` = '" . $this->db->escape($category['meta_description']) . "', `meta_keyword` = '" . $this->db->escape($category['meta_keyword']) . "'"); + } + + // Customer Group + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "customer_group_description` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $customer_group) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "customer_group_description` SET `customer_group_id` = '" . (int)$customer_group['customer_group_id'] . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($customer_group['name']) . "', `description` = '" . $this->db->escape($customer_group['description']) . "'"); + } + + // Custom Field + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "custom_field_description` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $custom_field) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "custom_field_description` SET `custom_field_id` = '" . (int)$custom_field['custom_field_id'] . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($custom_field['name']) . "'"); + } + + // Custom Field Value + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "custom_field_value_description` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $custom_field_value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "custom_field_value_description` SET `custom_field_value_id` = '" . (int)$custom_field_value['custom_field_value_id'] . "', `language_id` = '" . (int)$language_id . "', `custom_field_id` = '" . (int)$custom_field_value['custom_field_id'] . "', `name` = '" . $this->db->escape($custom_field_value['name']) . "'"); + } + + // Download + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "download_description` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $download) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "download_description` SET `download_id` = '" . (int)$download['download_id'] . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($download['name']) . "'"); + } + + // Filter + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "filter_description` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $filter) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "filter_description` SET `filter_id` = '" . (int)$filter['filter_id'] . "', `language_id` = '" . (int)$language_id . "', `filter_group_id` = '" . (int)$filter['filter_group_id'] . "', `name` = '" . $this->db->escape($filter['name']) . "'"); + } + + // Filter Group + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "filter_group_description` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $filter_group) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "filter_group_description` SET `filter_group_id` = '" . (int)$filter_group['filter_group_id'] . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($filter_group['name']) . "'"); + } + + // Information + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "information_description` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $information) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "information_description` SET `information_id` = '" . (int)$information['information_id'] . "', `language_id` = '" . (int)$language_id . "', `title` = '" . $this->db->escape($information['title']) . "', `description` = '" . $this->db->escape($information['description']) . "', `meta_title` = '" . $this->db->escape($information['meta_title']) . "', `meta_description` = '" . $this->db->escape($information['meta_description']) . "', `meta_keyword` = '" . $this->db->escape($information['meta_keyword']) . "'"); + } + + $this->cache->delete('information'); + + // Length + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "length_class_description` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $length) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "length_class_description` SET `length_class_id` = '" . (int)$length['length_class_id'] . "', `language_id` = '" . (int)$language_id . "', `title` = '" . $this->db->escape($length['title']) . "', `unit` = '" . $this->db->escape($length['unit']) . "'"); + } + + $this->cache->delete('length_class'); + + // Option + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "option_description` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $option) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "option_description` SET `option_id` = '" . (int)$option['option_id'] . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($option['name']) . "'"); + } + + // Option Value + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "option_value_description` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $option_value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "option_value_description` SET `option_value_id` = '" . (int)$option_value['option_value_id'] . "', `language_id` = '" . (int)$language_id . "', `option_id` = '" . (int)$option_value['option_id'] . "', `name` = '" . $this->db->escape($option_value['name']) . "'"); + } + + // Order Status + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "order_status` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $order_status) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "order_status` SET `order_status_id` = '" . (int)$order_status['order_status_id'] . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($order_status['name']) . "'"); + } + + $this->cache->delete('order_status'); + + // Product + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_description` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $product) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_description` SET `product_id` = '" . (int)$product['product_id'] . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($product['name']) . "', `description` = '" . $this->db->escape($product['description']) . "', `tag` = '" . $this->db->escape($product['tag']) . "', `meta_title` = '" . $this->db->escape($product['meta_title']) . "', `meta_description` = '" . $this->db->escape($product['meta_description']) . "', `meta_keyword` = '" . $this->db->escape($product['meta_keyword']) . "'"); + } + + $this->cache->delete('product'); + + // Product Attribute + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_attribute` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $product_attribute) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "product_attribute` SET `product_id` = '" . (int)$product_attribute['product_id'] . "', `attribute_id` = '" . (int)$product_attribute['attribute_id'] . "', `language_id` = '" . (int)$language_id . "', `text` = '" . $this->db->escape($product_attribute['text']) . "'"); + } + + // Return Action + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "return_action` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $return_action) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "return_action` SET `return_action_id` = '" . (int)$return_action['return_action_id'] . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($return_action['name']) . "'"); + } + + // Return Reason + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "return_reason` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $return_reason) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "return_reason` SET `return_reason_id` = '" . (int)$return_reason['return_reason_id'] . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($return_reason['name']) . "'"); + } + + // Return Status + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "return_status` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $return_status) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "return_status` SET `return_status_id` = '" . (int)$return_status['return_status_id'] . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($return_status['name']) . "'"); + } + + // Stock Status + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "stock_status` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $stock_status) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "stock_status` SET `stock_status_id` = '" . (int)$stock_status['stock_status_id'] . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($stock_status['name']) . "'"); + } + + $this->cache->delete('stock_status'); + + // Voucher Theme + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "voucher_theme_description` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $voucher_theme) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "voucher_theme_description` SET `voucher_theme_id` = '" . (int)$voucher_theme['voucher_theme_id'] . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($voucher_theme['name']) . "'"); + } + + $this->cache->delete('voucher_theme'); + + // Weight Class + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "weight_class_description` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $weight_class) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "weight_class_description` SET `weight_class_id` = '" . (int)$weight_class['weight_class_id'] . "', `language_id` = '" . (int)$language_id . "', `title` = '" . $this->db->escape($weight_class['title']) . "', `unit` = '" . $this->db->escape($weight_class['unit']) . "'"); + } + + $this->cache->delete('weight_class'); + + // Subscription + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "subscription_status` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $subscription) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "subscription_status` SET `subscription_status_id` = '" . (int)$subscription['subscription_status_id'] . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($subscription['name']) . "'"); + } + + // SEO URL + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "seo_url` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + foreach ($query->rows as $seo_url) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "seo_url` SET `store_id` = '" . (int)$seo_url['store_id'] . "', `language_id` = '" . (int)$language_id . "', `key` = '" . $this->db->escape($seo_url['key']) . "', `value` = '" . $this->db->escape($seo_url['value']) . "', `keyword` = '" . $this->db->escape($seo_url['keyword']) . "', `sort_order` = '" . (int)$seo_url['sort_order'] . "'"); + } + + return $language_id; + } + + /** + * @param int $language_id + * @param array $data + * + * @return void + */ + public function editLanguage(int $language_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "language` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `code` = '" . $this->db->escape((string)$data['code']) . "', `locale` = '" . $this->db->escape((string)$data['locale']) . "', `extension` = '" . $this->db->escape((string)$data['extension']) . "', `sort_order` = '" . (int)$data['sort_order'] . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "' WHERE `language_id` = '" . (int)$language_id . "'"); + + $this->cache->delete('language'); + } + + /** + * @param int $language_id + * + * @return void + */ + public function deleteLanguage(int $language_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "language` WHERE `language_id` = '" . (int)$language_id . "'"); + + $this->cache->delete('language'); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "attribute_description` WHERE `language_id` = '" . (int)$language_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "attribute_group_description` WHERE `language_id` = '" . (int)$language_id . "'"); + + $this->cache->delete('attribute'); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "banner_image` WHERE `language_id` = '" . (int)$language_id . "'"); + + $this->cache->delete('banner'); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "category_description` WHERE `language_id` = '" . (int)$language_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_group_description` WHERE `language_id` = '" . (int)$language_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "custom_field_description` WHERE `language_id` = '" . (int)$language_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "custom_field_value_description` WHERE `language_id` = '" . (int)$language_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "download_description` WHERE `language_id` = '" . (int)$language_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "filter_description` WHERE `language_id` = '" . (int)$language_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "filter_group_description` WHERE `language_id` = '" . (int)$language_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "information_description` WHERE `language_id` = '" . (int)$language_id . "'"); + + $this->cache->delete('information'); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "length_class_description` WHERE `language_id` = '" . (int)$language_id . "'"); + + $this->cache->delete('length_class'); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "option_description` WHERE `language_id` = '" . (int)$language_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "option_value_description` WHERE `language_id` = '" . (int)$language_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "order_status` WHERE `language_id` = '" . (int)$language_id . "'"); + + $this->cache->delete('order_status'); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_description` WHERE `language_id` = '" . (int)$language_id . "'"); + + $this->cache->delete('product'); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_attribute` WHERE `language_id` = '" . (int)$language_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "return_action` WHERE `language_id` = '" . (int)$language_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "return_reason` WHERE `language_id` = '" . (int)$language_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "return_status` WHERE `language_id` = '" . (int)$language_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "stock_status` WHERE `language_id` = '" . (int)$language_id . "'"); + + $this->cache->delete('stock_status'); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "voucher_theme_description` WHERE `language_id` = '" . (int)$language_id . "'"); + + $this->cache->delete('voucher_theme'); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "weight_class_description` WHERE `language_id` = '" . (int)$language_id . "'"); + + $this->cache->delete('weight_class'); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "subscription_status` WHERE `language_id` = '" . (int)$language_id . "'"); + + $this->cache->delete('subscription_status'); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "seo_url` WHERE `language_id` = '" . (int)$language_id . "'"); + } + + /** + * @param int $language_id + * + * @return array + */ + public function getLanguage(int $language_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "language` WHERE `language_id` = '" . (int)$language_id . "'"); + + $language = $query->row; + + if ($language) { + $language['image'] = HTTP_CATALOG; + + if (!$language['extension']) { + $language['image'] .= 'catalog/'; + } else { + $language['image'] .= 'extension/' . $language['extension'] . '/catalog/'; + } + + $language['image'] .= 'language/' . $language['code'] . '/' . $language['code'] . '.png'; + } + + return $language; + } + + /** + * @param string $code + * + * @return array + */ + public function getLanguageByCode(string $code): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "language` WHERE `code` = '" . $this->db->escape($code) . "'"); + + $language = $query->row; + + if ($language) { + $language['image'] = HTTP_CATALOG; + + if (!$language['extension']) { + $language['image'] .= 'catalog/'; + } else { + $language['image'] .= 'extension/' . $language['extension'] . '/catalog/'; + } + + $language['image'] .= 'language/' . $language['code'] . '/' . $language['code'] . '.png'; + } + + return $language; + } + + /** + * @param array $data + * + * @return array + */ + public function getLanguages(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "language`"; + + $sort_data = [ + 'name', + 'code', + 'sort_order' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `sort_order`, `name`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $results = (array)$this->cache->get('language.' . md5($sql)); + + if (!$results) { + $query = $this->db->query($sql); + + $results = $query->rows; + + $this->cache->set('language.' . md5($sql), $results); + } + + $language_data = []; + + foreach ($results as $result) { + $image = HTTP_CATALOG; + + if (!$result['extension']) { + $image .= 'catalog/'; + } else { + $image .= 'extension/' . $result['extension'] . '/catalog/'; + } + + $language_data[$result['code']] = [ + 'language_id' => $result['language_id'], + 'name' => $result['name'], + 'code' => $result['code'], + 'image' => $image . 'language/' . $result['code'] . '/' . $result['code'] . '.png', + 'locale' => $result['locale'], + 'extension' => $result['extension'], + 'sort_order' => $result['sort_order'], + 'status' => $result['status'] + ]; + } + + return $language_data; + } + + /** + * @return int + */ + public function getTotalLanguages(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "language`"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/localisation/length_class.php b/admininistrator/model/localisation/length_class.php new file mode 100644 index 0000000..f254c68 --- /dev/null +++ b/admininistrator/model/localisation/length_class.php @@ -0,0 +1,159 @@ +db->query("INSERT INTO `" . DB_PREFIX . "length_class` SET `value` = '" . (float)$data['value'] . "'"); + + $length_class_id = $this->db->getLastId(); + + foreach ($data['length_class_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "length_class_description` SET `length_class_id` = '" . (int)$length_class_id . "', `language_id` = '" . (int)$language_id . "', `title` = '" . $this->db->escape($value['title']) . "', `unit` = '" . $this->db->escape($value['unit']) . "'"); + } + + $this->cache->delete('length_class'); + + return $length_class_id; + } + + /** + * @param int $length_class_id + * @param array $data + * + * @return void + */ + public function editLengthClass(int $length_class_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "length_class` SET `value` = '" . (float)$data['value'] . "' WHERE `length_class_id` = '" . (int)$length_class_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "length_class_description` WHERE `length_class_id` = '" . (int)$length_class_id . "'"); + + foreach ($data['length_class_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "length_class_description` SET `length_class_id` = '" . (int)$length_class_id . "', `language_id` = '" . (int)$language_id . "', `title` = '" . $this->db->escape($value['title']) . "', `unit` = '" . $this->db->escape($value['unit']) . "'"); + } + + $this->cache->delete('length_class'); + } + + /** + * @param int $length_class_id + * + * @return void + */ + public function deleteLengthClass(int $length_class_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "length_class` WHERE `length_class_id` = '" . (int)$length_class_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "length_class_description` WHERE `length_class_id` = '" . (int)$length_class_id . "'"); + + $this->cache->delete('length_class'); + } + + /** + * @param array $data + * + * @return array + */ + public function getLengthClasses(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "length_class` lc LEFT JOIN `" . DB_PREFIX . "length_class_description` lcd ON (lc.`length_class_id` = lcd.`length_class_id`) WHERE lcd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"; + + $sort_data = [ + 'title', + 'unit', + 'value' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `title`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $length_class_data = $this->cache->get('length_class.' . md5($sql)); + + if (!$length_class_data) { + $query = $this->db->query($sql); + + $length_class_data = $query->rows; + + $this->cache->set('length_class.' . md5($sql), $length_class_data); + } + + return $length_class_data; + } + + /** + * @param int $length_class_id + * + * @return array + */ + public function getLengthClass(int $length_class_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "length_class` lc LEFT JOIN `" . DB_PREFIX . "length_class_description` lcd ON (lc.`length_class_id` = lcd.`length_class_id`) WHERE lc.`length_class_id` = '" . (int)$length_class_id . "' AND lcd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return $query->row; + } + + /** + * @param string $unit + * + * @return array + */ + public function getDescriptionByUnit(string $unit): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "length_class_description` WHERE `unit` = '" . $this->db->escape($unit) . "' AND `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return $query->row; + } + + /** + * @param int $length_class_id + * + * @return array + */ + public function getDescriptions(int $length_class_id): array { + $length_class_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "length_class_description` WHERE `length_class_id` = '" . (int)$length_class_id . "'"); + + foreach ($query->rows as $result) { + $length_class_data[$result['language_id']] = [ + 'title' => $result['title'], + 'unit' => $result['unit'] + ]; + } + + return $length_class_data; + } + + /** + * @return int + */ + public function getTotalLengthClasses(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "length_class`"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/localisation/location.php b/admininistrator/model/localisation/location.php new file mode 100644 index 0000000..ecb59ff --- /dev/null +++ b/admininistrator/model/localisation/location.php @@ -0,0 +1,100 @@ +db->query("INSERT INTO `" . DB_PREFIX . "location` SET `name` = '" . $this->db->escape((string)$data['name']) . "', address = '" . $this->db->escape((string)$data['address']) . "', `geocode` = '" . $this->db->escape((string)$data['geocode']) . "', `telephone` = '" . $this->db->escape((string)$data['telephone']) . "', `image` = '" . $this->db->escape((string)$data['image']) . "', `open` = '" . $this->db->escape((string)$data['open']) . "', `comment` = '" . $this->db->escape((string)$data['comment']) . "'"); + + return $this->db->getLastId(); + } + + /** + * @param int $location_id + * @param array $data + * + * @return void + */ + public function editLocation(int $location_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "location` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `address` = '" . $this->db->escape((string)$data['address']) . "', `geocode` = '" . $this->db->escape((string)$data['geocode']) . "', `telephone` = '" . $this->db->escape((string)$data['telephone']) . "', `image` = '" . $this->db->escape((string)$data['image']) . "', `open` = '" . $this->db->escape((string)$data['open']) . "', `comment` = '" . $this->db->escape((string)$data['comment']) . "' WHERE `location_id` = '" . (int)$location_id . "'"); + } + + /** + * @param int $location_id + * + * @return void + */ + public function deleteLocation(int $location_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "location` WHERE `location_id` = '" . (int)$location_id . "'"); + } + + /** + * @param int $location_id + * + * @return array + */ + public function getLocation(int $location_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "location` WHERE `location_id` = '" . (int)$location_id . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getLocations(array $data = []): array { + $sql = "SELECT `location_id`, `name`, `address` FROM `" . DB_PREFIX . "location`"; + + $sort_data = [ + 'name', + 'address', + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `name`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @return int + */ + public function getTotalLocations(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "location`"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/localisation/order_status.php b/admininistrator/model/localisation/order_status.php new file mode 100644 index 0000000..4541415 --- /dev/null +++ b/admininistrator/model/localisation/order_status.php @@ -0,0 +1,132 @@ + $value) { + if (isset($order_status_id)) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "order_status` SET `order_status_id` = '" . (int)$order_status_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } else { + $this->db->query("INSERT INTO `" . DB_PREFIX . "order_status` SET `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + + $order_status_id = $this->db->getLastId(); + } + } + + $this->cache->delete('order_status'); + + return $order_status_id; + } + + /** + * @param int $order_status_id + * @param array $data + * + * @return void + */ + public function editOrderStatus(int $order_status_id, array $data): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "order_status` WHERE `order_status_id` = '" . (int)$order_status_id . "'"); + + foreach ($data['order_status'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "order_status` SET `order_status_id` = '" . (int)$order_status_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } + + $this->cache->delete('order_status'); + } + + /** + * @param int $order_status_id + * + * @return void + */ + public function deleteOrderStatus(int $order_status_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "order_status` WHERE `order_status_id` = '" . (int)$order_status_id . "'"); + + $this->cache->delete('order_status'); + } + + /** + * @param int $order_status_id + * + * @return array + */ + public function getOrderStatus(int $order_status_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "order_status` WHERE `order_status_id` = '" . (int)$order_status_id . "' AND `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getOrderStatuses(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "order_status` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "' ORDER BY `name`"; + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $order_status_data = $this->cache->get('order_status.' . md5($sql)); + + if (!$order_status_data) { + $query = $this->db->query($sql); + + $order_status_data = $query->rows; + + $this->cache->set('order_status.' . md5($sql), $order_status_data); + } + + return $order_status_data; + } + + /** + * @param int $order_status_id + * + * @return array + */ + public function getDescriptions(int $order_status_id): array { + $order_status_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "order_status` WHERE `order_status_id` = '" . (int)$order_status_id . "'"); + + foreach ($query->rows as $result) { + $order_status_data[$result['language_id']] = ['name' => $result['name']]; + } + + return $order_status_data; + } + + /** + * @return int + */ + public function getTotalOrderStatuses(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "order_status` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/localisation/return_action.php b/admininistrator/model/localisation/return_action.php new file mode 100644 index 0000000..90ff6da --- /dev/null +++ b/admininistrator/model/localisation/return_action.php @@ -0,0 +1,132 @@ + $value) { + if (isset($return_action_id)) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "return_action` SET `return_action_id` = '" . (int)$return_action_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } else { + $this->db->query("INSERT INTO `" . DB_PREFIX . "return_action` SET `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + + $return_action_id = $this->db->getLastId(); + } + } + + $this->cache->delete('return_action'); + + return $return_action_id; + } + + /** + * @param int $return_action_id + * @param array $data + * + * @return void + */ + public function editReturnAction(int $return_action_id, array $data): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "return_action` WHERE `return_action_id` = '" . (int)$return_action_id . "'"); + + foreach ($data['return_action'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "return_action` SET `return_action_id` = '" . (int)$return_action_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } + + $this->cache->delete('return_action'); + } + + /** + * @param int $return_action_id + * + * @return void + */ + public function deleteReturnAction(int $return_action_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "return_action` WHERE `return_action_id` = '" . (int)$return_action_id . "'"); + + $this->cache->delete('return_action'); + } + + /** + * @param int $return_action_id + * + * @return array + */ + public function getReturnAction(int $return_action_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "return_action` WHERE `return_action_id` = '" . (int)$return_action_id . "' AND `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getReturnActions(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "return_action` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "' ORDER BY `name`"; + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $return_action_data = $this->cache->get('return_action.' . md5($sql)); + + if (!$return_action_data) { + $query = $this->db->query($sql); + + $return_action_data = $query->rows; + + $this->cache->set('return_action.' . md5($sql), $return_action_data); + } + + return $return_action_data; + } + + /** + * @param int $return_action_id + * + * @return array + */ + public function getDescriptions(int $return_action_id): array { + $return_action_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "return_action` WHERE `return_action_id` = '" . (int)$return_action_id . "'"); + + foreach ($query->rows as $result) { + $return_action_data[$result['language_id']] = ['name' => $result['name']]; + } + + return $return_action_data; + } + + /** + * @return int + */ + public function getTotalReturnActions(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "return_action` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/localisation/return_reason.php b/admininistrator/model/localisation/return_reason.php new file mode 100644 index 0000000..8202d50 --- /dev/null +++ b/admininistrator/model/localisation/return_reason.php @@ -0,0 +1,132 @@ + $value) { + if (isset($return_reason_id)) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "return_reason` SET `return_reason_id` = '" . (int)$return_reason_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } else { + $this->db->query("INSERT INTO `" . DB_PREFIX . "return_reason` SET `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + + $return_reason_id = $this->db->getLastId(); + } + } + + $this->cache->delete('return_reason'); + + return $return_reason_id; + } + + /** + * @param int $return_reason_id + * @param array $data + * + * @return void + */ + public function editReturnReason(int $return_reason_id, array $data): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "return_reason` WHERE `return_reason_id` = '" . (int)$return_reason_id . "'"); + + foreach ($data['return_reason'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "return_reason` SET `return_reason_id` = '" . (int)$return_reason_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } + + $this->cache->delete('return_reason'); + } + + /** + * @param int $return_reason_id + * + * @return void + */ + public function deleteReturnReason(int $return_reason_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "return_reason` WHERE `return_reason_id` = '" . (int)$return_reason_id . "'"); + + $this->cache->delete('return_reason'); + } + + /** + * @param int $return_reason_id + * + * @return array + */ + public function getReturnReason(int $return_reason_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "return_reason` WHERE `return_reason_id` = '" . (int)$return_reason_id . "' AND `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getReturnReasons(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "return_reason` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "' ORDER BY `name`"; + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $return_reason_data = $this->cache->get('return_reason.' . md5($sql)); + + if (!$return_reason_data) { + $query = $this->db->query($sql); + + $return_reason_data = $query->rows; + + $this->cache->set('return_reason.' . md5($sql), $return_reason_data); + } + + return $return_reason_data; + } + + /** + * @param int $return_reason_id + * + * @return array + */ + public function getDescriptions(int $return_reason_id): array { + $return_reason_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "return_reason` WHERE `return_reason_id` = '" . (int)$return_reason_id . "'"); + + foreach ($query->rows as $result) { + $return_reason_data[$result['language_id']] = ['name' => $result['name']]; + } + + return $return_reason_data; + } + + /** + * @return int + */ + public function getTotalReturnReasons(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "return_reason` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/localisation/return_status.php b/admininistrator/model/localisation/return_status.php new file mode 100644 index 0000000..37881c1 --- /dev/null +++ b/admininistrator/model/localisation/return_status.php @@ -0,0 +1,132 @@ + $value) { + if (isset($return_status_id)) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "return_status` SET `return_status_id` = '" . (int)$return_status_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } else { + $this->db->query("INSERT INTO `" . DB_PREFIX . "return_status` SET `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + + $return_status_id = $this->db->getLastId(); + } + } + + $this->cache->delete('return_status'); + + return $return_status_id; + } + + /** + * @param int $return_status_id + * @param array $data + * + * @return void + */ + public function editReturnStatus(int $return_status_id, array $data) : void{ + $this->db->query("DELETE FROM `" . DB_PREFIX . "return_status` WHERE `return_status_id` = '" . (int)$return_status_id . "'"); + + foreach ($data['return_status'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "return_status` SET `return_status_id` = '" . (int)$return_status_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } + + $this->cache->delete('return_status'); + } + + /** + * @param int $return_status_id + * + * @return void + */ + public function deleteReturnStatus(int $return_status_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "return_status` WHERE `return_status_id` = '" . (int)$return_status_id . "'"); + + $this->cache->delete('return_status'); + } + + /** + * @param int $return_status_id + * + * @return array + */ + public function getReturnStatus(int $return_status_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "return_status` WHERE `return_status_id` = '" . (int)$return_status_id . "' AND `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getReturnStatuses(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "return_status` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "' ORDER BY `name`"; + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $return_status_data = $this->cache->get('return_status.' . md5($sql)); + + if (!$return_status_data) { + $query = $this->db->query($sql); + + $return_status_data = $query->rows; + + $this->cache->set('return_status.' . md5($sql), $return_status_data); + } + + return $return_status_data; + } + + /** + * @param int $return_status_id + * + * @return array + */ + public function getDescriptions(int $return_status_id): array { + $return_status_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "return_status` WHERE `return_status_id` = '" . (int)$return_status_id . "'"); + + foreach ($query->rows as $result) { + $return_status_data[$result['language_id']] = ['name' => $result['name']]; + } + + return $return_status_data; + } + + /** + * @return int + */ + public function getTotalReturnStatuses(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "return_status` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return (int)$query->row['total']; + } +} \ No newline at end of file diff --git a/admininistrator/model/localisation/stock_status.php b/admininistrator/model/localisation/stock_status.php new file mode 100644 index 0000000..4b6d4f3 --- /dev/null +++ b/admininistrator/model/localisation/stock_status.php @@ -0,0 +1,132 @@ + $value) { + if (isset($stock_status_id)) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "stock_status` SET `stock_status_id` = '" . (int)$stock_status_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } else { + $this->db->query("INSERT INTO `" . DB_PREFIX . "stock_status` SET `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + + $stock_status_id = $this->db->getLastId(); + } + } + + $this->cache->delete('stock_status'); + + return $stock_status_id; + } + + /** + * @param int $stock_status_id + * @param array $data + * + * @return void + */ + public function editStockStatus(int $stock_status_id, array $data): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "stock_status` WHERE `stock_status_id` = '" . (int)$stock_status_id . "'"); + + foreach ($data['stock_status'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "stock_status` SET `stock_status_id` = '" . (int)$stock_status_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } + + $this->cache->delete('stock_status'); + } + + /** + * @param int $stock_status_id + * + * @return void + */ + public function deleteStockStatus(int $stock_status_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "stock_status` WHERE `stock_status_id` = '" . (int)$stock_status_id . "'"); + + $this->cache->delete('stock_status'); + } + + /** + * @param int $stock_status_id + * + * @return array + */ + public function getStockStatus(int $stock_status_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "stock_status` WHERE `stock_status_id` = '" . (int)$stock_status_id . "' AND `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getStockStatuses(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "stock_status` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "' ORDER BY `name`"; + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $stock_status_data = $this->cache->get('stock_status.' . md5($sql)); + + if (!$stock_status_data) { + $query = $this->db->query($sql); + + $stock_status_data = $query->rows; + + $this->cache->set('stock_status.' . md5($sql), $stock_status_data); + } + + return $stock_status_data; + } + + /** + * @param int $stock_status_id + * + * @return array + */ + public function getDescriptions(int $stock_status_id): array { + $stock_status_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "stock_status` WHERE `stock_status_id` = '" . (int)$stock_status_id . "'"); + + foreach ($query->rows as $result) { + $stock_status_data[$result['language_id']] = ['name' => $result['name']]; + } + + return $stock_status_data; + } + + /** + * @return int + */ + public function getTotalStockStatuses(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "stock_status` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/localisation/subscription_status.php b/admininistrator/model/localisation/subscription_status.php new file mode 100644 index 0000000..340a49f --- /dev/null +++ b/admininistrator/model/localisation/subscription_status.php @@ -0,0 +1,132 @@ + $value) { + if (isset($subscription_status_id)) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "subscription_status` SET `subscription_status_id` = '" . (int)$subscription_status_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } else { + $this->db->query("INSERT INTO `" . DB_PREFIX . "subscription_status` SET `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + + $subscription_status_id = $this->db->getLastId(); + } + } + + $this->cache->delete('subscription_status'); + + return $subscription_status_id; + } + + /** + * @param int $subscription_status_id + * @param array $data + * + * @return void + */ + public function editSubscriptionStatus(int $subscription_status_id, array $data): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "subscription_status` WHERE `subscription_status_id` = '" . (int)$subscription_status_id . "'"); + + foreach ($data['subscription_status'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "subscription_status` SET `subscription_status_id` = '" . (int)$subscription_status_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } + + $this->cache->delete('subscription_status'); + } + + /** + * @param int $subscription_status_id + * + * @return void + */ + public function deleteSubscriptionStatus(int $subscription_status_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "subscription_status` WHERE `subscription_status_id` = '" . (int)$subscription_status_id . "'"); + + $this->cache->delete('subscription_status'); + } + + /** + * @param int $subscription_status_id + * + * @return array + */ + public function getSubscriptionStatus(int $subscription_status_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "subscription_status` WHERE `subscription_status_id` = '" . (int)$subscription_status_id . "' AND `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getSubscriptionStatuses(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "subscription_status` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "' ORDER BY `name`"; + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $subscription_status_data = $this->cache->get('subscription_status.' . md5($sql)); + + if (!$subscription_status_data) { + $query = $this->db->query($sql); + + $subscription_status_data = $query->rows; + + $this->cache->set('subscription_status.' . md5($sql), $subscription_status_data); + } + + return $subscription_status_data; + } + + /** + * @param int $subscription_status_id + * + * @return array + */ + public function getDescriptions(int $subscription_status_id): array { + $subscription_status_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "subscription_status` WHERE `subscription_status_id` = '" . (int)$subscription_status_id . "'"); + + foreach ($query->rows as $result) { + $subscription_status_data[$result['language_id']] = ['name' => $result['name']]; + } + + return $subscription_status_data; + } + + /** + * @return int + */ + public function getTotalSubscriptionStatuses(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "subscription_status` WHERE `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/localisation/tax_class.php b/admininistrator/model/localisation/tax_class.php new file mode 100644 index 0000000..ee35706 --- /dev/null +++ b/admininistrator/model/localisation/tax_class.php @@ -0,0 +1,142 @@ +db->query("INSERT INTO `" . DB_PREFIX . "tax_class` SET `title` = '" . $this->db->escape((string)$data['title']) . "', `description` = '" . $this->db->escape((string)$data['description']) . "', `date_added` = NOW()"); + + $tax_class_id = $this->db->getLastId(); + + if (isset($data['tax_rule'])) { + foreach ($data['tax_rule'] as $tax_rule) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "tax_rule` SET `tax_class_id` = '" . (int)$tax_class_id . "', `tax_rate_id` = '" . (int)$tax_rule['tax_rate_id'] . "', `based` = '" . $this->db->escape($tax_rule['based']) . "', `priority` = '" . (int)$tax_rule['priority'] . "'"); + } + } + + $this->cache->delete('tax_class'); + + return $tax_class_id; + } + + /** + * @param int $tax_class_id + * @param array $data + * + * @return void + */ + public function editTaxClass(int $tax_class_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "tax_class` SET `title` = '" . $this->db->escape((string)$data['title']) . "', `description` = '" . $this->db->escape((string)$data['description']) . "', `date_modified` = NOW() WHERE `tax_class_id` = '" . (int)$tax_class_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "tax_rule` WHERE `tax_class_id` = '" . (int)$tax_class_id . "'"); + + if (isset($data['tax_rule'])) { + foreach ($data['tax_rule'] as $tax_rule) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "tax_rule` SET `tax_class_id` = '" . (int)$tax_class_id . "', `tax_rate_id` = '" . (int)$tax_rule['tax_rate_id'] . "', `based` = '" . $this->db->escape($tax_rule['based']) . "', `priority` = '" . (int)$tax_rule['priority'] . "'"); + } + } + + $this->cache->delete('tax_class'); + } + + /** + * @param int $tax_class_id + * + * @return void + */ + public function deleteTaxClass(int $tax_class_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "tax_class` WHERE `tax_class_id` = '" . (int)$tax_class_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "tax_rule` WHERE `tax_class_id` = '" . (int)$tax_class_id . "'"); + + $this->cache->delete('tax_class'); + } + + /** + * @param int $tax_class_id + * + * @return array + */ + public function getTaxClass(int $tax_class_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "tax_class` WHERE `tax_class_id` = '" . (int)$tax_class_id . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getTaxClasses(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "tax_class` ORDER BY `title`"; + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $tax_class_data = $this->cache->get('tax_class.'. md5($sql)); + + if (!$tax_class_data) { + $query = $this->db->query($sql); + + $tax_class_data = $query->rows; + + $this->cache->set('tax_class.'. md5($sql), $tax_class_data); + } + + return $tax_class_data; + } + + /** + * @return int + */ + public function getTotalTaxClasses(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "tax_class`"); + + return (int)$query->row['total']; + } + + /** + * @param int $tax_class_id + * + * @return array + */ + public function getTaxRules(int $tax_class_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "tax_rule` WHERE `tax_class_id` = '" . (int)$tax_class_id . "' ORDER BY `priority` ASC"); + + return $query->rows; + } + + /** + * @param int $tax_rate_id + * + * @return int + */ + public function getTotalTaxRulesByTaxRateId(int $tax_rate_id): int { + $query = $this->db->query("SELECT COUNT(DISTINCT `tax_class_id`) AS `total` FROM `" . DB_PREFIX . "tax_rule` WHERE `tax_rate_id` = '" . (int)$tax_rate_id . "'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/localisation/tax_rate.php b/admininistrator/model/localisation/tax_rate.php new file mode 100644 index 0000000..8f9fd2f --- /dev/null +++ b/admininistrator/model/localisation/tax_rate.php @@ -0,0 +1,149 @@ +db->query("INSERT INTO `" . DB_PREFIX . "tax_rate` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `rate` = '" . (float)$data['rate'] . "', `type` = '" . $this->db->escape((string)$data['type']) . "', `geo_zone_id` = '" . (int)$data['geo_zone_id'] . "', `date_added` = NOW(), `date_modified` = NOW()"); + + $tax_rate_id = $this->db->getLastId(); + + if (isset($data['tax_rate_customer_group'])) { + foreach ($data['tax_rate_customer_group'] as $customer_group_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "tax_rate_to_customer_group` SET `tax_rate_id` = '" . (int)$tax_rate_id . "', `customer_group_id` = '" . (int)$customer_group_id . "'"); + } + } + + return $tax_rate_id; + } + + /** + * @param int $tax_rate_id + * @param array $data + * + * @return void + */ + public function editTaxRate(int $tax_rate_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "tax_rate` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `rate` = '" . (float)$data['rate'] . "', `type` = '" . $this->db->escape((string)$data['type']) . "', `geo_zone_id` = '" . (int)$data['geo_zone_id'] . "', `date_modified` = NOW() WHERE `tax_rate_id` = '" . (int)$tax_rate_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "tax_rate_to_customer_group` WHERE `tax_rate_id` = '" . (int)$tax_rate_id . "'"); + + if (isset($data['tax_rate_customer_group'])) { + foreach ($data['tax_rate_customer_group'] as $customer_group_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "tax_rate_to_customer_group` SET `tax_rate_id` = '" . (int)$tax_rate_id . "', `customer_group_id` = '" . (int)$customer_group_id . "'"); + } + } + } + + /** + * @param int $tax_rate_id + * + * @return void + */ + public function deleteTaxRate(int $tax_rate_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "tax_rate` WHERE `tax_rate_id` = '" . (int)$tax_rate_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "tax_rate_to_customer_group` WHERE `tax_rate_id` = '" . (int)$tax_rate_id . "'"); + } + + /** + * @param int $tax_rate_id + * + * @return array + */ + public function getTaxRate(int $tax_rate_id): array { + $query = $this->db->query("SELECT tr.`tax_rate_id`, tr.`name` AS name, tr.`rate`, tr.`type`, tr.`geo_zone_id`, gz.`name` AS geo_zone, tr.`date_added`, tr.`date_modified` FROM `" . DB_PREFIX . "tax_rate` tr LEFT JOIN `" . DB_PREFIX . "geo_zone` gz ON (tr.`geo_zone_id` = gz.`geo_zone_id`) WHERE tr.`tax_rate_id` = '" . (int)$tax_rate_id . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getTaxRates(array $data = []): array { + $sql = "SELECT tr.`tax_rate_id`, tr.`name` AS name, tr.`rate`, tr.`type`, gz.`name` AS geo_zone, tr.`date_added`, tr.`date_modified` FROM `" . DB_PREFIX . "tax_rate` tr LEFT JOIN `" . DB_PREFIX . "geo_zone` gz ON (tr.`geo_zone_id` = gz.`geo_zone_id`)"; + + $sort_data = [ + 'tr.name', + 'tr.rate', + 'tr.type', + 'gz.name', + 'tr.date_added', + 'tr.date_modified' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY tr.`name`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param int $tax_rate_id + * + * @return array + */ + public function getCustomerGroups(int $tax_rate_id): array { + $tax_customer_group_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "tax_rate_to_customer_group` WHERE `tax_rate_id` = '" . (int)$tax_rate_id . "'"); + + foreach ($query->rows as $result) { + $tax_customer_group_data[] = $result['customer_group_id']; + } + + return $tax_customer_group_data; + } + + /** + * @return int + */ + public function getTotalTaxRates(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "tax_rate`"); + + return (int)$query->row['total']; + } + + /** + * @param int $geo_zone_id + * + * @return int + */ + public function getTotalTaxRatesByGeoZoneId(int $geo_zone_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "tax_rate` WHERE `geo_zone_id` = '" . (int)$geo_zone_id . "'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/localisation/weight_class.php b/admininistrator/model/localisation/weight_class.php new file mode 100644 index 0000000..d587e53 --- /dev/null +++ b/admininistrator/model/localisation/weight_class.php @@ -0,0 +1,159 @@ +db->query("INSERT INTO `" . DB_PREFIX . "weight_class` SET `value` = '" . (float)$data['value'] . "'"); + + $weight_class_id = $this->db->getLastId(); + + foreach ($data['weight_class_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "weight_class_description` SET `weight_class_id` = '" . (int)$weight_class_id . "', `language_id` = '" . (int)$language_id . "', `title` = '" . $this->db->escape($value['title']) . "', `unit` = '" . $this->db->escape($value['unit']) . "'"); + } + + $this->cache->delete('weight_class'); + + return $weight_class_id; + } + + /** + * @param int $weight_class_id + * @param array $data + * + * @return void + */ + public function editWeightClass(int $weight_class_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "weight_class` SET `value` = '" . (float)$data['value'] . "' WHERE `weight_class_id` = '" . (int)$weight_class_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "weight_class_description` WHERE `weight_class_id` = '" . (int)$weight_class_id . "'"); + + foreach ($data['weight_class_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "weight_class_description` SET `weight_class_id` = '" . (int)$weight_class_id . "', `language_id` = '" . (int)$language_id . "', `title` = '" . $this->db->escape($value['title']) . "', `unit` = '" . $this->db->escape($value['unit']) . "'"); + } + + $this->cache->delete('weight_class'); + } + + /** + * @param int $weight_class_id + * + * @return void + */ + public function deleteWeightClass(int $weight_class_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "weight_class` WHERE `weight_class_id` = '" . (int)$weight_class_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "weight_class_description` WHERE `weight_class_id` = '" . (int)$weight_class_id . "'"); + + $this->cache->delete('weight_class'); + } + + /** + * @param array $data + * + * @return array + */ + public function getWeightClasses(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "weight_class` wc LEFT JOIN `" . DB_PREFIX . "weight_class_description` wcd ON (wc.`weight_class_id` = wcd.`weight_class_id`) WHERE wcd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"; + + $sort_data = [ + 'title', + 'unit', + 'value' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `title`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $weight_class_data = $this->cache->get('weight_class.' . md5($sql)); + + if (!$weight_class_data) { + $query = $this->db->query($sql); + + $weight_class_data = $query->rows; + + $this->cache->set('weight_class.' . md5($sql), $weight_class_data); + } + + return $weight_class_data; + } + + /** + * @param int $weight_class_id + * + * @return array + */ + public function getWeightClass(int $weight_class_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "weight_class` wc LEFT JOIN `" . DB_PREFIX . "weight_class_description` wcd ON (wc.`weight_class_id` = wcd.`weight_class_id`) WHERE wc.`weight_class_id` = '" . (int)$weight_class_id . "' AND wcd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return $query->row; + } + + /** + * @param string $unit + * + * @return array + */ + public function getDescriptionByUnit(string $unit): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "weight_class_description` WHERE `unit` = '" . $this->db->escape($unit) . "' AND `language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return $query->row; + } + + /** + * @param int $weight_class_id + * + * @return array + */ + public function getDescriptions(int $weight_class_id): array { + $weight_class_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "weight_class_description` WHERE `weight_class_id` = '" . (int)$weight_class_id . "'"); + + foreach ($query->rows as $result) { + $weight_class_data[$result['language_id']] = [ + 'title' => $result['title'], + 'unit' => $result['unit'] + ]; + } + + return $weight_class_data; + } + + /** + * @return int + */ + public function getTotalWeightClasses(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "weight_class`"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/localisation/zone.php b/admininistrator/model/localisation/zone.php new file mode 100644 index 0000000..a20550f --- /dev/null +++ b/admininistrator/model/localisation/zone.php @@ -0,0 +1,183 @@ +db->query("INSERT INTO `" . DB_PREFIX . "zone` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `code` = '" . $this->db->escape((string)$data['code']) . "', `country_id` = '" . (int)$data['country_id'] . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "'"); + + $this->cache->delete('zone'); + + return $this->db->getLastId(); + } + + /** + * @param int $zone_id + * @param array $data + * + * @return void + */ + public function editZone(int $zone_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "zone` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `code` = '" . $this->db->escape((string)$data['code']) . "', `country_id` = '" . (int)$data['country_id'] . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "' WHERE `zone_id` = '" . (int)$zone_id . "'"); + + $this->cache->delete('zone'); + } + + /** + * @param int $zone_id + * + * @return void + */ + public function deleteZone(int $zone_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "zone` WHERE `zone_id` = '" . (int)$zone_id . "'"); + + $this->cache->delete('zone'); + } + + /** + * @param int $zone_id + * + * @return array + */ + public function getZone(int $zone_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "zone` WHERE `zone_id` = '" . (int)$zone_id . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getZones(array $data = []): array { + $sql = "SELECT *, z.`name`, c.`name` AS country FROM `" . DB_PREFIX . "zone` z LEFT JOIN `" . DB_PREFIX . "country` c ON (z.`country_id` = c.`country_id`)"; + + $implode = []; + + if (!empty($data['filter_name'])) { + $implode[] = "z.`name` LIKE '" . $this->db->escape((string)$data['filter_name'] . '%') . "'"; + } + + if (!empty($data['filter_country'])) { + $implode[] = "c.`name` LIKE '" . $this->db->escape((string)$data['filter_country'] . '%') . "'"; + } + + if (!empty($data['filter_code'])) { + $implode[] = "z.`code` LIKE '" . $this->db->escape((string)$data['filter_code'] . '%') . "'"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $sort_data = [ + 'c.name', + 'z.name', + 'z.code' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY c.`name`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param int $country_id + * + * @return array + */ + public function getZonesByCountryId(int $country_id): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "zone` WHERE `country_id` = '" . (int)$country_id . "' AND `status` = '1' ORDER BY `name`"; + + $zone_data = $this->cache->get('zone.' . md5($sql)); + + if (!$zone_data) { + $query = $this->db->query($sql); + + $zone_data = $query->rows; + + $this->cache->set('zone.' . md5($sql), $zone_data); + } + + return $zone_data; + } + + /** + * @param array $data + * + * @return int + */ + public function getTotalZones(array $data = []): int { + $sql = "SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "zone` z"; + + if (!empty($data['filter_country'])) { + $sql .= " LEFT JOIN `" . DB_PREFIX . "country` c ON (z.`country_id` = c.`country_id`)"; + } + + $implode = []; + + if (!empty($data['filter_name'])) { + $implode[] = "z.`name` LIKE '" . $this->db->escape((string)$data['filter_name'] . '%') . "'"; + } + + if (!empty($data['filter_country'])) { + $implode[] = "c.`name` LIKE '" . $this->db->escape((string)$data['filter_country'] . '%') . "'"; + } + + if (!empty($data['filter_code'])) { + $implode[] = "z.`code` LIKE '" . $this->db->escape((string)$data['filter_code'] . '%') . "'"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $query = $this->db->query($sql); + + return (int)$query->row['total']; + } + + /** + * @param int $country_id + * + * @return int + */ + public function getTotalZonesByCountryId(int $country_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "zone` WHERE `country_id` = '" . (int)$country_id . "'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/marketing/affiliate.php b/admininistrator/model/marketing/affiliate.php new file mode 100644 index 0000000..3fdc47e --- /dev/null +++ b/admininistrator/model/marketing/affiliate.php @@ -0,0 +1,227 @@ +db->query("INSERT INTO `" . DB_PREFIX . "customer_affiliate` SET `customer_id` = '" . (int)$data['customer_id'] . "', `company` = '" . $this->db->escape((string)$data['company']) . "', `website` = '" . $this->db->escape((string)$data['website']) . "', `tracking` = '" . $this->db->escape((string)$data['tracking']) . "', `commission` = '" . (float)$data['commission'] . "', `tax` = '" . $this->db->escape((string)$data['tax']) . "', `payment_method` = '" . $this->db->escape((string)$data['payment_method']) . "', `cheque` = '" . $this->db->escape((string)$data['cheque']) . "', `paypal` = '" . $this->db->escape((string)$data['paypal']) . "', `bank_name` = '" . $this->db->escape((string)$data['bank_name']) . "', `bank_branch_number` = '" . $this->db->escape((string)$data['bank_branch_number']) . "', `bank_swift_code` = '" . $this->db->escape((string)$data['bank_swift_code']) . "', `bank_account_name` = '" . $this->db->escape((string)$data['bank_account_name']) . "', `bank_account_number` = '" . $this->db->escape((string)$data['bank_account_number']) . "', `custom_field` = '" . $this->db->escape(isset($data['custom_field']) ? json_encode($data['custom_field']) : json_encode([])) . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "', `date_added` = NOW()"); + } + + /** + * @param int $customer_id + * @param array $data + * + * @return void + */ + public function editAffiliate(int $customer_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "customer_affiliate` SET `company` = '" . $this->db->escape((string)$data['company']) . "', `website` = '" . $this->db->escape((string)$data['website']) . "', `tracking` = '" . $this->db->escape((string)$data['tracking']) . "', `commission` = '" . (float)$data['commission'] . "', `tax` = '" . $this->db->escape((string)$data['tax']) . "', `payment_method` = '" . $this->db->escape((string)$data['payment_method']) . "', `cheque` = '" . $this->db->escape((string)$data['cheque']) . "', `paypal` = '" . $this->db->escape((string)$data['paypal']) . "', `bank_name` = '" . $this->db->escape((string)$data['bank_name']) . "', `bank_branch_number` = '" . $this->db->escape((string)$data['bank_branch_number']) . "', `bank_swift_code` = '" . $this->db->escape((string)$data['bank_swift_code']) . "', `bank_account_name` = '" . $this->db->escape((string)$data['bank_account_name']) . "', `bank_account_number` = '" . $this->db->escape((string)$data['bank_account_number']) . "', `custom_field` = '" . $this->db->escape(isset($data['custom_field']) ? json_encode($data['custom_field']) : json_encode([])) . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "' WHERE `customer_id` = '" . (int)$customer_id . "'"); + } + + /** + * @param int $customer_id + * @param float $amount + * + * @return void + */ + public function editBalance(int $customer_id, float $amount): void { + $this->db->query("UPDATE `" . DB_PREFIX . "customer_affiliate` SET `balance` = '" . (float)$amount . "' WHERE `customer_id` = '" . (int)$customer_id . "'"); + } + + /** + * @param int $customer_id + * + * @return void + */ + public function deleteAffiliate(int $customer_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_affiliate` WHERE `customer_id` = '" . (int)$customer_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_affiliate_report` WHERE `customer_id` = '" . (int)$customer_id . "'"); + } + + /** + * @param int $customer_id + * + * @return array + */ + public function getAffiliate(int $customer_id): array { + $query = $this->db->query("SELECT DISTINCT *, CONCAT(c.`firstname`, ' ', c.`lastname`) AS `customer`, ca.`custom_field` FROM `" . DB_PREFIX . "customer_affiliate` ca LEFT JOIN `" . DB_PREFIX . "customer` c ON (ca.`customer_id` = c.`customer_id`) WHERE ca.`customer_id` = '" . (int)$customer_id . "'"); + + return $query->row; + } + + /** + * @param string $tracking + * + * @return array + */ + public function getAffiliateByTracking(string $tracking): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "customer_affiliate` WHERE `tracking` = '" . $this->db->escape($tracking) . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getAffiliates(array $data = []): array { + $sql = "SELECT *, CONCAT(`c`.`firstname`, ' ', `c`.`lastname`) AS `name`, `ca`.`status` FROM `" . DB_PREFIX . "customer_affiliate` `ca` LEFT JOIN `" . DB_PREFIX . "customer` `c` ON (`ca`.`customer_id` = `c`.`customer_id`)"; + + $implode = []; + + if (!empty($data['filter_name'])) { + $implode[] = "CONCAT(c.`firstname`, ' ', c.`lastname`) LIKE '" . $this->db->escape((string)$data['filter_name'] . '%') . "'"; + } + + if (!empty($data['filter_tracking'])) { + $implode[] = "`ca`.`tracking` = '" . $this->db->escape((string)$data['filter_tracking']) . "'"; + } + + if (!empty($data['filter_payment_method'])) { + $implode[] = "`ca`.`payment_method` = '" . $this->db->escape($data['filter_payment_method']) . "'"; + } + + if (!empty($data['filter_commission'])) { + $implode[] = "`ca`.`commission` = '" . (float)$data['filter_commission'] . "'"; + } + + if (!empty($data['filter_date_from'])) { + $implode[] = "DATE(`ca`.`date_added`) >= DATE('" . $this->db->escape((string)$data['filter_date_from']) . "')"; + } + + if (!empty($data['filter_date_to'])) { + $implode[] = "DATE(`ca.``date_added`) <= DATE('" . $this->db->escape((string)$data['filter_date_to']) . "')"; + } + + if (isset($data['filter_status']) && $data['filter_status'] !== '') { + $implode[] = "`ca`.`status` = '" . (int)$data['filter_status'] . "'"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $sort_data = [ + 'name', + 'ca.tracking', + 'ca.commission', + 'ca.status', + 'ca.date_added' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `name`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param array $data + * + * @return int + */ + public function getTotalAffiliates(array $data = []): int { + $sql = "SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "customer_affiliate` ca LEFT JOIN `" . DB_PREFIX . "customer` c ON (ca.`customer_id` = c.`customer_id`)"; + + $implode = []; + + if (!empty($data['filter_name'])) { + $implode[] = "CONCAT(`c`.`firstname`, ' ', `c`.`lastname`) LIKE '" . $this->db->escape((string)$data['filter_name'] . '%') . "'"; + } + + if (!empty($data['filter_tracking'])) { + $implode[] = "`ca`.`tracking` = '" . $this->db->escape((string)$data['filter_tracking']) . "'"; + } + + if (!empty($data['filter_payment_method'])) { + $implode[] = "`ca`.`payment_method` = '" . $this->db->escape($data['filter_payment_method']) . "'"; + } + + if (!empty($data['filter_commission'])) { + $implode[] = "`ca`.`commission` = '" . (float)$data['filter_commission'] . "'"; + } + + if (!empty($data['filter_date_from'])) { + $implode[] = "DATE(`ca`.`date_added`) >= DATE('" . $this->db->escape((string)$data['filter_date_from']) . "')"; + } + + if (!empty($data['filter_date_to'])) { + $implode[] = "DATE(`ca`.`date_added`) <= DATE('" . $this->db->escape((string)$data['filter_date_to']) . "')"; + } + + if (isset($data['filter_status']) && $data['filter_status'] !== '') { + $implode[] = "`ca`.`status` = '" . (int)$data['filter_status'] . "'"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $query = $this->db->query($sql); + + return (int)$query->row['total']; + } + + /** + * @param int $customer_id + * @param int $start + * @param int $limit + * + * @return array + */ + public function getReports(int $customer_id, int $start = 0, int $limit = 10): array { + if ($start < 0) { + $start = 0; + } + + if ($limit < 1) { + $limit = 10; + } + + $query = $this->db->query("SELECT `ip`, `store_id`, `country`, `date_added` FROM `" . DB_PREFIX . "customer_affiliate_report` WHERE `customer_id` = '" . (int)$customer_id . "' ORDER BY `date_added` ASC LIMIT " . (int)$start . "," . (int)$limit); + + return $query->rows; + } + + /** + * @param int $customer_id + * + * @return int + */ + public function getTotalReports(int $customer_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "customer_affiliate_report` WHERE `customer_id` = '" . (int)$customer_id . "'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/marketing/coupon.php b/admininistrator/model/marketing/coupon.php new file mode 100644 index 0000000..c8f5d11 --- /dev/null +++ b/admininistrator/model/marketing/coupon.php @@ -0,0 +1,214 @@ +db->query("INSERT INTO `" . DB_PREFIX . "coupon` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `code` = '" . $this->db->escape((string)$data['code']) . "', `discount` = '" . (float)$data['discount'] . "', `type` = '" . $this->db->escape((string)$data['type']) . "', `total` = '" . (float)$data['total'] . "', `logged` = '" . (isset($data['logged']) ? (bool)$data['logged'] : 0) . "', `shipping` = '" . (isset($data['shipping']) ? (bool)$data['shipping'] : 0) . "', `date_start` = '" . $this->db->escape((string)$data['date_start']) . "', `date_end` = '" . $this->db->escape((string)$data['date_end']) . "', `uses_total` = '" . (int)$data['uses_total'] . "', `uses_customer` = '" . (int)$data['uses_customer'] . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "', `date_added` = NOW()"); + + $coupon_id = $this->db->getLastId(); + + if (isset($data['coupon_product'])) { + foreach ($data['coupon_product'] as $product_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "coupon_product` SET `coupon_id` = '" . (int)$coupon_id . "', `product_id` = '" . (int)$product_id . "'"); + } + } + + if (isset($data['coupon_category'])) { + foreach ($data['coupon_category'] as $category_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "coupon_category` SET `coupon_id` = '" . (int)$coupon_id . "', `category_id` = '" . (int)$category_id . "'"); + } + } + + return $coupon_id; + } + + /** + * @param int $coupon_id + * @param array $data + * + * @return void + */ + public function editCoupon(int $coupon_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "coupon` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `code` = '" . $this->db->escape((string)$data['code']) . "', `discount` = '" . (float)$data['discount'] . "', `type` = '" . $this->db->escape((string)$data['type']) . "', `total` = '" . (float)$data['total'] . "', `logged` = '" . (isset($data['logged']) ? (bool)$data['logged'] : 0) . "', `shipping` = '" . (isset($data['shipping']) ? (bool)$data['shipping'] : 0) . "', `date_start` = '" . $this->db->escape((string)$data['date_start']) . "', `date_end` = '" . $this->db->escape((string)$data['date_end']) . "', `uses_total` = '" . (int)$data['uses_total'] . "', `uses_customer` = '" . (int)$data['uses_customer'] . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "' WHERE `coupon_id` = '" . (int)$coupon_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "coupon_product` WHERE `coupon_id` = '" . (int)$coupon_id . "'"); + + if (isset($data['coupon_product'])) { + foreach ($data['coupon_product'] as $product_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "coupon_product` SET `coupon_id` = '" . (int)$coupon_id . "', `product_id` = '" . (int)$product_id . "'"); + } + } + + $this->db->query("DELETE FROM `" . DB_PREFIX . "coupon_category` WHERE `coupon_id` = '" . (int)$coupon_id . "'"); + + if (isset($data['coupon_category'])) { + foreach ($data['coupon_category'] as $category_id) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "coupon_category` SET `coupon_id` = '" . (int)$coupon_id . "', `category_id` = '" . (int)$category_id . "'"); + } + } + } + + /** + * @param int $coupon_id + * + * @return void + */ + public function deleteCoupon(int $coupon_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "coupon` WHERE `coupon_id` = '" . (int)$coupon_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "coupon_product` WHERE `coupon_id` = '" . (int)$coupon_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "coupon_category` WHERE `coupon_id` = '" . (int)$coupon_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "coupon_history` WHERE `coupon_id` = '" . (int)$coupon_id . "'"); + } + + /** + * @param int $coupon_id + * + * @return array + */ + public function getCoupon(int $coupon_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "coupon` WHERE `coupon_id` = '" . (int)$coupon_id . "'"); + + return $query->row; + } + + /** + * @param string $code + * + * @return array + */ + public function getCouponByCode(string $code): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "coupon` WHERE `code` = '" . $this->db->escape($code) . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getCoupons(array $data = []): array { + $sql = "SELECT `coupon_id`, `name`, `code`, `discount`, `date_start`, `date_end`, `status` FROM `" . DB_PREFIX . "coupon`"; + + $sort_data = [ + 'name', + 'code', + 'discount', + 'date_start', + 'date_end', + 'status' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `name`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param int $coupon_id + * + * @return array + */ + public function getProducts(int $coupon_id): array { + $coupon_product_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "coupon_product` WHERE `coupon_id` = '" . (int)$coupon_id . "'"); + + foreach ($query->rows as $result) { + $coupon_product_data[] = $result['product_id']; + } + + return $coupon_product_data; + } + + /** + * @param int $coupon_id + * + * @return array + */ + public function getCategories(int $coupon_id): array { + $coupon_category_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "coupon_category` WHERE `coupon_id` = '" . (int)$coupon_id . "'"); + + foreach ($query->rows as $result) { + $coupon_category_data[] = $result['category_id']; + } + + return $coupon_category_data; + } + + /** + * @return int + */ + public function getTotalCoupons(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "coupon`"); + + return (int)$query->row['total']; + } + + /** + * @param int $coupon_id + * @param int $start + * @param int $limit + * + * @return array + */ + public function getHistories(int $coupon_id, int $start = 0, int $limit = 10): array { + if ($start < 0) { + $start = 0; + } + + if ($limit < 1) { + $limit = 10; + } + + $query = $this->db->query("SELECT ch.`order_id`, CONCAT(c.`firstname`, ' ', c.`lastname`) AS customer, ch.`amount`, ch.`date_added` FROM `" . DB_PREFIX . "coupon_history` ch LEFT JOIN `" . DB_PREFIX . "customer` c ON (ch.`customer_id` = c.`customer_id`) WHERE ch.`coupon_id` = '" . (int)$coupon_id . "' ORDER BY ch.`date_added` ASC LIMIT " . (int)$start . "," . (int)$limit); + + return $query->rows; + } + + /** + * @param int $coupon_id + * + * @return int + */ + public function getTotalHistories(int $coupon_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "coupon_history` WHERE `coupon_id` = '" . (int)$coupon_id . "'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/marketing/marketing.php b/admininistrator/model/marketing/marketing.php new file mode 100644 index 0000000..ec879f0 --- /dev/null +++ b/admininistrator/model/marketing/marketing.php @@ -0,0 +1,200 @@ +db->query("INSERT INTO `" . DB_PREFIX . "marketing` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `description` = '" . $this->db->escape((string)$data['description']) . "', `code` = '" . $this->db->escape((string)$data['code']) . "', `date_added` = NOW()"); + + return $this->db->getLastId(); + } + + /** + * @param int $marketing_id + * @param array $data + * + * @return void + */ + public function editMarketing(int $marketing_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "marketing` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `description` = '" . $this->db->escape((string)$data['description']) . "', `code` = '" . $this->db->escape((string)$data['code']) . "' WHERE `marketing_id` = '" . (int)$marketing_id . "'"); + } + + /** + * @param int $marketing_id + * + * @return void + */ + public function deleteMarketing(int $marketing_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "marketing` WHERE `marketing_id` = '" . (int)$marketing_id . "'"); + } + + /** + * @param int $marketing_id + * + * @return array + */ + public function getMarketing(int $marketing_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "marketing` WHERE `marketing_id` = '" . (int)$marketing_id . "'"); + + return $query->row; + } + + /** + * @param string $code + * + * @return array + */ + public function getMarketingByCode(string $code): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "marketing` WHERE `code` = '" . $this->db->escape($code) . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getMarketings(array $data = []): array { + $implode = []; + + $order_statuses = $this->config->get('config_complete_status'); + + foreach ($order_statuses as $order_status_id) { + $implode[] = "o.`order_status_id` = '" . (int)$order_status_id . "'"; + } + + $sql = "SELECT *, (SELECT COUNT(*) FROM `" . DB_PREFIX . "order` o WHERE (" . implode(" OR ", $implode) . ") AND o.`marketing_id` = m.`marketing_id`) AS `orders` FROM `" . DB_PREFIX . "marketing` m"; + + $implode = []; + + if (!empty($data['filter_name'])) { + $implode[] = "m.`name` LIKE '" . $this->db->escape((string)$data['filter_name'] . '%') . "'"; + } + + if (!empty($data['filter_code'])) { + $implode[] = "m.`code` = '" . $this->db->escape((string)$data['filter_code']) . "'"; + } + + if (!empty($data['filter_date_from'])) { + $implode[] = "DATE(m.`date_added`) >= DATE('" . $this->db->escape((string)$data['filter_date_from']) . "')"; + } + + if (!empty($data['filter_date_to'])) { + $implode[] = "DATE(m.`date_added`) <= DATE('" . $this->db->escape((string)$data['filter_date_to']) . "')"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $sort_data = [ + 'm.name', + 'm.code', + 'm.date_added' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY m.`name`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param array $data + * + * @return int + */ + public function getTotalMarketings(array $data = []): int { + $sql = "SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "marketing`"; + + $implode = []; + + if (!empty($data['filter_name'])) { + $implode[] = "`name` LIKE '" . $this->db->escape((string)$data['filter_name']) . "'"; + } + + if (!empty($data['filter_code'])) { + $implode[] = "`code` = '" . $this->db->escape((string)$data['filter_code']) . "'"; + } + + if (!empty($data['filter_date_from'])) { + $implode[] = "DATE(`date_added`) >= DATE('" . $this->db->escape((string)$data['filter_date_from']) . "')"; + } + + if (!empty($data['filter_date_to'])) { + $implode[] = "DATE(`date_added`) <= DATE('" . $this->db->escape((string)$data['filter_date_to']) . "')"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $query = $this->db->query($sql); + + return (int)$query->row['total']; + } + + /** + * @param int $marketing_id + * @param int $start + * @param int $limit + * + * @return array + */ + public function getReports(int $marketing_id, int $start = 0, int $limit = 10): array { + if ($start < 0) { + $start = 0; + } + + if ($limit < 1) { + $limit = 10; + } + + $query = $this->db->query("SELECT `ip`, `store_id`, `country`, `date_added` FROM `" . DB_PREFIX . "marketing_report` WHERE `marketing_id` = '" . (int)$marketing_id . "' ORDER BY `date_added` ASC LIMIT " . (int)$start . "," . (int)$limit); + + return $query->rows; + } + + /** + * @param int $marketing_id + * + * @return int + */ + public function getTotalReports(int $marketing_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "marketing_report` WHERE `marketing_id` = '" . (int)$marketing_id . "'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/report/online.php b/admininistrator/model/report/online.php new file mode 100644 index 0000000..e1ea0d2 --- /dev/null +++ b/admininistrator/model/report/online.php @@ -0,0 +1,76 @@ +db->escape((string)$data['filter_ip']) . "'"; + } + + if (!empty($data['filter_customer'])) { + $implode[] = "`co`.`customer_id` > '0' AND CONCAT(`c`.`firstname`, ' ', `c`.`lastname`) LIKE '" . $this->db->escape((string)$data['filter_customer']) . "'"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $sql .= " ORDER BY `co`.`date_added` DESC"; + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param array $data + * + * @return int + */ + public function getTotalOnline(array $data = []): int { + $sql = "SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "customer_online` `co` LEFT JOIN `" . DB_PREFIX . "customer` `c` ON (`co`.`customer_id` = `c`.`customer_id`)"; + + $implode = []; + + if (!empty($data['filter_ip'])) { + $implode[] = "`co`.`ip` LIKE '" . $this->db->escape((string)$data['filter_ip']) . "'"; + } + + if (!empty($data['filter_customer'])) { + $implode[] = "`co`.`customer_id` > '0' AND CONCAT(`c`.`firstname`, ' ', `c`.`lastname`) LIKE '" . $this->db->escape((string)$data['filter_customer']) . "'"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $query = $this->db->query($sql); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/report/statistics.php b/admininistrator/model/report/statistics.php new file mode 100644 index 0000000..ec62f41 --- /dev/null +++ b/admininistrator/model/report/statistics.php @@ -0,0 +1,62 @@ +db->query("SELECT * FROM `" . DB_PREFIX . "statistics`"); + + return $query->rows; + } + + /** + * @param string $code + * + * @return float + */ + public function getValue(string $code): float { + $query = $this->db->query("SELECT `value` FROM `" . DB_PREFIX . "statistics` WHERE `code` = '" . $this->db->escape($code) . "'"); + + if ($query->num_rows) { + return $query->row['value']; + } else { + return 0; + } + } + + /** + * @param string $code + * @param float $value + * + * @return void + */ + public function addValue(string $code, float $value): void { + $this->db->query("UPDATE `" . DB_PREFIX . "statistics` SET `value` = (`value` + '" . (float)$value . "') WHERE `code` = '" . $this->db->escape($code) . "'"); + } + + /** + * @param string $code + * @param float $value + * + * @return void + */ + public function removeValue(string $code, float $value): void { + $this->db->query("UPDATE `" . DB_PREFIX . "statistics` SET `value` = (`value` - '" . (float)$value . "') WHERE `code` = '" . $this->db->escape($code) . "'"); + } + + /** + * @param string $code + * @param float $value + * + * @return void + */ + public function editValue(string $code, float $value): void { + $this->db->query("UPDATE `" . DB_PREFIX . "statistics` SET `value` = '" . (float)$value . "' WHERE `code` = '" . $this->db->escape($code) . "'"); + } +} diff --git a/admininistrator/model/sale/order.php b/admininistrator/model/sale/order.php new file mode 100644 index 0000000..a05a3b3 --- /dev/null +++ b/admininistrator/model/sale/order.php @@ -0,0 +1,701 @@ +db->query("SELECT *, (SELECT `os`.`name` FROM `" . DB_PREFIX . "order_status` os WHERE `os`.`order_status_id` = `o`.`order_status_id` AND `os`.`language_id` = '" . (int)$this->config->get('config_language_id') . "') AS `order_status` FROM `" . DB_PREFIX . "order` `o` WHERE `o`.`order_id` = '" . (int)$order_id . "'"); + + if ($order_query->num_rows) { + $country_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "country` WHERE `country_id` = '" . (int)$order_query->row['payment_country_id'] . "'"); + + if ($country_query->num_rows) { + $payment_iso_code_2 = $country_query->row['iso_code_2']; + $payment_iso_code_3 = $country_query->row['iso_code_3']; + } else { + $payment_iso_code_2 = ''; + $payment_iso_code_3 = ''; + } + + $zone_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "zone` WHERE `zone_id` = '" . (int)$order_query->row['payment_zone_id'] . "'"); + + if ($zone_query->num_rows) { + $payment_zone_code = $zone_query->row['code']; + } else { + $payment_zone_code = ''; + } + + $country_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "country` WHERE `country_id` = '" . (int)$order_query->row['shipping_country_id'] . "'"); + + if ($country_query->num_rows) { + $shipping_iso_code_2 = $country_query->row['iso_code_2']; + $shipping_iso_code_3 = $country_query->row['iso_code_3']; + } else { + $shipping_iso_code_2 = ''; + $shipping_iso_code_3 = ''; + } + + $zone_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "zone` WHERE `zone_id` = '" . (int)$order_query->row['shipping_zone_id'] . "'"); + + if ($zone_query->num_rows) { + $shipping_zone_code = $zone_query->row['code']; + } else { + $shipping_zone_code = ''; + } + + $reward = 0; + + $order_product_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "order_product` WHERE `order_id` = '" . (int)$order_id . "'"); + + foreach ($order_product_query->rows as $product) { + $reward += $product['reward']; + } + + $this->load->model('customer/customer'); + + $affiliate_info = $this->model_customer_customer->getCustomer($order_query->row['affiliate_id']); + + if ($affiliate_info) { + $affiliate = $affiliate_info['firstname'] . ' ' . $affiliate_info['lastname']; + } else { + $affiliate = ''; + } + + $this->load->model('localisation/language'); + + $language_info = $this->model_localisation_language->getLanguage($order_query->row['language_id']); + + if ($language_info) { + $language_code = $language_info['code']; + } else { + $language_code = $this->config->get('config_language'); + } + + return [ + 'order_id' => $order_query->row['order_id'], + 'invoice_no' => $order_query->row['invoice_no'], + 'invoice_prefix' => $order_query->row['invoice_prefix'], + 'store_id' => $order_query->row['store_id'], + 'store_name' => $order_query->row['store_name'], + 'store_url' => $order_query->row['store_url'], + 'customer_id' => $order_query->row['customer_id'], + 'customer_group_id' => $order_query->row['customer_group_id'], + 'firstname' => $order_query->row['firstname'], + 'lastname' => $order_query->row['lastname'], + 'email' => $order_query->row['email'], + 'telephone' => $order_query->row['telephone'], + 'custom_field' => json_decode($order_query->row['custom_field'], true), + 'payment_address_id' => $order_query->row['payment_address_id'], + 'payment_firstname' => $order_query->row['payment_firstname'], + 'payment_lastname' => $order_query->row['payment_lastname'], + 'payment_company' => $order_query->row['payment_company'], + 'payment_address_1' => $order_query->row['payment_address_1'], + 'payment_address_2' => $order_query->row['payment_address_2'], + 'payment_postcode' => $order_query->row['payment_postcode'], + 'payment_city' => $order_query->row['payment_city'], + 'payment_zone_id' => $order_query->row['payment_zone_id'], + 'payment_zone' => $order_query->row['payment_zone'], + 'payment_zone_code' => $payment_zone_code, + 'payment_country_id' => $order_query->row['payment_country_id'], + 'payment_country' => $order_query->row['payment_country'], + 'payment_iso_code_2' => $payment_iso_code_2, + 'payment_iso_code_3' => $payment_iso_code_3, + 'payment_address_format' => $order_query->row['payment_address_format'], + 'payment_custom_field' => json_decode($order_query->row['payment_custom_field'], true), + 'payment_method' => json_decode($order_query->row['payment_method'], true), + 'shipping_address_id' => $order_query->row['shipping_address_id'], + 'shipping_firstname' => $order_query->row['shipping_firstname'], + 'shipping_lastname' => $order_query->row['shipping_lastname'], + 'shipping_company' => $order_query->row['shipping_company'], + 'shipping_address_1' => $order_query->row['shipping_address_1'], + 'shipping_address_2' => $order_query->row['shipping_address_2'], + 'shipping_postcode' => $order_query->row['shipping_postcode'], + 'shipping_city' => $order_query->row['shipping_city'], + 'shipping_zone_id' => $order_query->row['shipping_zone_id'], + 'shipping_zone' => $order_query->row['shipping_zone'], + 'shipping_zone_code' => $shipping_zone_code, + 'shipping_country_id' => $order_query->row['shipping_country_id'], + 'shipping_country' => $order_query->row['shipping_country'], + 'shipping_iso_code_2' => $shipping_iso_code_2, + 'shipping_iso_code_3' => $shipping_iso_code_3, + 'shipping_address_format' => $order_query->row['shipping_address_format'], + 'shipping_custom_field' => json_decode($order_query->row['shipping_custom_field'], true), + 'shipping_method' => json_decode($order_query->row['shipping_method'], true), + 'comment' => $order_query->row['comment'], + 'total' => $order_query->row['total'], + 'reward' => $reward, + 'order_status_id' => $order_query->row['order_status_id'], + 'order_status' => $order_query->row['order_status'], + 'affiliate_id' => $order_query->row['affiliate_id'], + 'affiliate' => $affiliate, + 'commission' => $order_query->row['commission'], + 'language_id' => $order_query->row['language_id'], + 'language_code' => $language_code, + 'currency_id' => $order_query->row['currency_id'], + 'currency_code' => $order_query->row['currency_code'], + 'currency_value' => $order_query->row['currency_value'], + 'ip' => $order_query->row['ip'], + 'forwarded_ip' => $order_query->row['forwarded_ip'], + 'user_agent' => $order_query->row['user_agent'], + 'accept_language' => $order_query->row['accept_language'], + 'date_added' => $order_query->row['date_added'], + 'date_modified' => $order_query->row['date_modified'] + ]; + } else { + return []; + } + } + + /** + * @param array $data + * + * @return array + */ + public function getOrders(array $data = []): array { + $sql = "SELECT o.`order_id`, CONCAT(o.`firstname`, ' ', o.`lastname`) AS customer, (SELECT os.`name` FROM `" . DB_PREFIX . "order_status` os WHERE os.`order_status_id` = o.`order_status_id` AND os.`language_id` = '" . (int)$this->config->get('config_language_id') . "') AS order_status, o.`store_name`, o.`shipping_method`, o.`total`, o.`currency_code`, o.`currency_value`, o.`date_added`, o.`date_modified` FROM `" . DB_PREFIX . "order` o"; + + if (!empty($data['filter_order_status'])) { + $implode = []; + + $order_statuses = explode(',', $data['filter_order_status']); + + foreach ($order_statuses as $order_status_id) { + $implode[] = "o.`order_status_id` = '" . (int)$order_status_id . "'"; + } + + if ($implode) { + $sql .= " WHERE (" . implode(" OR ", $implode) . ")"; + } + } elseif (isset($data['filter_order_status_id']) && $data['filter_order_status_id'] !== '') { + $sql .= " WHERE o.`order_status_id` = '" . (int)$data['filter_order_status_id'] . "'"; + } else { + $sql .= " WHERE o.`order_status_id` > '0'"; + } + + if (!empty($data['filter_order_id'])) { + $sql .= " AND o.`order_id` = '" . (int)$data['filter_order_id'] . "'"; + } + + if (isset($data['filter_store_id']) && $data['filter_store_id'] !== '') { + $sql .= " AND o.`store_id` = '" . (int)$data['filter_store_id'] . "'"; + } + + if (!empty($data['filter_customer_id'])) { + $sql .= " AND o.`customer_id` = '" . (int)$data['filter_customer_id'] . "'"; + } + + if (!empty($data['filter_customer'])) { + $sql .= " AND CONCAT(o.`firstname`, ' ', o.`lastname`) LIKE '" . $this->db->escape('%' . (string)$data['filter_customer'] . '%') . "'"; + } + + if (!empty($data['filter_email'])) { + $sql .= " AND o.`email` LIKE '" . $this->db->escape('%' . (string)$data['filter_email'] . '%') . "'"; + } + + if (!empty($data['filter_date_from'])) { + $sql .= " AND DATE(o.`date_added`) >= DATE('" . $this->db->escape((string)$data['filter_date_from']) . "')"; + } + + if (!empty($data['filter_date_to'])) { + $sql .= " AND DATE(o.`date_added`) <= DATE('" . $this->db->escape((string)$data['filter_date_to']) . "')"; + } + + if (!empty($data['filter_total'])) { + $sql .= " AND o.`total` = '" . (float)$data['filter_total'] . "'"; + } + + $sort_data = [ + 'o.order_id', + 'o.store_name', + 'customer', + 'order_status', + 'o.date_added', + 'o.date_modified', + 'o.total' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY o.`order_id`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param int $subscription_id + * + * @return array + */ + public function getOrdersBySubscriptionId(int $subscription_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "order` WHERE `subscription_id` = '" . (int)$subscription_id . "'"); + + return $query->rows; + } + + /** + * @param int $subscription_id + * + * @return int + */ + public function getTotalOrdersBySubscriptionId(int $subscription_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "order` WHERE `subscription_id` = '" . (int)$subscription_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $order_id + * + * @return array + */ + public function getProducts(int $order_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "order_product` WHERE `order_id` = '" . (int)$order_id . "' ORDER BY order_product_id ASC"); + + return $query->rows; + } + + /** + * @param int $product_id + * + * @return int + */ + public function getTotalProductsByProductId(int $product_id): int { + $sql = "SELECT SUM(op.quantity) AS `total` FROM `" . DB_PREFIX . "order_product` `op` LEFT JOIN `" . DB_PREFIX . "order` `o` ON (`op`.`order_id` = `o`.`order_id`) WHERE `op`.`product_id` = '" . (int)$product_id . "'"; + + if (!empty($data['filter_order_status'])) { + $implode = []; + + $order_statuses = explode(',', $data['filter_order_status']); + + foreach ($order_statuses as $order_status_id) { + $implode[] = "`order_status_id` = '" . (int)$order_status_id . "'"; + } + + if ($implode) { + $sql .= " AND (" . implode(" OR ", $implode) . ")"; + } + } elseif (isset($data['filter_order_status_id']) && $data['filter_order_status_id'] !== '') { + $sql .= " AND `order_status_id` = '" . (int)$data['filter_order_status_id'] . "'"; + } else { + $sql .= " AND `order_status_id` > '0'"; + } + + $query = $this->db->query($sql); + + return (int)$query->row['total']; + } + + /** + * @param int $order_id + * @param int $order_product_id + * + * @return array + */ + public function getOptions(int $order_id, int $order_product_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "order_option` WHERE `order_id` = '" . (int)$order_id . "' AND `order_product_id` = '" . (int)$order_product_id . "'"); + + return $query->rows; + } + + /** + * @param int $order_id + * @param int $order_product_id + * + * @return array + */ + public function getSubscription(int $order_id, int $order_product_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "order_subscription` WHERE `order_id` = '" . (int)$order_id . "' AND `order_product_id` = '" . (int)$order_product_id . "'"); + + return $query->row; + } + + /** + * @param int $order_id + * + * @return array + */ + public function getVouchers(int $order_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "order_voucher` WHERE `order_id` = '" . (int)$order_id . "'"); + + return $query->rows; + } + + /** + * @param int $voucher_id + * + * @return array + */ + public function getVoucherByVoucherId(int $voucher_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "order_voucher` WHERE `voucher_id` = '" . (int)$voucher_id . "'"); + + return $query->row; + } + + /** + * @param int $order_id + * + * @return array + */ + public function getTotals(int $order_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "order_total` WHERE `order_id` = '" . (int)$order_id . "' ORDER BY `sort_order`"); + + return $query->rows; + } + + /** + * @param array $data + * + * @return int + */ + public function getTotalOrders(array $data = []): int { + $sql = "SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "order`"; + + if (!empty($data['filter_order_status'])) { + $implode = []; + + $order_statuses = explode(',', $data['filter_order_status']); + + foreach ($order_statuses as $order_status_id) { + $implode[] = "`order_status_id` = '" . (int)$order_status_id . "'"; + } + + if ($implode) { + $sql .= " WHERE (" . implode(" OR ", $implode) . ")"; + } + } elseif (isset($data['filter_order_status_id']) && $data['filter_order_status_id'] !== '') { + $sql .= " WHERE `order_status_id` = '" . (int)$data['filter_order_status_id'] . "'"; + } else { + $sql .= " WHERE `order_status_id` > '0'"; + } + + if (!empty($data['filter_order_id'])) { + $sql .= " AND `order_id` = '" . (int)$data['filter_order_id'] . "'"; + } + + if (isset($data['filter_store_id']) && $data['filter_store_id'] !== '') { + $sql .= " AND `store_id` = '" . (int)$data['filter_store_id'] . "'"; + } + + if (!empty($data['filter_customer_id'])) { + $sql .= " AND `customer_id` = '" . (int)$data['filter_customer_id'] . "'"; + } + + if (!empty($data['filter_customer'])) { + $sql .= " AND CONCAT(`firstname`, ' ', `lastname`) LIKE '" . $this->db->escape('%' . (string)$data['filter_customer'] . '%') . "'"; + } + + if (!empty($data['filter_email'])) { + $sql .= " AND `email` LIKE '" . $this->db->escape('%' . (string)$data['filter_email'] . '%') . "'"; + } + + if (!empty($data['filter_date_from'])) { + $sql .= " AND DATE(`date_added`) >= DATE('" . $this->db->escape((string)$data['filter_date_from']) . "')"; + } + + if (!empty($data['filter_date_to'])) { + $sql .= " AND DATE(`date_added`) <= DATE('" . $this->db->escape((string)$data['filter_date_to']) . "')"; + } + + if (!empty($data['filter_total'])) { + $sql .= " AND `total` = '" . (float)$data['filter_total'] . "'"; + } + + $query = $this->db->query($sql); + + return (int)$query->row['total']; + } + + /** + * @param int $store_id + * + * @return int + */ + public function getTotalOrdersByStoreId(int $store_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "order` WHERE `store_id` = '" . (int)$store_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $order_status_id + * + * @return int + */ + public function getTotalOrdersByOrderStatusId(int $order_status_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "order` WHERE `order_status_id` = '" . (int)$order_status_id . "' AND `order_status_id` > '0'"); + + return (int)$query->row['total']; + } + + /** + * @return int + */ + public function getTotalOrdersByProcessingStatus(): int { + $implode = []; + + $order_statuses = $this->config->get('config_processing_status'); + + foreach ($order_statuses as $order_status_id) { + $implode[] = "`order_status_id` = '" . (int)$order_status_id . "'"; + } + + if ($implode) { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "order` WHERE " . implode(" OR ", $implode)); + + return (int)$query->row['total']; + } else { + return 0; + } + } + + /** + * @return int + */ + public function getTotalOrdersByCompleteStatus(): int { + $implode = []; + + $order_statuses = $this->config->get('config_complete_status'); + + foreach ($order_statuses as $order_status_id) { + $implode[] = "`order_status_id` = '" . (int)$order_status_id . "'"; + } + + if ($implode) { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "order` WHERE " . implode(" OR ", $implode) . ""); + + return (int)$query->row['total']; + } else { + return 0; + } + } + + /** + * @param int $language_id + * + * @return int + */ + public function getTotalOrdersByLanguageId(int $language_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "order` WHERE `language_id` = '" . (int)$language_id . "' AND `order_status_id` > '0'"); + + return (int)$query->row['total']; + } + + /** + * @param int $currency_id + * + * @return int + */ + public function getTotalOrdersByCurrencyId(int $currency_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "order` WHERE `currency_id` = '" . (int)$currency_id . "' AND `order_status_id` > '0'"); + + return (int)$query->row['total']; + } + + /** + * @param array $data + * + * @return float + */ + public function getTotalSales(array $data = []): float { + $sql = "SELECT SUM(`total`) AS `total` FROM `" . DB_PREFIX . "order`"; + + if (!empty($data['filter_order_status'])) { + $implode = []; + + $order_statuses = explode(',', $data['filter_order_status']); + + foreach ($order_statuses as $order_status_id) { + $implode[] = "`order_status_id` = '" . (int)$order_status_id . "'"; + } + + if ($implode) { + $sql .= " WHERE (" . implode(" OR ", $implode) . ")"; + } + } elseif (isset($data['filter_order_status_id']) && $data['filter_order_status_id'] !== '') { + $sql .= " WHERE `order_status_id` = '" . (int)$data['filter_order_status_id'] . "'"; + } else { + $sql .= " WHERE `order_status_id` > '0'"; + } + + if (!empty($data['filter_order_id'])) { + $sql .= " AND `order_id` = '" . (int)$data['filter_order_id'] . "'"; + } + + if (isset($data['filter_store_id']) && $data['filter_store_id'] !== '') { + $sql .= " AND `store_id` = '" . (int)$data['filter_store_id'] . "'"; + } + + if (!empty($data['filter_customer_id'])) { + $sql .= " AND `customer_id` = '" . (int)$data['filter_customer_id'] . "'"; + } + + if (!empty($data['filter_customer'])) { + $sql .= " AND CONCAT(`firstname`, ' ', `lastname`) LIKE '" . $this->db->escape('%' . (string)$data['filter_customer'] . '%') . "'"; + } + + if (!empty($data['filter_email'])) { + $sql .= " AND `email` LIKE '" . $this->db->escape('%' . (string)$data['filter_email'] . '%') . "'"; + } + + if (!empty($data['filter_date_added'])) { + $sql .= " AND DATE(`date_added`) = DATE('" . $this->db->escape((string)$data['filter_date_added']) . "')"; + } + + if (!empty($data['filter_date_modified'])) { + $sql .= " AND DATE(`date_modified`) = DATE('" . $this->db->escape((string)$data['filter_date_modified']) . "')"; + } + + if (!empty($data['filter_total'])) { + $sql .= " AND `total` = '" . (float)$data['filter_total'] . "'"; + } + + $query = $this->db->query($sql); + + return (int)$query->row['total']; + } + + /** + * @param int $order_id + * + * @return string + */ + public function createInvoiceNo(int $order_id): string { + $order_info = $this->getOrder($order_id); + + if ($order_info && !$order_info['invoice_no']) { + $query = $this->db->query("SELECT MAX(`invoice_no`) AS invoice_no FROM `" . DB_PREFIX . "order` WHERE `invoice_prefix` = '" . $this->db->escape($order_info['invoice_prefix']) . "'"); + + if ($query->row['invoice_no']) { + $invoice_no = $query->row['invoice_no'] + 1; + } else { + $invoice_no = 1; + } + + $this->db->query("UPDATE `" . DB_PREFIX . "order` SET `invoice_no` = '" . (int)$invoice_no . "', `invoice_prefix` = '" . $this->db->escape($order_info['invoice_prefix']) . "' WHERE `order_id` = '" . (int)$order_id . "'"); + + return $order_info['invoice_prefix'] . $invoice_no; + } + + return ''; + } + + /** + * @param int $order_id + * + * @return int + */ + public function getRewardTotal(int $order_id): int { + $query = $this->db->query("SELECT SUM(reward) AS `total` FROM `" . DB_PREFIX . "order_product` WHERE `order_id` = '" . (int)$order_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $order_id + * @param int $start + * @param int $limit + * + * @return array + */ + public function getHistories(int $order_id, int $start = 0, int $limit = 10): array { + if ($start < 0) { + $start = 0; + } + + if ($limit < 1) { + $limit = 10; + } + + $query = $this->db->query("SELECT oh.`date_added`, os.`name` AS `status`, oh.`comment`, oh.`notify` FROM `" . DB_PREFIX . "order_history` oh LEFT JOIN `" . DB_PREFIX . "order_status` os ON oh.`order_status_id` = os.`order_status_id` WHERE oh.`order_id` = '" . (int)$order_id . "' AND os.`language_id` = '" . (int)$this->config->get('config_language_id') . "' ORDER BY oh.`date_added` DESC LIMIT " . (int)$start . "," . (int)$limit); + + return $query->rows; + } + + /** + * @param int $order_id + * + * @return int + */ + public function getTotalHistories(int $order_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "order_history` WHERE `order_id` = '" . (int)$order_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $order_status_id + * + * @return int + */ + public function getTotalHistoriesByOrderStatusId(int $order_status_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "order_history` WHERE `order_status_id` = '" . (int)$order_status_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param array $products + * @param int $start + * @param int $end + * + * @return array + */ + public function getEmailsByProductsOrdered(array $products, int $start, int $end): array { + $implode = []; + + foreach ($products as $product_id) { + $implode[] = "op.`product_id` = '" . (int)$product_id . "'"; + } + + $query = $this->db->query("SELECT DISTINCT o.`email` FROM `" . DB_PREFIX . "order` o LEFT JOIN `" . DB_PREFIX . "order_product` op ON (o.`order_id` = op.`order_id`) WHERE (" . implode(" OR ", $implode) . ") AND o.`order_status_id` <> '0' LIMIT " . (int)$start . "," . (int)$end); + + return $query->rows; + } + + /** + * @param array $products + * + * @return int + */ + public function getTotalEmailsByProductsOrdered(array $products): int { + $implode = []; + + foreach ($products as $product_id) { + $implode[] = "op.`product_id` = '" . (int)$product_id . "'"; + } + + $query = $this->db->query("SELECT COUNT(DISTINCT o.`email`) AS `total` FROM `" . DB_PREFIX . "order` o LEFT JOIN `" . DB_PREFIX . "order_product` op ON (o.`order_id` = op.`order_id`) WHERE (" . implode(" OR ", $implode) . ") AND o.`order_status_id` <> '0'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/sale/returns.php b/admininistrator/model/sale/returns.php new file mode 100644 index 0000000..421ec0e --- /dev/null +++ b/admininistrator/model/sale/returns.php @@ -0,0 +1,276 @@ +db->query("INSERT INTO `" . DB_PREFIX . "return` SET `order_id` = '" . (int)$data['order_id'] . "', `product_id` = '" . (int)$data['product_id'] . "', `customer_id` = '" . (int)$data['customer_id'] . "', `firstname` = '" . $this->db->escape((string)$data['firstname']) . "', `lastname` = '" . $this->db->escape((string)$data['lastname']) . "', `email` = '" . $this->db->escape((string)$data['email']) . "', `telephone` = '" . $this->db->escape((string)$data['telephone']) . "', `product` = '" . $this->db->escape((string)$data['product']) . "', `model` = '" . $this->db->escape((string)$data['model']) . "', `quantity` = '" . (int)$data['quantity'] . "', `opened` = '" . (int)$data['opened'] . "', `return_reason_id` = '" . (int)$data['return_reason_id'] . "', `return_action_id` = '" . (int)$data['return_action_id'] . "', `return_status_id` = '" . (int)$data['return_status_id'] . "', `comment` = '" . $this->db->escape((string)$data['comment']) . "', `date_ordered` = '" . $this->db->escape((string)$data['date_ordered']) . "', `date_added` = NOW(), `date_modified` = NOW()"); + + return $this->db->getLastId(); + } + + /** + * @param int $return_id + * @param array $data + * + * @return void + */ + public function editReturn(int $return_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "return` SET `order_id` = '" . (int)$data['order_id'] . "', `product_id` = '" . (int)$data['product_id'] . "', `customer_id` = '" . (int)$data['customer_id'] . "', `firstname` = '" . $this->db->escape((string)$data['firstname']) . "', `lastname` = '" . $this->db->escape((string)$data['lastname']) . "', `email` = '" . $this->db->escape((string)$data['email']) . "', `telephone` = '" . $this->db->escape((string)$data['telephone']) . "', `product` = '" . $this->db->escape((string)$data['product']) . "', `model` = '" . $this->db->escape((string)$data['model']) . "', `quantity` = '" . (int)$data['quantity'] . "', `opened` = '" . (int)$data['opened'] . "', `return_reason_id` = '" . (int)$data['return_reason_id'] . "', `return_action_id` = '" . (int)$data['return_action_id'] . "', `comment` = '" . $this->db->escape((string)$data['comment']) . "', `date_ordered` = '" . $this->db->escape((string)$data['date_ordered']) . "', `date_modified` = NOW() WHERE `return_id` = '" . (int)$return_id . "'"); + } + + /** + * @param int $return_id + * + * @return void + */ + public function deleteReturn(int $return_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "return` WHERE `return_id` = '" . (int)$return_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "return_history` WHERE `return_id` = '" . (int)$return_id . "'"); + } + + /** + * @param int $return_id + * + * @return array + */ + public function getReturn(int $return_id): array { + $query = $this->db->query("SELECT DISTINCT *, (SELECT CONCAT(c.`firstname`, ' ', c.`lastname`) FROM `" . DB_PREFIX . "customer` c WHERE c.`customer_id` = r.`customer_id`) AS customer, (SELECT c.`language_id` FROM `" . DB_PREFIX . "customer` c WHERE c.`customer_id` = r.`customer_id`) AS language_id, (SELECT rs.`name` FROM `" . DB_PREFIX . "return_status` rs WHERE rs.`return_status_id` = r.`return_status_id` AND rs.`language_id` = '" . (int)$this->config->get('config_language_id') . "') AS return_status FROM `" . DB_PREFIX . "return` r WHERE r.`return_id` = '" . (int)$return_id . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getReturns(array $data = []): array { + $sql = "SELECT *, CONCAT(r.`firstname`, ' ', r.`lastname`) AS customer, (SELECT rs.`name` FROM `" . DB_PREFIX . "return_status` rs WHERE rs.`return_status_id` = r.`return_status_id` AND rs.`language_id` = '" . (int)$this->config->get('config_language_id') . "') AS return_status FROM `" . DB_PREFIX . "return` r"; + + $implode = []; + + if (!empty($data['filter_return_id'])) { + $implode[] = "r.`return_id` = '" . (int)$data['filter_return_id'] . "'"; + } + + if (!empty($data['filter_order_id'])) { + $implode[] = "r.`order_id` = '" . (int)$data['filter_order_id'] . "'"; + } + + if (!empty($data['filter_customer'])) { + $implode[] = "CONCAT(r.`firstname`, ' ', r.`lastname`) LIKE '" . $this->db->escape((string)$data['filter_customer'] . '%') . "'"; + } + + if (!empty($data['filter_product'])) { + $implode[] = "r.`product` = '" . $this->db->escape((string)$data['filter_product']) . "'"; + } + + if (!empty($data['filter_model'])) { + $implode[] = "r.`model` = '" . $this->db->escape((string)$data['filter_model']) . "'"; + } + + if (!empty($data['filter_return_status_id'])) { + $implode[] = "r.`return_status_id` = '" . (int)$data['filter_return_status_id'] . "'"; + } + + if (!empty($data['filter_date_from'])) { + $implode[] = "DATE(r.`date_added`) >= DATE('" . $this->db->escape((string)$data['filter_date_from']) . "')"; + } + + if (!empty($data['filter_date_to'])) { + $implode[] = "DATE(r.`date_added`) <= DATE('" . $this->db->escape((string)$data['filter_date_to']) . "')"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $sort_data = [ + 'r.return_id', + 'r.order_id', + 'customer', + 'r.product', + 'r.model', + 'return_status', + 'r.date_added', + 'r.date_modified' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY r.`return_id`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param array $data + * + * @return int + */ + public function getTotalReturns(array $data = []): int { + $sql = "SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "return` r"; + + $implode = []; + + if (!empty($data['filter_return_id'])) { + $implode[] = "r.`return_id` = '" . (int)$data['filter_return_id'] . "'"; + } + + if (!empty($data['filter_customer'])) { + $implode[] = "CONCAT(r.`firstname`, ' ', r.`lastname`) LIKE '" . $this->db->escape((string)$data['filter_customer'] . '%') . "'"; + } + + if (!empty($data['filter_order_id'])) { + $implode[] = "r.`order_id` = '" . $this->db->escape((string)$data['filter_order_id']) . "'"; + } + + if (!empty($data['filter_product'])) { + $implode[] = "r.`product` = '" . $this->db->escape((string)$data['filter_product']) . "'"; + } + + if (!empty($data['filter_model'])) { + $implode[] = "r.`model` = '" . $this->db->escape((string)$data['filter_model']) . "'"; + } + + if (!empty($data['filter_return_status_id'])) { + $implode[] = "r.`return_status_id` = '" . (int)$data['filter_return_status_id'] . "'"; + } + + if (!empty($data['filter_date_from'])) { + $implode[] = "DATE(r.`date_added`) >= DATE('" . $this->db->escape((string)$data['filter_date_from']) . "')"; + } + + if (!empty($data['filter_date_to'])) { + $implode[] = "DATE(r.`date_added`) <= DATE('" . $this->db->escape((string)$data['filter_date_to']) . "')"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $query = $this->db->query($sql); + + return (int)$query->row['total']; + } + + /** + * @param int $return_status_id + * + * @return int + */ + public function getTotalReturnsByReturnStatusId(int $return_status_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "return` WHERE `return_status_id` = '" . (int)$return_status_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $return_reason_id + * + * @return int + */ + public function getTotalReturnsByReturnReasonId(int $return_reason_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "return` WHERE `return_reason_id` = '" . (int)$return_reason_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $return_action_id + * + * @return int + */ + public function getTotalReturnsByReturnActionId(int $return_action_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "return` WHERE `return_action_id` = '" . (int)$return_action_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $return_id + * @param int $return_status_id + * @param string $comment + * @param bool $notify + * + * @return void + */ + public function addHistory(int $return_id, int $return_status_id, string $comment, bool $notify): void { + $this->db->query("UPDATE `" . DB_PREFIX . "return` SET `return_status_id` = '" . (int)$return_status_id . "', `date_modified` = NOW() WHERE `return_id` = '" . (int)$return_id . "'"); + $this->db->query("INSERT INTO `" . DB_PREFIX . "return_history` SET `return_id` = '" . (int)$return_id . "', `return_status_id` = '" . (int)$return_status_id . "', `notify` = '" . (int)$notify . "', `comment` = '" . $this->db->escape(strip_tags($comment)) . "', `date_added` = NOW()"); + } + + /** + * @param int $return_id + * @param int $start + * @param int $limit + * + * @return array + */ + public function getHistories(int $return_id, int $start = 0, int $limit = 10): array { + if ($start < 0) { + $start = 0; + } + + if ($limit < 1) { + $limit = 10; + } + + $query = $this->db->query("SELECT rh.`date_added`, rs.`name` AS status, rh.`comment`, rh.`notify` FROM `" . DB_PREFIX . "return_history` rh LEFT JOIN `" . DB_PREFIX . "return_status` rs ON rh.`return_status_id` = rs.`return_status_id` WHERE rh.`return_id` = '" . (int)$return_id . "' AND rs.`language_id` = '" . (int)$this->config->get('config_language_id') . "' ORDER BY rh.`date_added` DESC LIMIT " . (int)$start . "," . (int)$limit); + + return $query->rows; + } + + /** + * @param int $return_id + * + * @return int + */ + public function getTotalHistories(int $return_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "return_history` WHERE `return_id` = '" . (int)$return_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $return_status_id + * + * @return int + */ + public function getTotalHistoriesByReturnStatusId(int $return_status_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "return_history` WHERE `return_status_id` = '" . (int)$return_status_id . "'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/sale/subscription.php b/admininistrator/model/sale/subscription.php new file mode 100644 index 0000000..3080c15 --- /dev/null +++ b/admininistrator/model/sale/subscription.php @@ -0,0 +1,306 @@ +db->query("UPDATE `" . DB_PREFIX . "subscription` SET `subscription_plan_id` = '" . (int)$data['subscription_plan_id'] . "', `customer_payment_id` = '" . (int)$data['customer_payment_id'] . "' WHERE `subscription_id` = '" . (int)$subscription_id . "'"); + } + + /** + * @param int $subscription_id + * @param int $customer_payment_id + * + * @return void + */ + public function editPaymentMethod(int $subscription_id, int $customer_payment_id): void { + $this->db->query("UPDATE `" . DB_PREFIX . "subscription` SET `customer_payment_id ` = '" . (int)$customer_payment_id . "' WHERE `subscription_id` = '" . (int)$subscription_id . "'"); + } + + /** + * @param int $subscription_id + * @param int $subscription_plan_id + * + * @return void + */ + public function editSubscriptionPlan(int $subscription_id, int $subscription_plan_id): void { + $this->db->query("UPDATE `" . DB_PREFIX . "subscription` SET `subscription_plan_id` = '" . (int)$subscription_plan_id . "' WHERE `subscription_id` = '" . (int)$subscription_id . "'"); + } + + /** + * @param int $subscription_id + * @param int $remaining + * + * @return void + */ + public function editRemaining(int $subscription_id, int $remaining): void { + $this->db->query("UPDATE `" . DB_PREFIX . "subscription` SET `remaining` = '" . (int)$remaining . "' WHERE `subscription_id` = '" . (int)$subscription_id . "'"); + } + + /** + * @param int $subscription_id + * @param int $trial_remaining + * + * @return void + */ + public function editTrialRemaining(int $subscription_id, int $trial_remaining): void { + $this->db->query("UPDATE `" . DB_PREFIX . "subscription` SET `trial_remaining` = '" . (int)$trial_remaining . "' WHERE `subscription_id` = '" . (int)$subscription_id . "'"); + } + + /** + * @param int $subscription_id + * @param string $date_next + * + * @return void + */ + public function editDateNext(int $subscription_id, string $date_next): void { + $this->db->query("UPDATE `" . DB_PREFIX . "subscription` SET `date_next` = '" . $this->db->escape($date_next) . "' WHERE `subscription_id` = '" . (int)$subscription_id . "'"); + } + + /** + * @param int $subscription_id + * + * @return array + */ + public function getSubscription(int $subscription_id): array { + $subscription_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "subscription` WHERE `subscription_id` = '" . (int)$subscription_id . "'"); + + if ($query->num_rows) { + $subscription_data = $query->row; + + $subscription_data['payment_method'] = ($query->row['payment_method'] ? json_decode($query->row['payment_method'], true) : ''); + $subscription_data['shipping_method'] = ($query->row['shipping_method'] ? json_decode($query->row['shipping_method'], true) : ''); + } + + return $subscription_data; + } + + /** + * @param int $order_id + * @param int $order_product_id + * + * @return array + */ + public function getSubscriptionByOrderProductId(int $order_id, int $order_product_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "subscription` WHERE `order_id` = '" . (int)$order_id . "' AND `order_product_id` = '" . (int)$order_product_id . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getSubscriptions(array $data): array { + $sql = "SELECT `s`.`subscription_id`, `s`.*, CONCAT(o.`firstname`, ' ', o.`lastname`) AS customer, (SELECT ss.`name` FROM `" . DB_PREFIX . "subscription_status` ss WHERE ss.`subscription_status_id` = s.`subscription_status_id` AND ss.`language_id` = '" . (int)$this->config->get('config_language_id') . "') AS subscription_status FROM `" . DB_PREFIX . "subscription` `s` LEFT JOIN `" . DB_PREFIX . "order` `o` ON (`s`.`order_id` = `o`.`order_id`)"; + + $implode = []; + + if (!empty($data['filter_subscription_id'])) { + $implode[] = "`s`.`subscription_id` = '" . (int)$data['filter_subscription_id'] . "'"; + } + + if (!empty($data['filter_order_id'])) { + $implode[] = "`s`.`order_id` = '" . (int)$data['filter_order_id'] . "'"; + } + + if (!empty($data['filter_order_product_id'])) { + $implode[] = "`s`.`order_product_id` = '" . (int)$data['filter_order_product_id'] . "'"; + } + + if (!empty($data['filter_customer'])) { + $implode[] = "CONCAT(o.`firstname`, ' ', o.`lastname`) LIKE '" . $this->db->escape((string)$data['filter_customer'] . '%') . "'"; + } + + if (!empty($data['filter_date_next'])) { + $implode[] = "DATE(`s`.`date_next`) = DATE('" . $this->db->escape((string)$data['filter_date_next']) . "')"; + } + + if (!empty($data['filter_subscription_status_id'])) { + $implode[] = "`s`.`subscription_status_id` = '" . (int)$data['filter_subscription_status_id'] . "'"; + } + + if (!empty($data['filter_date_from'])) { + $implode[] = "DATE(s.`date_added`) >= DATE('" . $this->db->escape((string)$data['filter_date_from']) . "')"; + } + + if (!empty($data['filter_date_to'])) { + $implode[] = "DATE(s.`date_added`) <= DATE('" . $this->db->escape((string)$data['filter_date_to']) . "')"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $sort_data = [ + 's.subscription_id', + 's.order_id', + 's.reference', + 'customer', + 's.subscription_status', + 's.date_added' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `s`.`subscription_id`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param array $data + * + * @return int + */ + public function getTotalSubscriptions(array $data = []): int { + $sql = "SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "subscription` `s` LEFT JOIN `" . DB_PREFIX . "order` `o` ON (`s`.`order_id` = o.`order_id`)"; + + $implode = []; + + if (!empty($data['filter_subscription_id'])) { + $implode[] .= "`s`.`subscription_id` = '" . (int)$data['filter_subscription_id'] . "'"; + } + + if (!empty($data['filter_order_id'])) { + $implode[] .= "`s`.`order_id` = '" . (int)$data['filter_order_id'] . "'"; + } + + if (!empty($data['filter_customer'])) { + $implode[] .= "CONCAT(o.`firstname`, ' ', o.`lastname`) LIKE '" . $this->db->escape((string)$data['filter_customer'] . '%') . "'"; + } + + if (!empty($data['filter_subscription_status_id'])) { + $implode[] .= "`s`.`subscription_status_id` = '" . (int)$data['filter_subscription_status_id'] . "'"; + } + + if (!empty($data['filter_date_from'])) { + $implode[] = "DATE(s.`date_added`) >= DATE('" . $this->db->escape((string)$data['filter_date_from']) . "')"; + } + + if (!empty($data['filter_date_to'])) { + $implode[] = "DATE(s.`date_added`) <= DATE('" . $this->db->escape((string)$data['filter_date_to']) . "')"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $query = $this->db->query($sql); + + return (int)$query->row['total']; + } + + /** + * @param int $store_id + * + * @return int + */ + public function getTotalSubscriptionsByStoreId(int $store_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "subscription` WHERE `store_id` = '" . (int)$store_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $subscription_status_id + * + * @return int + */ + public function getTotalSubscriptionsBySubscriptionStatusId(int $subscription_status_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "subscription` WHERE `subscription_status_id` = '" . (int)$subscription_status_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $subscription_id + * @param int $subscription_status_id + * @param string $comment + * @param bool $notify + * + * @return void + */ + public function addHistory(int $subscription_id, int $subscription_status_id, string $comment = '', bool $notify = false): void { + $this->db->query("INSERT INTO `" . DB_PREFIX . "subscription_history` SET `subscription_id` = '" . (int)$subscription_id . "', `subscription_status_id` = '" . (int)$subscription_status_id . "', `comment` = '" . $this->db->escape($comment) . "', `notify` = '" . (int)$notify . "', `date_added` = NOW()"); + + $this->db->query("UPDATE `" . DB_PREFIX . "subscription` SET `subscription_status_id` = '" . (int)$subscription_status_id . "' WHERE `subscription_id` = '" . (int)$subscription_id . "'"); + } + + /** + * @param int $subscription_id + * @param int $start + * @param int $limit + * + * @return array + */ + public function getHistories(int $subscription_id, int $start = 0, int $limit = 10): array { + if ($start < 0) { + $start = 0; + } + + if ($limit < 1) { + $limit = 10; + } + + $query = $this->db->query("SELECT sh.`date_added`, ss.`name` AS status, sh.`comment`, sh.`notify` FROM `" . DB_PREFIX . "subscription_history` sh LEFT JOIN `" . DB_PREFIX . "subscription_status` ss ON sh.`subscription_status_id` = ss.`subscription_status_id` WHERE sh.`subscription_id` = '" . (int)$subscription_id . "' AND ss.`language_id` = '" . (int)$this->config->get('config_language_id') . "' ORDER BY sh.`date_added` DESC LIMIT " . (int)$start . "," . (int)$limit); + + return $query->rows; + } + + /** + * @param int $subscription_id + * + * @return int + */ + public function getTotalHistories(int $subscription_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "subscription_history` WHERE `subscription_id` = '" . (int)$subscription_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $subscription_status_id + * + * @return int + */ + public function getTotalHistoriesBySubscriptionStatusId(int $subscription_status_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "subscription_history` WHERE `subscription_status_id` = '" . (int)$subscription_status_id . "'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/sale/voucher.php b/admininistrator/model/sale/voucher.php new file mode 100644 index 0000000..54de4c0 --- /dev/null +++ b/admininistrator/model/sale/voucher.php @@ -0,0 +1,160 @@ +db->query("INSERT INTO `" . DB_PREFIX . "voucher` SET `code` = '" . $this->db->escape((string)$data['code']) . "', `from_name` = '" . $this->db->escape((string)$data['from_name']) . "', `from_email` = '" . $this->db->escape((string)$data['from_email']) . "', `to_name` = '" . $this->db->escape((string)$data['to_name']) . "', `to_email` = '" . $this->db->escape((string)$data['to_email']) . "', `voucher_theme_id` = '" . (int)$data['voucher_theme_id'] . "', `message` = '" . $this->db->escape((string)$data['message']) . "', `amount` = '" . (float)$data['amount'] . "', `status` = '" . (bool)$data['status'] . "', `date_added` = NOW()"); + + return $this->db->getLastId(); + } + + /** + * @param int $voucher_id + * @param array $data + * + * @return void + */ + public function editVoucher(int $voucher_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "voucher` SET `code` = '" . $this->db->escape((string)$data['code']) . "', `from_name` = '" . $this->db->escape((string)$data['from_name']) . "', `from_email` = '" . $this->db->escape((string)$data['from_email']) . "', `to_name` = '" . $this->db->escape((string)$data['to_name']) . "', `to_email` = '" . $this->db->escape((string)$data['to_email']) . "', `voucher_theme_id` = '" . (int)$data['voucher_theme_id'] . "', `message` = '" . $this->db->escape((string)$data['message']) . "', `amount` = '" . (float)$data['amount'] . "', `status` = '" . (bool)$data['status'] . "' WHERE `voucher_id` = '" . (int)$voucher_id . "'"); + } + + /** + * @param int $voucher_id + * + * @return void + */ + public function deleteVoucher(int $voucher_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "voucher` WHERE `voucher_id` = '" . (int)$voucher_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "voucher_history` WHERE `voucher_id` = '" . (int)$voucher_id . "'"); + } + + /** + * @param int $voucher_id + * + * @return array + */ + public function getVoucher(int $voucher_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "voucher` WHERE `voucher_id` = '" . (int)$voucher_id . "'"); + + return $query->row; + } + + /** + * @param string $code + * + * @return array + */ + public function getVoucherByCode(string $code): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "voucher` WHERE `code` = '" . $this->db->escape($code) . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getVouchers(array $data = []): array { + $sql = "SELECT v.`voucher_id`, v.`order_id`, v.`code`, v.`from_name`, v.`from_email`, v.`to_name`, v.`to_email`, (SELECT vtd.`name` FROM `" . DB_PREFIX . "voucher_theme_description` vtd WHERE vtd.`voucher_theme_id` = v.`voucher_theme_id` AND vtd.`language_id` = '" . (int)$this->config->get('config_language_id') . "') AS theme, v.`amount`, v.`status`, v.`date_added` FROM `" . DB_PREFIX . "voucher` v"; + + $sort_data = [ + 'v.code', + 'v.from_name', + 'v.to_name', + 'theme', + 'v.amount', + 'v.status', + 'v.date_added' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY v.`date_added`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @return int + */ + public function getTotalVouchers(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "voucher`"); + + return (int)$query->row['total']; + } + + /** + * @param int $voucher_theme_id + * + * @return int + */ + public function getTotalVouchersByVoucherThemeId(int $voucher_theme_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "voucher` WHERE `voucher_theme_id` = '" . (int)$voucher_theme_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $voucher_id + * @param int $start + * @param int $limit + * + * @return array + */ + public function getHistories(int $voucher_id, int $start = 0, int $limit = 10): array { + if ($start < 0) { + $start = 0; + } + + if ($limit < 1) { + $limit = 10; + } + + $query = $this->db->query("SELECT vh.`order_id`, CONCAT(o.`firstname`, ' ', o.`lastname`) AS customer, vh.`amount`, vh.`date_added` FROM `" . DB_PREFIX . "voucher_history` vh LEFT JOIN `" . DB_PREFIX . "order` o ON (vh.`order_id` = o.`order_id`) WHERE vh.`voucher_id` = '" . (int)$voucher_id . "' ORDER BY vh.`date_added` ASC LIMIT " . (int)$start . "," . (int)$limit); + + return $query->rows; + } + + /** + * @param int $voucher_id + * + * @return int + */ + public function getTotalHistories(int $voucher_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "voucher_history` WHERE `voucher_id` = '" . (int)$voucher_id . "'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/sale/voucher_theme.php b/admininistrator/model/sale/voucher_theme.php new file mode 100644 index 0000000..775735b --- /dev/null +++ b/admininistrator/model/sale/voucher_theme.php @@ -0,0 +1,133 @@ +db->query("INSERT INTO `" . DB_PREFIX . "voucher_theme` SET `image` = '" . $this->db->escape((string)$data['image']) . "'"); + + $voucher_theme_id = $this->db->getLastId(); + + foreach ($data['voucher_theme_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "voucher_theme_description` SET `voucher_theme_id` = '" . (int)$voucher_theme_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } + + $this->cache->delete('voucher_theme'); + + return $voucher_theme_id; + } + + /** + * @param int $voucher_theme_id + * @param array $data + * + * @return void + */ + public function editVoucherTheme(int $voucher_theme_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "voucher_theme` SET `image` = '" . $this->db->escape((string)$data['image']) . "' WHERE `voucher_theme_id` = '" . (int)$voucher_theme_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "voucher_theme_description` WHERE `voucher_theme_id` = '" . (int)$voucher_theme_id . "'"); + + foreach ($data['voucher_theme_description'] as $language_id => $value) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "voucher_theme_description` SET `voucher_theme_id` = '" . (int)$voucher_theme_id . "', `language_id` = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'"); + } + + $this->cache->delete('voucher_theme'); + } + + /** + * @param int $voucher_theme_id + * + * @return void + */ + public function deleteVoucherTheme(int $voucher_theme_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "voucher_theme` WHERE `voucher_theme_id` = '" . (int)$voucher_theme_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "voucher_theme_description` WHERE `voucher_theme_id` = '" . (int)$voucher_theme_id . "'"); + + $this->cache->delete('voucher_theme'); + } + + /** + * @param int $voucher_theme_id + * + * @return array + */ + public function getVoucherTheme(int $voucher_theme_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "voucher_theme` vt LEFT JOIN `" . DB_PREFIX . "voucher_theme_description` vtd ON (vt.`voucher_theme_id` = vtd.`voucher_theme_id`) WHERE vt.`voucher_theme_id` = '" . (int)$voucher_theme_id . "' AND vtd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getVoucherThemes(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "voucher_theme` vt LEFT JOIN `" . DB_PREFIX . "voucher_theme_description` `vtd` ON (`vt`.`voucher_theme_id` = `vtd`.`voucher_theme_id`) WHERE `vtd`.`language_id` = '" . (int)$this->config->get('config_language_id') . "' ORDER BY `vtd`.`name`"; + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $voucher_theme_data = $this->cache->get('voucher_theme.' . md5($sql)); + + if (!$voucher_theme_data) { + $query = $this->db->query($sql); + + $voucher_theme_data = $query->rows; + + $this->cache->set('voucher_theme.' . md5($sql), $voucher_theme_data); + } + + return $voucher_theme_data; + } + + /** + * @param int $voucher_theme_id + * + * @return array + */ + public function getDescriptions(int $voucher_theme_id): array { + $voucher_theme_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "voucher_theme_description` WHERE `voucher_theme_id` = '" . (int)$voucher_theme_id . "'"); + + foreach ($query->rows as $result) { + $voucher_theme_data[$result['language_id']] = ['name' => $result['name']]; + } + + return $voucher_theme_data; + } + + /** + * @return int + */ + public function getTotalVoucherThemes(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "voucher_theme`"); + + return (int)$query->row['total']; + } +} \ No newline at end of file diff --git a/admininistrator/model/setting/cron.php b/admininistrator/model/setting/cron.php new file mode 100644 index 0000000..8f6463c --- /dev/null +++ b/admininistrator/model/setting/cron.php @@ -0,0 +1,137 @@ +db->query("INSERT INTO `" . DB_PREFIX . "cron` SET `code` = '" . $this->db->escape($code) . "', `description` = '" . $this->db->escape($description) . "', `cycle` = '" . $this->db->escape($cycle) . "', `action` = '" . $this->db->escape($action) . "', `status` = '" . (int)$status . "', `date_added` = NOW(), `date_modified` = NOW()"); + + return $this->db->getLastId(); + } + + /** + * @param int $cron_id + * + * @return void + */ + public function deleteCron(int $cron_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "cron` WHERE `cron_id` = '" . (int)$cron_id . "'"); + } + + /** + * @param string $code + * + * @return void + */ + public function deleteCronByCode(string $code): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "cron` WHERE `code` = '" . $this->db->escape($code) . "'"); + } + + /** + * @param int $cron_id + * + * @return void + */ + public function editCron(int $cron_id): void { + $this->db->query("UPDATE `" . DB_PREFIX . "cron` SET `date_modified` = NOW() WHERE `cron_id` = '" . (int)$cron_id . "'"); + } + + /** + * @param int $cron_id + * @param bool $status + * + * @return void + */ + public function editStatus(int $cron_id, bool $status): void { + $this->db->query("UPDATE `" . DB_PREFIX . "cron` SET `status` = '" . (bool)$status . "' WHERE `cron_id` = '" . (int)$cron_id . "'"); + } + + /** + * @param int $cron_id + * + * @return array + */ + public function getCron(int $cron_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "cron` WHERE `cron_id` = '" . (int)$cron_id . "'"); + + return $query->row; + } + + /** + * @param string $code + * + * @return array + */ + public function getCronByCode(string $code): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "cron` WHERE `code` = '" . $this->db->escape($code) . "' LIMIT 1"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getCrons(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "cron`"; + + $sort_data = [ + 'code', + 'cycle', + 'action', + 'status', + 'date_added', + 'date_modified' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `date_added`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @return int + */ + public function getTotalCrons(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "cron`"); + + return (int)$query->row['total']; + } +} \ No newline at end of file diff --git a/admininistrator/model/setting/event.php b/admininistrator/model/setting/event.php new file mode 100644 index 0000000..3ec1553 --- /dev/null +++ b/admininistrator/model/setting/event.php @@ -0,0 +1,124 @@ +db->query("INSERT INTO `" . DB_PREFIX . "event` SET `code` = '" . $this->db->escape($data['code']) . "', `description` = '" . $this->db->escape($data['description']) . "', `trigger` = '" . $this->db->escape($data['trigger']) . "', `action` = '" . $this->db->escape($data['action']) . "', `status` = '" . (bool)$data['status'] . "', `sort_order` = '" . (int)$data['sort_order'] . "'"); + + return $this->db->getLastId(); + } + + /** + * @param int $event_id + * + * @return void + */ + public function deleteEvent(int $event_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "event` WHERE `event_id` = '" . (int)$event_id . "'"); + } + + /** + * @param string $code + * + * @return void + */ + public function deleteEventByCode(string $code): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "event` WHERE `code` = '" . $this->db->escape($code) . "'"); + } + + /** + * @param int $event_id + * @param bool $status + * + * @return void + */ + public function editStatus(int $event_id, bool $status): void { + $this->db->query("UPDATE `" . DB_PREFIX . "event` SET `status` = '" . (bool)$status . "' WHERE `event_id` = '" . (int)$event_id . "'"); + } + + /** + * @param int $event_id + * + * @return array + */ + public function getEvent(int $event_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "event` WHERE `event_id` = '" . (int)$event_id . "'"); + + return $query->row; + } + + /** + * @param string $code + * + * @return array + */ + public function getEventByCode(string $code): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "event` WHERE `code` = '" . $this->db->escape($code) . "' LIMIT 1"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getEvents(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "event`"; + + $sort_data = [ + 'code', + 'trigger', + 'action', + 'sort_order', + 'status', + 'date_added' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `sort_order`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @return int + */ + public function getTotalEvents(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "event`"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/setting/extension.php b/admininistrator/model/setting/extension.php new file mode 100644 index 0000000..8bf2eea --- /dev/null +++ b/admininistrator/model/setting/extension.php @@ -0,0 +1,258 @@ +db->query("SELECT DISTINCT `extension` FROM `" . DB_PREFIX . "extension`"); + + return $query->rows; + } + + /** + * @param string $type + * + * @return array + */ + public function getExtensionsByType(string $type): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "extension` WHERE `type` = '" . $this->db->escape($type) . "' ORDER BY `code` ASC"); + + return $query->rows; + } + + /** + * @param string $type + * @param string $code + * + * @return array + */ + public function getExtensionByCode(string $type, string $code): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "extension` WHERE `type` = '" . $this->db->escape($type) . "' AND `code` = '" . $this->db->escape($code) . "'"); + + return $query->row; + } + + /** + * @param string $extension + * + * @return int + */ + public function getTotalExtensionsByExtension(string $extension): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "extension` WHERE `extension` = '" . $this->db->escape($extension) . "'"); + + return (int)$query->row['total']; + } + + /** + * @param string $type + * @param string $extension + * @param string $code + * + * @return void + */ + public function install(string $type, string $extension, string $code): void { + $extensions = $this->getExtensionsByType($type); + + $codes = array_column($extensions, 'code'); + + if (!in_array($code, $codes)) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "extension` SET `extension` = '" . $this->db->escape($extension) . "', `type` = '" . $this->db->escape($type) . "', `code` = '" . $this->db->escape($code) . "'"); + } + } + + /** + * @param string $type + * @param string $code + * + * @return void + */ + public function uninstall(string $type, string $code): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "extension` WHERE `type` = '" . $this->db->escape($type) . "' AND `code` = '" . $this->db->escape($code) . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "setting` WHERE `code` = '" . $this->db->escape($type . '_' . $code) . "'"); + } + + /** + * @param array $data + * + * @return int + */ + public function addInstall(array $data): int { + $this->db->query("INSERT INTO `" . DB_PREFIX . "extension_install` SET `extension_id` = '" . (int)$data['extension_id'] . "', `extension_download_id` = '" . (int)$data['extension_download_id'] . "', `name` = '" . $this->db->escape($data['name']) . "', `code` = '" . $this->db->escape($data['code']) . "', `version` = '" . $this->db->escape($data['version']) . "', `author` = '" . $this->db->escape($data['author']) . "', `link` = '" . $this->db->escape($data['link']) . "', `status` = '0', `date_added` = NOW()"); + + return $this->db->getLastId(); + } + + /** + * @param int $extension_install_id + * + * @return void + */ + public function deleteInstall(int $extension_install_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "extension_install` WHERE `extension_install_id` = '" . (int)$extension_install_id . "'"); + } + + /** + * @param int $extension_install_id + * @param bool $status + * + * @return void + */ + public function editStatus(int $extension_install_id, bool $status): void { + $this->db->query("UPDATE `" . DB_PREFIX . "extension_install` SET `status` = '" . (bool)$status . "' WHERE `extension_install_id` = '" . (int)$extension_install_id . "'"); + } + + /** + * @param int $extension_install_id + * + * @return array + */ + public function getInstall(int $extension_install_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "extension_install` WHERE `extension_install_id` = '" . (int)$extension_install_id . "'"); + + return $query->row; + } + + /** + * @param int $extension_download_id + * + * @return array + */ + public function getInstallByExtensionDownloadId(int $extension_download_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "extension_install` WHERE `extension_download_id` = '" . (int)$extension_download_id . "'"); + + return $query->row; + } + + /** + * @param string $code + * + * @return array + */ + public function getInstallByCode(string $code): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "extension_install` WHERE `code` = '" . $this->db->escape($code) . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getInstalls(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "extension_install`"; + + if (!empty($data['filter_extension_download_id'])) { + $sql .= " WHERE `extension_download_id` = '" . (int)$data['filter_extension_download_id'] . "'"; + } + + $sort_data = [ + 'name', + 'version', + 'date_added' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `date_added`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param array $data + * + * @return int + */ + public function getTotalInstalls(array $data = []): int { + $sql = "SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "extension_install`"; + + if (!empty($data['filter_extension_download_id'])) { + $sql .= " WHERE `extension_download_id` = '" . (int)$data['filter_extension_download_id'] . "'"; + } + + $query = $this->db->query($sql); + + return (int)$query->row['total']; + } + + /** + * @param int $extension_install_id + * @param string $path + * + * @return void + */ + public function addPath(int $extension_install_id, string $path): void { + $this->db->query("INSERT INTO `" . DB_PREFIX . "extension_path` SET `extension_install_id` = '" . (int)$extension_install_id . "', `path` = '" . $this->db->escape($path) . "'"); + } + + /** + * @param int $extension_path_id + * + * @return void + */ + public function deletePath(int $extension_path_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "extension_path` WHERE `extension_path_id` = '" . (int)$extension_path_id . "'"); + } + + /** + * @param int $extension_install_id + * + * @return array + */ + public function getPathsByExtensionInstallId(int $extension_install_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "extension_path` WHERE `extension_install_id` = '" . (int)$extension_install_id . "' ORDER BY `extension_path_id` ASC"); + + return $query->rows; + } + + /** + * @param string $path + * + * @return array + */ + public function getPaths(string $path): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "extension_path` WHERE `path` LIKE '" . $this->db->escape($path) . "' ORDER BY `path` ASC"); + + return $query->rows; + } + + /** + * @param string $path + * + * @return int + */ + public function getTotalPaths(string $path): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "extension_path` WHERE `path` LIKE '" . $this->db->escape($path) . "'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/setting/module.php b/admininistrator/model/setting/module.php new file mode 100644 index 0000000..531c6e8 --- /dev/null +++ b/admininistrator/model/setting/module.php @@ -0,0 +1,86 @@ +db->query("INSERT INTO `" . DB_PREFIX . "module` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `code` = '" . $this->db->escape($code) . "', `setting` = '" . $this->db->escape(json_encode($data)) . "'"); + + $module_id = $this->db->getLastId(); + + return (int)$module_id; + } + + /** + * @param int $module_id + * @param array $data + * + * @return void + */ + public function editModule(int $module_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "module` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `setting` = '" . $this->db->escape(json_encode($data)) . "' WHERE `module_id` = '" . (int)$module_id . "'"); + } + + /** + * @param int $module_id + * + * @return void + */ + public function deleteModule(int $module_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "module` WHERE `module_id` = '" . (int)$module_id . "'"); + } + + /** + * @param int $module_id + * + * @return array + */ + public function getModule(int $module_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "module` WHERE `module_id` = '" . (int)$module_id . "'"); + + if ($query->row) { + return json_decode($query->row['setting'], true); + } else { + return []; + } + } + + /** + * @return array + */ + public function getModules(): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "module` ORDER BY `code`"); + + return $query->rows; + } + + /** + * @param string $code + * + * @return array + */ + public function getModulesByCode(string $code): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "module` WHERE `code` = '" . $this->db->escape($code) . "' ORDER BY `name`"); + + return $query->rows; + } + + /** + * @param string $code + * + * @return void + */ + public function deleteModulesByCode(string $code): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "module` WHERE `code` = '" . $this->db->escape($code) . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "layout_module` WHERE `code` = '" . $this->db->escape($code) . "' OR `code` LIKE '" . $this->db->escape($code . '.%') . "'"); + } +} diff --git a/admininistrator/model/setting/setting.php b/admininistrator/model/setting/setting.php new file mode 100644 index 0000000..5c480a1 --- /dev/null +++ b/admininistrator/model/setting/setting.php @@ -0,0 +1,104 @@ +db->query("SELECT * FROM `" . DB_PREFIX . "setting` WHERE `store_id` = '" . (int)$store_id . "' OR `store_id` = '0' ORDER BY `store_id` ASC"); + + return $query->rows; + } + + /** + * @param string $code + * @param int $store_id + * + * @return array + */ + public function getSetting(string $code, int $store_id = 0): array { + $setting_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "setting` WHERE `store_id` = '" . (int)$store_id . "' AND `code` = '" . $this->db->escape($code) . "'"); + + foreach ($query->rows as $result) { + if (!$result['serialized']) { + $setting_data[$result['key']] = $result['value']; + } else { + $setting_data[$result['key']] = json_decode($result['value'], true); + } + } + + return $setting_data; + } + + /** + * @param string $code + * @param array $data + * @param int $store_id + * + * @return void + */ + public function editSetting(string $code, array $data, int $store_id = 0): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "setting` WHERE `store_id` = '" . (int)$store_id . "' AND `code` = '" . $this->db->escape($code) . "'"); + + foreach ($data as $key => $value) { + if (substr($key, 0, strlen($code)) == $code) { + if (!is_array($value)) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "setting` SET `store_id` = '" . (int)$store_id . "', `code` = '" . $this->db->escape($code) . "', `key` = '" . $this->db->escape($key) . "', `value` = '" . $this->db->escape($value) . "'"); + } else { + $this->db->query("INSERT INTO `" . DB_PREFIX . "setting` SET `store_id` = '" . (int)$store_id . "', `code` = '" . $this->db->escape($code) . "', `key` = '" . $this->db->escape($key) . "', `value` = '" . $this->db->escape(json_encode($value)) . "', `serialized` = '1'"); + } + } + } + } + + /** + * @param string $code + * @param int $store_id + * + * @return void + */ + public function deleteSetting(string $code, int $store_id = 0): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "setting` WHERE `store_id` = '" . (int)$store_id . "' AND `code` = '" . $this->db->escape($code) . "'"); + } + + /** + * @param string $key + * @param int $store_id + * + * @return string + */ + public function getValue(string $key, int $store_id = 0): string { + $query = $this->db->query("SELECT `value` FROM `" . DB_PREFIX . "setting` WHERE `store_id` = '" . (int)$store_id . "' AND `key` = '" . $this->db->escape($key) . "'"); + + if ($query->num_rows) { + return $query->row['value']; + } else { + return ''; + } + } + + /** + * @param string $code + * @param string $key + * @param string|array $value + * @param int $store_id + * + * @return void + */ + public function editValue(string $code = '', string $key = '', string|array $value = '', int $store_id = 0): void { + if (!is_array($value)) { + $this->db->query("UPDATE `" . DB_PREFIX . "setting` SET `value` = '" . $this->db->escape($value) . "', `serialized` = '0' WHERE `code` = '" . $this->db->escape($code) . "' AND `key` = '" . $this->db->escape($key) . "' AND `store_id` = '" . (int)$store_id . "'"); + } else { + $this->db->query("UPDATE `" . DB_PREFIX . "setting` SET `value` = '" . $this->db->escape(json_encode($value)) . "', `serialized` = '1' WHERE `code` = '" . $this->db->escape($code) . "' AND `key` = '" . $this->db->escape($key) . "' AND `store_id` = '" . (int)$store_id . "'"); + } + } +} diff --git a/admininistrator/model/setting/startup.php b/admininistrator/model/setting/startup.php new file mode 100644 index 0000000..754eb91 --- /dev/null +++ b/admininistrator/model/setting/startup.php @@ -0,0 +1,123 @@ +db->query("INSERT INTO `" . DB_PREFIX . "startup` SET `code` = '" . $this->db->escape($data['code']) . "', `action` = '" . $this->db->escape($data['action']) . "', `status` = '" . (bool)$data['status'] . "', `sort_order` = '" . (int)$data['sort_order'] . "'"); + + return $this->db->getLastId(); + } + + /** + * @param int $startup_id + * + * @return void + */ + public function deleteStartup(int $startup_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "startup` WHERE `startup_id` = '" . (int)$startup_id . "'"); + } + + /** + * @param string $code + * + * @return void + */ + public function deleteStartupByCode(string $code): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "startup` WHERE `code` = '" . $this->db->escape($code) . "'"); + } + + /** + * @param int $startup_id + * @param bool $status + * + * @return void + */ + public function editStatus(int $startup_id, bool $status): void { + $this->db->query("UPDATE `" . DB_PREFIX . "startup` SET `status` = '" . (bool)$status . "' WHERE `startup_id` = '" . (int)$startup_id . "'"); + } + + /** + * @param int $startup_id + * + * @return array + */ + public function getStartup(int $startup_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "startup` WHERE `startup_id` = '" . (int)$startup_id . "'"); + + return $query->row; + } + + /** + * @param string $code + * + * @return array + */ + public function getStartupByCode(string $code): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "startup` WHERE `code` = '" . $this->db->escape($code) . "' LIMIT 1"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getStartups(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "startup`"; + + $sort_data = [ + 'code', + 'action', + 'status', + 'sort_order', + 'date_added' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `sort_order`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @return int + */ + public function getTotalStartups(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "startup`"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/setting/store.php b/admininistrator/model/setting/store.php new file mode 100644 index 0000000..40694cf --- /dev/null +++ b/admininistrator/model/setting/store.php @@ -0,0 +1,325 @@ +db->query("INSERT INTO `" . DB_PREFIX . "store` SET `name` = '" . $this->db->escape((string)$data['config_name']) . "', `url` = '" . $this->db->escape((string)$data['config_url']) . "'"); + + $store_id = $this->db->getLastId(); + + // Layout Route + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "layout_route` WHERE `store_id` = '0'"); + + foreach ($query->rows as $layout_route) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "layout_route` SET `layout_id` = '" . (int)$layout_route['layout_id'] . "', `route` = '" . $this->db->escape($layout_route['route']) . "', `store_id` = '" . (int)$store_id . "'"); + } + + $this->cache->delete('store'); + + return $store_id; + } + + /** + * @param int $store_id + * @param array $data + * + * @return void + */ + public function editStore(int $store_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "store` SET `name` = '" . $this->db->escape((string)$data['config_name']) . "', `url` = '" . $this->db->escape((string)$data['config_url']) . "' WHERE `store_id` = '" . (int)$store_id . "'"); + + $this->cache->delete('store'); + } + + /** + * @param int $store_id + * + * @return void + */ + public function deleteStore(int $store_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "store` WHERE `store_id` = '" . (int)$store_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "category_to_layout` WHERE `store_id` = '" . (int)$store_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "category_to_store` WHERE `store_id` = '" . (int)$store_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer` WHERE `store_id` = '" . (int)$store_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_affiliate_report` WHERE `store_id` = '" . (int)$store_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_ip` WHERE `store_id` = '" . (int)$store_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "customer_search` WHERE `store_id` = '" . (int)$store_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "download_report` WHERE `store_id` = '" . (int)$store_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "gdpr` WHERE `store_id` = '" . (int)$store_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "information_to_layout` WHERE `store_id` = '" . (int)$store_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "information_to_store` WHERE `store_id` = '" . (int)$store_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "layout_route` WHERE `store_id` = '" . (int)$store_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "manufacturer_to_layout` WHERE `store_id` = '" . (int)$store_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "manufacturer_to_store` WHERE `store_id` = '" . (int)$store_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "marketing_report` WHERE `store_id` = '" . (int)$store_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "order` WHERE `store_id` = '" . (int)$store_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_report` WHERE `store_id` = '" . (int)$store_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_to_layout` WHERE `store_id` = '" . (int)$store_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "product_to_store` WHERE `store_id` = '" . (int)$store_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "setting` WHERE `store_id` = '" . (int)$store_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "subscription` WHERE `store_id` = '" . (int)$store_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "theme` WHERE `store_id` = '" . (int)$store_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "translation` WHERE `store_id` = '" . (int)$store_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "seo_url` WHERE `store_id` = '" . (int)$store_id . "'"); + + $this->cache->delete('store'); + } + + /** + * @param int $store_id + * + * @return array + */ + public function getStore(int $store_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "store` WHERE `store_id` = '" . (int)$store_id . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getStores(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "store` ORDER BY `url`"; + + $store_data = $this->cache->get('store.' . md5($sql)); + + if (!$store_data) { + $query = $this->db->query($sql); + + $store_data = $query->rows; + + $this->cache->set('store.' . md5($sql), $store_data); + } + + return $store_data; + } + + /** + * @param int $store_id + * @param string $language + * @param string $session_id + * + * @return \Opencart\System\Engine\Registry + * @throws \Exception + */ + public function createStoreInstance(int $store_id = 0, string $language = '', string $session_id = ''): object { + // Autoloader + $this->autoloader->register('Opencart\Catalog', DIR_CATALOG); + + // Registry + $registry = new \Opencart\System\Engine\Registry(); + $registry->set('autoloader', $this->autoloader); + + // Config + $config = new \Opencart\System\Engine\Config(); + $registry->set('config', $config); + + // Load the default config + $config->addPath(DIR_CONFIG); + $config->load('default'); + $config->load('catalog'); + $config->set('application', 'Catalog'); + + // Store + $config->set('config_store_id', $store_id); + + // Logging + $registry->set('log', $this->log); + + // Event + $event = new \Opencart\System\Engine\Event($registry); + $registry->set('event', $event); + + // Event Register + if ($config->has('action_event')) { + foreach ($config->get('action_event') as $key => $value) { + foreach ($value as $priority => $action) { + $event->register($key, new \Opencart\System\Engine\Action($action), $priority); + } + } + } + + // Loader + $loader = new \Opencart\System\Engine\Loader($registry); + $registry->set('load', $loader); + + // Create a dummy request class, so we can feed the data to the order editor + $request = new \stdClass(); + $request->get = []; + $request->post = []; + $request->server = $this->request->server; + $request->cookie = []; + + // Request + $registry->set('request', $request); + + // Response + $response = new \Opencart\System\Library\Response(); + $registry->set('response', $response); + + // Database + $registry->set('db', $this->db); + + // Cache + $registry->set('cache', $this->cache); + + // Session + $session = new \Opencart\System\Library\Session($config->get('session_engine'), $registry); + $registry->set('session', $session); + + // Start session + $session->start($session_id); + + // Template + $template = new \Opencart\System\Library\Template($config->get('template_engine')); + $template->addPath(DIR_CATALOG . 'view/template/'); + $registry->set('template', $template); + + // Adding language var to the GET variable so there is a default language + $registry->request->get['language'] = $language; + + // Language + $language = new \Opencart\System\Library\Language($config->get('language_code')); + $language->addPath(DIR_CATALOG . 'language/'); + $language->load('default'); + $registry->set('language', $language); + + // Url + $registry->set('url', new \Opencart\System\Library\Url($config->get('site_url'))); + + // Document + $registry->set('document', new \Opencart\System\Library\Document()); + + // Run pre actions to load key settings and classes. + $pre_actions = [ + 'startup/setting', + 'startup/language', + 'startup/extension', + 'startup/customer', + 'startup/tax', + 'startup/currency', + 'startup/application', + 'startup/startup', + 'startup/event' + ]; + + // Pre Actions + foreach ($pre_actions as $pre_action) { + $loader->controller($pre_action); + } + + return $registry; + } + + /** + * @return int + */ + public function getTotalStores(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "store`"); + + return (int)$query->row['total']; + } + + /** + * @param int $layout_id + * + * @return int + */ + public function getTotalStoresByLayoutId(int $layout_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "setting` WHERE `key` = 'config_layout_id' AND `value` = '" . (int)$layout_id . "' AND `store_id` != '0'"); + + return (int)$query->row['total']; + } + + /** + * @param string $language + * + * @return int + */ + public function getTotalStoresByLanguage(string $language): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "setting` WHERE `key` = 'config_language' AND `value` = '" . $this->db->escape($language) . "' AND `store_id` != '0'"); + + return (int)$query->row['total']; + } + + /** + * @param string $currency + * + * @return int + */ + public function getTotalStoresByCurrency(string $currency): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "setting` WHERE `key` = 'config_currency' AND `value` = '" . $this->db->escape($currency) . "' AND `store_id` != '0'"); + + return (int)$query->row['total']; + } + + /** + * @param int $country_id + * + * @return int + */ + public function getTotalStoresByCountryId(int $country_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "setting` WHERE `key` = 'config_country_id' AND `value` = '" . (int)$country_id . "' AND `store_id` != '0'"); + + return (int)$query->row['total']; + } + + /** + * @param int $zone_id + * + * @return int + */ + public function getTotalStoresByZoneId(int $zone_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "setting` WHERE `key` = 'config_zone_id' AND `value` = '" . (int)$zone_id . "' AND `store_id` != '0'"); + + return (int)$query->row['total']; + } + + /** + * @param int $customer_group_id + * + * @return int + */ + public function getTotalStoresByCustomerGroupId(int $customer_group_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "setting` WHERE `key` = 'config_customer_group_id' AND `value` = '" . (int)$customer_group_id . "' AND `store_id` != '0'"); + + return (int)$query->row['total']; + } + + /** + * @param int $information_id + * + * @return int + */ + public function getTotalStoresByInformationId(int $information_id): int { + $account_query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "setting` WHERE `key` = 'config_account_id' AND `value` = '" . (int)$information_id . "' AND `store_id` != '0'"); + + $checkout_query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "setting` WHERE `key` = 'config_checkout_id' AND `value` = '" . (int)$information_id . "' AND `store_id` != '0'"); + + return ($account_query->row['total'] + $checkout_query->row['total']); + } + + /** + * @param int $order_status_id + * + * @return int + */ + public function getTotalStoresByOrderStatusId(int $order_status_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "setting` WHERE `key` = 'config_order_status_id' AND `value` = '" . (int)$order_status_id . "' AND `store_id` != '0'"); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/tool/backup.php b/admininistrator/model/tool/backup.php new file mode 100644 index 0000000..b96ca2b --- /dev/null +++ b/admininistrator/model/tool/backup.php @@ -0,0 +1,65 @@ +db->query("SHOW TABLES FROM `" . DB_DATABASE . "`"); + + foreach ($query->rows as $result) { + if (isset($result['Tables_in_' . DB_DATABASE]) && substr($result['Tables_in_' . DB_DATABASE], 0, strlen(DB_PREFIX)) == DB_PREFIX) { + $table_data[] = $result['Tables_in_' . DB_DATABASE]; + } + } + + return $table_data; + } + + /** + * @param string $table + * @param int $start + * @param int $limit + * + * @return array + */ + public function getRecords(string $table, int $start = 0, int $limit = 100): array { + if ($start < 0) { + $start = 0; + } + + if ($limit < 1) { + $limit = 10; + } + + $query = $this->db->query("SELECT * FROM `" . $table . "` LIMIT " . (int)$start . "," . (int)$limit); + + if ($query->num_rows) { + return $query->rows; + } else { + return []; + } + } + + /** + * @param string $table + * + * @return int + */ + public function getTotalRecords(string $table): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . $table . "`"); + + if ($query->num_rows) { + return (int)$query->row['total']; + } else { + return 0; + } + } +} \ No newline at end of file diff --git a/admininistrator/model/tool/image.php b/admininistrator/model/tool/image.php new file mode 100644 index 0000000..a3c9433 --- /dev/null +++ b/admininistrator/model/tool/image.php @@ -0,0 +1,61 @@ + filemtime(DIR_IMAGE . $image_new))) { + list($width_orig, $height_orig, $image_type) = getimagesize(DIR_IMAGE . $image_old); + + if (!in_array($image_type, [IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF, IMAGETYPE_WEBP])) { + return HTTP_CATALOG . 'image/' . $image_old; + } + + $path = ''; + + $directories = explode('/', dirname($image_new)); + + foreach ($directories as $directory) { + if (!$path) { + $path = $directory; + } else { + $path = $path . '/' . $directory; + } + + if (!is_dir(DIR_IMAGE . $path)) { + @mkdir(DIR_IMAGE . $path, 0777); + } + } + + if ($width_orig != $width || $height_orig != $height) { + $image = new \Opencart\System\Library\Image(DIR_IMAGE . $image_old); + $image->resize($width, $height); + $image->save(DIR_IMAGE . $image_new); + } else { + copy(DIR_IMAGE . $image_old, DIR_IMAGE . $image_new); + } + } + + return HTTP_CATALOG . 'image/' . $image_new; + } +} diff --git a/admininistrator/model/tool/notification.php b/admininistrator/model/tool/notification.php new file mode 100644 index 0000000..ce930fa --- /dev/null +++ b/admininistrator/model/tool/notification.php @@ -0,0 +1,97 @@ +db->query("INSERT INTO `" . DB_PREFIX . "notification` SET `title` = '" . $this->db->escape((string)$data['title']) . "', `text` = '" . $this->db->escape((string)$data['text']) . "', `status` = '" . (bool)$data['status'] . "', `date_added` = NOW()"); + + return $this->db->getLastId(); + } + + /** + * @param int $notification_id + * @param bool $status + * + * @return void + */ + public function editStatus(int $notification_id, bool $status): void { + $this->db->query("UPDATE `" . DB_PREFIX . "notification` SET `status` = '" . (bool)$status . "' WHERE `notification_id` = '" . (int)$notification_id . "'"); + } + + /** + * @param int $notification_id + * + * @return void + */ + public function deleteNotification(int $notification_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "notification` WHERE `notification_id` = '" . (int)$notification_id . "'"); + } + + /** + * @param int $notification_id + * + * @return array + */ + public function getNotification(int $notification_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "notification` WHERE `notification_id` = '" . (int)$notification_id . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getNotifications(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "notification`"; + + if (isset($data['filter_status']) && $data['filter_status'] !== '') { + $sql .= " WHERE `status` = '" . (bool)$data['filter_status'] . "'"; + } + + $sql .= " ORDER BY `date_added` DESC"; + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param array $data + * + * @return int + */ + public function getTotalNotifications(array $data = []): int { + $sql = "SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "notification`"; + + if (isset($data['filter_status']) && $data['filter_status'] !== '') { + $sql .= " WHERE `status` = '" . (bool)$data['filter_status'] . "'"; + } + + $query = $this->db->query($sql); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/tool/upload.php b/admininistrator/model/tool/upload.php new file mode 100644 index 0000000..3c32d32 --- /dev/null +++ b/admininistrator/model/tool/upload.php @@ -0,0 +1,153 @@ +db->query("INSERT INTO `" . DB_PREFIX . "upload` SET `name` = '" . $this->db->escape($name) . "', `filename` = '" . $this->db->escape($filename) . "', `code` = '" . $this->db->escape($code) . "', `date_added` = NOW()"); + + return $code; + } + + /** + * @param int $upload_id + * + * @return void + */ + public function deleteUpload(int $upload_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "upload` WHERE `upload_id` = '" . (int)$upload_id . "'"); + } + + /** + * @param int $upload_id + * + * @return array + */ + public function getUpload(int $upload_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "upload` WHERE `upload_id` = '" . (int)$upload_id . "'"); + + return $query->row; + } + + /** + * @param string $code + * + * @return array + */ + public function getUploadByCode(string $code): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "upload` WHERE `code` = '" . $this->db->escape($code) . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getUploads(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "upload`"; + + $implode = []; + + if (!empty($data['filter_name'])) { + $implode[] = "`name` LIKE '" . $this->db->escape((string)$data['filter_name'] . '%') . "'"; + } + + if (!empty($data['filter_code'])) { + $implode[] = "`code` LIKE '" . $this->db->escape((string)$data['filter_code'] . '%') . "'"; + } + + if (!empty($data['filter_date_from'])) { + $implode[] = "DATE(`date_added`) >= DATE('" . $this->db->escape((string)$data['filter_date_from']) . "')"; + } + + if (!empty($data['filter_date_to'])) { + $implode[] = "DATE(`date_added`) <= DATE('" . $this->db->escape((string)$data['filter_date_to']) . "')"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $sort_data = [ + 'name', + 'code', + 'date_added' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `date_added`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @param array $data + * + * @return int + */ + public function getTotalUploads(array $data = []): int { + $sql = "SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "upload`"; + + $implode = []; + + if (!empty($data['filter_name'])) { + $implode[] = "`name` LIKE '" . $this->db->escape((string)$data['filter_name'] . '%') . "'"; + } + + if (!empty($data['filter_code'])) { + $implode[] = "`code` LIKE '" . $this->db->escape((string)$data['filter_code'] . '%') . "'"; + } + + if (!empty($data['filter_date_from'])) { + $implode[] = "DATE(`date_added`) >= DATE('" . $this->db->escape((string)$data['filter_date_from']) . "')"; + } + + if (!empty($data['filter_date_to'])) { + $implode[] = "DATE(`date_added`) <= DATE('" . $this->db->escape((string)$data['filter_date_to']) . "')"; + } + + if ($implode) { + $sql .= " WHERE " . implode(" AND ", $implode); + } + + $query = $this->db->query($sql); + + return (int)$query->row['total']; + } +} diff --git a/admininistrator/model/user/api.php b/admininistrator/model/user/api.php new file mode 100644 index 0000000..61e0f2b --- /dev/null +++ b/admininistrator/model/user/api.php @@ -0,0 +1,197 @@ +db->query("INSERT INTO `" . DB_PREFIX . "api` SET `username` = '" . $this->db->escape((string)$data['username']) . "', `key` = '" . $this->db->escape((string)$data['key']) . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "', `date_added` = NOW(), `date_modified` = NOW()"); + + $api_id = $this->db->getLastId(); + + if (isset($data['api_ip'])) { + foreach ($data['api_ip'] as $ip) { + if ($ip) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "api_ip` SET `api_id` = '" . (int)$api_id . "', `ip` = '" . $this->db->escape($ip) . "'"); + } + } + } + + return $api_id; + } + + /** + * @param int $api_id + * @param array $data + * + * @return void + */ + public function editApi(int $api_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "api` SET `username` = '" . $this->db->escape((string)$data['username']) . "', `key` = '" . $this->db->escape((string)$data['key']) . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "', `date_modified` = NOW() WHERE `api_id` = '" . (int)$api_id . "'"); + + $this->db->query("DELETE FROM `" . DB_PREFIX . "api_ip` WHERE `api_id` = '" . (int)$api_id . "'"); + + if (isset($data['api_ip'])) { + foreach ($data['api_ip'] as $ip) { + if ($ip) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "api_ip` SET `api_id` = '" . (int)$api_id . "', `ip` = '" . $this->db->escape($ip) . "'"); + } + } + } + } + + /** + * @param int $api_id + * + * @return void + */ + public function deleteApi(int $api_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "api` WHERE `api_id` = '" . (int)$api_id . "'"); + } + + /** + * @param int $api_id + * + * @return array + */ + public function getApi(int $api_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "api` WHERE `api_id` = '" . (int)$api_id . "'"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getApis(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "api`"; + + $sort_data = [ + 'username', + 'status', + 'date_added', + 'date_modified' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `username`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @return int + */ + public function getTotalApis(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "api`"); + + return (int)$query->row['total']; + } + + /** + * @param int $api_id + * @param string $ip + * + * @return void + */ + public function addIp(int $api_id, string $ip): void { + $this->db->query("INSERT INTO `" . DB_PREFIX . "api_ip` SET `api_id` = '" . (int)$api_id . "', `ip` = '" . $this->db->escape($ip) . "'"); + } + + /** + * @param int $api_id + * + * @return array + */ + public function getIps(int $api_id): array { + $ip_data = []; + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "api_ip` WHERE `api_id` = '" . (int)$api_id . "'"); + + foreach ($query->rows as $result) { + $ip_data[] = $result['ip']; + } + + return $ip_data; + } + + /** + * @param int $api_id + * @param string $session_id + * @param string $ip + * + * @return int + */ + public function addSession(int $api_id, string $session_id, string $ip): int { + $api_ip_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "api_ip` WHERE `ip` = '" . $this->db->escape($ip) . "'"); + + if (!$api_ip_query->num_rows) { + $this->db->query("INSERT INTO `" . DB_PREFIX . "api_ip` SET `api_id` = '" . (int)$api_id . "', `ip` = '" . $this->db->escape($ip) . "'"); + } + + $this->db->query("INSERT INTO `" . DB_PREFIX . "api_session` SET `api_id` = '" . (int)$api_id . "', `session_id` = '" . $this->db->escape($session_id) . "', `ip` = '" . $this->db->escape($ip) . "', `date_added` = NOW(), `date_modified` = NOW()"); + + return $this->db->getLastId(); + } + + /** + * @param int $api_id + * + * @return array + */ + public function getSessions(int $api_id): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "api_session` WHERE `api_id` = '" . (int)$api_id . "'"); + + return $query->rows; + } + + /** + * @param int $api_session_id + * + * @return void + */ + public function deleteSession(int $api_session_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "api_session` WHERE `api_session_id` = '" . (int)$api_session_id . "'"); + } + + /** + * @param string $session_id + * + * @return void + */ + public function deleteSessionBySessionId(string $session_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "api_session` WHERE `session_id` = '" . $this->db->escape($session_id) . "'"); + } +} diff --git a/admininistrator/model/user/user.php b/admininistrator/model/user/user.php new file mode 100644 index 0000000..90507b0 --- /dev/null +++ b/admininistrator/model/user/user.php @@ -0,0 +1,332 @@ +db->query("INSERT INTO `" . DB_PREFIX . "user` SET `username` = '" . $this->db->escape((string)$data['username']) . "', `user_group_id` = '" . (int)$data['user_group_id'] . "', `password` = '" . $this->db->escape(password_hash(html_entity_decode($data['password'], ENT_QUOTES, 'UTF-8'), PASSWORD_DEFAULT)) . "', `firstname` = '" . $this->db->escape((string)$data['firstname']) . "', `lastname` = '" . $this->db->escape((string)$data['lastname']) . "', `email` = '" . $this->db->escape((string)$data['email']) . "', `image` = '" . $this->db->escape((string)$data['image']) . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "', `date_added` = NOW()"); + + return $this->db->getLastId(); + } + + /** + * @param int $user_id + * @param array $data + * + * @return void + */ + public function editUser(int $user_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "user` SET `username` = '" . $this->db->escape((string)$data['username']) . "', `user_group_id` = '" . (int)$data['user_group_id'] . "', `firstname` = '" . $this->db->escape((string)$data['firstname']) . "', `lastname` = '" . $this->db->escape((string)$data['lastname']) . "', `email` = '" . $this->db->escape((string)$data['email']) . "', `image` = '" . $this->db->escape((string)$data['image']) . "', `status` = '" . (bool)(isset($data['status']) ? $data['status'] : 0) . "' WHERE `user_id` = '" . (int)$user_id . "'"); + + if ($data['password']) { + $this->db->query("UPDATE `" . DB_PREFIX . "user` SET `password` = '" . $this->db->escape(password_hash(html_entity_decode($data['password'], ENT_QUOTES, 'UTF-8'), PASSWORD_DEFAULT)) . "' WHERE `user_id` = '" . (int)$user_id . "'"); + } + } + + /** + * @param int $user_id + * @param $password + * + * @return void + */ + public function editPassword(int $user_id, $password): void { + $this->db->query("UPDATE `" . DB_PREFIX . "user` SET `password` = '" . $this->db->escape(password_hash(html_entity_decode($password, ENT_QUOTES, 'UTF-8'), PASSWORD_DEFAULT)) . "', `code` = '' WHERE `user_id` = '" . (int)$user_id . "'"); + } + + /** + * @param string $email + * @param string $code + * + * @return void + */ + public function editCode(string $email, string $code): void { + $this->db->query("UPDATE `" . DB_PREFIX . "user` SET `code` = '" . $this->db->escape($code) . "' WHERE LCASE(`email`) = '" . $this->db->escape(oc_strtolower($email)) . "'"); + } + + /** + * @param int $user_id + * + * @return void + */ + public function deleteUser(int $user_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "user` WHERE `user_id` = '" . (int)$user_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "user_history` WHERE `user_id` = '" . (int)$user_id . "'"); + $this->db->query("DELETE FROM `" . DB_PREFIX . "user_history` WHERE `user_id` = '" . (int)$user_id . "'"); + } + + /** + * @param int $user_id + * + * @return array + */ + public function getUser(int $user_id): array { + $query = $this->db->query("SELECT *, (SELECT ug.`name` FROM `" . DB_PREFIX . "user_group` ug WHERE ug.`user_group_id` = u.`user_group_id`) AS user_group FROM `" . DB_PREFIX . "user` u WHERE u.`user_id` = '" . (int)$user_id . "'"); + + return $query->row; + } + + /** + * @param string $username + * + * @return array + */ + public function getUserByUsername(string $username): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "user` WHERE `username` = '" . $this->db->escape($username) . "'"); + + return $query->row; + } + + /** + * @param string $email + * + * @return array + */ + public function getUserByEmail(string $email): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "user` WHERE LCASE(`email`) = '" . $this->db->escape(oc_strtolower($email)) . "'"); + + return $query->row; + } + + /** + * @param string $code + * + * @return array + */ + public function getUserByCode(string $code): array { + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "user` WHERE `code` = '" . $this->db->escape($code) . "' AND `code` != ''"); + + return $query->row; + } + + /** + * @param array $data + * + * @return array + */ + public function getUsers(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "user`"; + + $sort_data = [ + 'username', + 'status', + 'date_added' + ]; + + if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { + $sql .= " ORDER BY " . $data['sort']; + } else { + $sql .= " ORDER BY `username`"; + } + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @return int + */ + public function getTotalUsers(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "user`"); + + return (int)$query->row['total']; + } + + /** + * @param int $user_group_id + * + * @return int + */ + public function getTotalUsersByGroupId(int $user_group_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "user` WHERE `user_group_id` = '" . (int)$user_group_id . "'"); + + return (int)$query->row['total']; + } + + /** + * @param string $email + * + * @return int + */ + public function getTotalUsersByEmail(string $email): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "user` WHERE LCASE(`email`) = '" . $this->db->escape(oc_strtolower($email)) . "'"); + + return (int)$query->row['total']; + } + + /** + * @param int $user_id + * @param array $data + * + * @return void + */ + public function addLogin(int $user_id, array $data): void { + $this->db->query("INSERT INTO `" . DB_PREFIX . "user_login` SET `user_id` = '" . (int)$user_id . "', `ip` = '" . $this->db->escape($data['ip']) . "', `user_agent` = '" . $this->db->escape($data['user_agent']) . "', `date_added` = NOW()"); + } + + /** + * @param int $user_id + * @param int $start + * @param int $limit + * + * @return array + */ + public function getLogins(int $user_id, int $start = 0, int $limit = 10): array { + if ($start < 0) { + $start = 0; + } + + if ($limit < 1) { + $limit = 10; + } + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "user_login` WHERE `user_id` = '" . (int)$user_id . "' LIMIT " . (int)$start . "," . (int)$limit); + + if ($query->num_rows) { + return $query->rows; + } else { + return []; + } + } + + /** + * @param int $user_id + * + * @return int + */ + public function getTotalLogins(int $user_id): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "user_login` WHERE `user_id` = '" . (int)$user_id . "'"); + + if ($query->num_rows) { + return (int)$query->row['total']; + } else { + return 0; + } + } + + /** + * @param int $user_id + * @param array $data + * + * @return void + */ + public function addAuthorize(int $user_id, array $data): void { + $this->db->query("INSERT INTO `" . DB_PREFIX . "user_authorize` SET `user_id` = '" . (int)$user_id . "', `token` = '" . $this->db->escape($data['token']) . "', `ip` = '" . $this->db->escape($data['ip']) . "', `user_agent` = '" . $this->db->escape($data['user_agent']) . "', `date_added` = NOW()"); + } + + /** + * @param int $user_authorize_id + * @param bool $status + * + * @return void + */ + public function editAuthorizeStatus(int $user_authorize_id, bool $status): void { + $this->db->query("UPDATE `" . DB_PREFIX . "user_authorize` SET `status` = '" . (bool)$status . "' WHERE `user_authorize_id` = '" . (int)$user_authorize_id . "'"); + } + + /** + * @param int $user_authorize_id + * @param int $total + * + * @return void + */ + public function editAuthorizeTotal(int $user_authorize_id, int $total): void { + $this->db->query("UPDATE `" . DB_PREFIX . "user_authorize` SET `total` = '" . (int)$total . "' WHERE `user_authorize_id` = '" . (int)$user_authorize_id . "'"); + } + + /** + * @param int $user_authorize_id + * + * @return void + */ + public function deleteAuthorize(int $user_authorize_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "user_authorize` WHERE `user_authorize_id` = '" . (int)$user_authorize_id . "'"); + } + + /** + * @param int $user_id + * @param string $token + * + * @return array + */ + public function getAuthorizeByToken(int $user_id, string $token): array { + $query = $this->db->query("SELECT *, (SELECT SUM(total) FROM `" . DB_PREFIX . "user_authorize` WHERE `user_id` = '" . (int)$user_id . "') AS `attempts` FROM `" . DB_PREFIX . "user_authorize` WHERE `user_id` = '" . (int)$user_id . "' AND `token` = '" . $this->db->escape($token) . "'"); + + return $query->row; + } + + /** + * @param int $user_id + * + * @return void + */ + public function resetAuthorizes(int $user_id): void { + $this->db->query("UPDATE `" . DB_PREFIX . "user_authorize` SET `total` = '0' WHERE `user_id` = '" . (int)$user_id . "'"); + } + + /** + * @param int $user_id + * @param int $start + * @param int $limit + * + * @return array + */ + public function getAuthorizes(int $user_id, int $start = 0, int $limit = 10): array { + if ($start < 0) { + $start = 0; + } + + if ($limit < 1) { + $limit = 10; + } + + $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "user_authorize` WHERE `user_id` = '" . (int)$user_id . "' LIMIT " . (int)$start . "," . (int)$limit); + + if ($query->num_rows) { + return $query->rows; + } else { + return []; + } + } + + /** + * @param int $user_id + * + * @return int + */ + public function getTotalAuthorizes(int $user_id): int { + $query = $this->db->query("SELECT COUNT(*) AS total FROM `" . DB_PREFIX . "user_authorize` WHERE `user_id` = '" . (int)$user_id . "'"); + + if ($query->num_rows) { + return (int)$query->row['total']; + } else { + return 0; + } + } +} diff --git a/admininistrator/model/user/user_group.php b/admininistrator/model/user/user_group.php new file mode 100644 index 0000000..f5ce499 --- /dev/null +++ b/admininistrator/model/user/user_group.php @@ -0,0 +1,134 @@ +db->query("INSERT INTO `" . DB_PREFIX . "user_group` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `permission` = '" . (isset($data['permission']) ? $this->db->escape(json_encode($data['permission'])) : '') . "'"); + + return $this->db->getLastId(); + } + + /** + * @param int $user_group_id + * @param array $data + * + * @return void + */ + public function editUserGroup(int $user_group_id, array $data): void { + $this->db->query("UPDATE `" . DB_PREFIX . "user_group` SET `name` = '" . $this->db->escape((string)$data['name']) . "', `permission` = '" . (isset($data['permission']) ? $this->db->escape(json_encode($data['permission'])) : '') . "' WHERE `user_group_id` = '" . (int)$user_group_id . "'"); + } + + /** + * @param int $user_group_id + * + * @return void + */ + public function deleteUserGroup(int $user_group_id): void { + $this->db->query("DELETE FROM `" . DB_PREFIX . "user_group` WHERE `user_group_id` = '" . (int)$user_group_id . "'"); + } + + /** + * @param int $user_group_id + * + * @return array + */ + public function getUserGroup(int $user_group_id): array { + $query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "user_group` WHERE `user_group_id` = '" . (int)$user_group_id . "'"); + + $user_group = [ + 'name' => $query->row['name'], + 'permission' => json_decode($query->row['permission'], true) + ]; + + return $user_group; + } + + /** + * @param array $data + * + * @return array + */ + public function getUserGroups(array $data = []): array { + $sql = "SELECT * FROM `" . DB_PREFIX . "user_group` ORDER BY `name`"; + + if (isset($data['order']) && ($data['order'] == 'DESC')) { + $sql .= " DESC"; + } else { + $sql .= " ASC"; + } + + if (isset($data['start']) || isset($data['limit'])) { + if ($data['start'] < 0) { + $data['start'] = 0; + } + + if ($data['limit'] < 1) { + $data['limit'] = 20; + } + + $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; + } + + $query = $this->db->query($sql); + + return $query->rows; + } + + /** + * @return int + */ + public function getTotalUserGroups(): int { + $query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "user_group`"); + + return (int)$query->row['total']; + } + + /** + * @param int $user_group_id + * @param string $type + * @param string $route + * + * @return void + */ + public function addPermission(int $user_group_id, string $type, string $route): void { + $user_group_query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "user_group` WHERE `user_group_id` = '" . (int)$user_group_id . "'"); + + if ($user_group_query->num_rows) { + $data = json_decode($user_group_query->row['permission'], true); + + $data[$type][] = $route; + + $this->db->query("UPDATE `" . DB_PREFIX . "user_group` SET `permission` = '" . $this->db->escape(json_encode($data)) . "' WHERE `user_group_id` = '" . (int)$user_group_id . "'"); + } + } + + /** + * @param int $user_group_id + * @param string $type + * @param string $route + * + * @return void + */ + public function removePermission(int $user_group_id, string $type, string $route): void { + $user_group_query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "user_group` WHERE `user_group_id` = '" . (int)$user_group_id . "'"); + + if ($user_group_query->num_rows) { + $data = json_decode($user_group_query->row['permission'], true); + + if (isset($data[$type])) { + $data[$type] = array_diff($data[$type], [$route]); + } + + $this->db->query("UPDATE `" . DB_PREFIX . "user_group` SET `permission` = '" . $this->db->escape(json_encode($data)) . "' WHERE `user_group_id` = '" . (int)$user_group_id . "'"); + } + } +} diff --git a/admininistrator/view/image/checkmark.png b/admininistrator/view/image/checkmark.png new file mode 100644 index 0000000..ad85a91 Binary files /dev/null and b/admininistrator/view/image/checkmark.png differ diff --git a/admininistrator/view/image/logo.png b/admininistrator/view/image/logo.png new file mode 100644 index 0000000..21d9479 Binary files /dev/null and b/admininistrator/view/image/logo.png differ diff --git a/admininistrator/view/javascript/bootstrap/js/bootstrap.bundle.js b/admininistrator/view/javascript/bootstrap/js/bootstrap.bundle.js new file mode 100644 index 0000000..111a2ca --- /dev/null +++ b/admininistrator/view/javascript/bootstrap/js/bootstrap.bundle.js @@ -0,0 +1,6314 @@ +/*! + * Bootstrap v5.3.1 (https://getbootstrap.com/) + * Copyright 2011-2023 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.bootstrap = factory()); +})(this, (function () { 'use strict'; + + /** + * -------------------------------------------------------------------------- + * Bootstrap dom/data.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + /** + * Constants + */ + + const elementMap = new Map(); + const Data = { + set(element, key, instance) { + if (!elementMap.has(element)) { + elementMap.set(element, new Map()); + } + const instanceMap = elementMap.get(element); + + // make it clear we only want one instance per element + // can be removed later when multiple key/instances are fine to be used + if (!instanceMap.has(key) && instanceMap.size !== 0) { + // eslint-disable-next-line no-console + console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(instanceMap.keys())[0]}.`); + return; + } + instanceMap.set(key, instance); + }, + get(element, key) { + if (elementMap.has(element)) { + return elementMap.get(element).get(key) || null; + } + return null; + }, + remove(element, key) { + if (!elementMap.has(element)) { + return; + } + const instanceMap = elementMap.get(element); + instanceMap.delete(key); + + // free up element references if there are no instances left for an element + if (instanceMap.size === 0) { + elementMap.delete(element); + } + } + }; + + /** + * -------------------------------------------------------------------------- + * Bootstrap util/index.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + const MAX_UID = 1000000; + const MILLISECONDS_MULTIPLIER = 1000; + const TRANSITION_END = 'transitionend'; + + /** + * Properly escape IDs selectors to handle weird IDs + * @param {string} selector + * @returns {string} + */ + const parseSelector = selector => { + if (selector && window.CSS && window.CSS.escape) { + // document.querySelector needs escaping to handle IDs (html5+) containing for instance / + selector = selector.replace(/#([^\s"#']+)/g, (match, id) => `#${CSS.escape(id)}`); + } + return selector; + }; + + // Shout-out Angus Croll (https://goo.gl/pxwQGp) + const toType = object => { + if (object === null || object === undefined) { + return `${object}`; + } + return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase(); + }; + + /** + * Public Util API + */ + + const getUID = prefix => { + do { + prefix += Math.floor(Math.random() * MAX_UID); + } while (document.getElementById(prefix)); + return prefix; + }; + const getTransitionDurationFromElement = element => { + if (!element) { + return 0; + } + + // Get transition-duration of the element + let { + transitionDuration, + transitionDelay + } = window.getComputedStyle(element); + const floatTransitionDuration = Number.parseFloat(transitionDuration); + const floatTransitionDelay = Number.parseFloat(transitionDelay); + + // Return 0 if element or transition duration is not found + if (!floatTransitionDuration && !floatTransitionDelay) { + return 0; + } + + // If multiple durations are defined, take the first + transitionDuration = transitionDuration.split(',')[0]; + transitionDelay = transitionDelay.split(',')[0]; + return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER; + }; + const triggerTransitionEnd = element => { + element.dispatchEvent(new Event(TRANSITION_END)); + }; + const isElement$1 = object => { + if (!object || typeof object !== 'object') { + return false; + } + if (typeof object.jquery !== 'undefined') { + object = object[0]; + } + return typeof object.nodeType !== 'undefined'; + }; + const getElement = object => { + // it's a jQuery object or a node element + if (isElement$1(object)) { + return object.jquery ? object[0] : object; + } + if (typeof object === 'string' && object.length > 0) { + return document.querySelector(parseSelector(object)); + } + return null; + }; + const isVisible = element => { + if (!isElement$1(element) || element.getClientRects().length === 0) { + return false; + } + const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible'; + // Handle `details` element as its content may falsie appear visible when it is closed + const closedDetails = element.closest('details:not([open])'); + if (!closedDetails) { + return elementIsVisible; + } + if (closedDetails !== element) { + const summary = element.closest('summary'); + if (summary && summary.parentNode !== closedDetails) { + return false; + } + if (summary === null) { + return false; + } + } + return elementIsVisible; + }; + const isDisabled = element => { + if (!element || element.nodeType !== Node.ELEMENT_NODE) { + return true; + } + if (element.classList.contains('disabled')) { + return true; + } + if (typeof element.disabled !== 'undefined') { + return element.disabled; + } + return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false'; + }; + const findShadowRoot = element => { + if (!document.documentElement.attachShadow) { + return null; + } + + // Can find the shadow root otherwise it'll return the document + if (typeof element.getRootNode === 'function') { + const root = element.getRootNode(); + return root instanceof ShadowRoot ? root : null; + } + if (element instanceof ShadowRoot) { + return element; + } + + // when we don't find a shadow root + if (!element.parentNode) { + return null; + } + return findShadowRoot(element.parentNode); + }; + const noop = () => {}; + + /** + * Trick to restart an element's animation + * + * @param {HTMLElement} element + * @return void + * + * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation + */ + const reflow = element => { + element.offsetHeight; // eslint-disable-line no-unused-expressions + }; + + const getjQuery = () => { + if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) { + return window.jQuery; + } + return null; + }; + const DOMContentLoadedCallbacks = []; + const onDOMContentLoaded = callback => { + if (document.readyState === 'loading') { + // add listener on the first call when the document is in loading state + if (!DOMContentLoadedCallbacks.length) { + document.addEventListener('DOMContentLoaded', () => { + for (const callback of DOMContentLoadedCallbacks) { + callback(); + } + }); + } + DOMContentLoadedCallbacks.push(callback); + } else { + callback(); + } + }; + const isRTL = () => document.documentElement.dir === 'rtl'; + const defineJQueryPlugin = plugin => { + onDOMContentLoaded(() => { + const $ = getjQuery(); + /* istanbul ignore if */ + if ($) { + const name = plugin.NAME; + const JQUERY_NO_CONFLICT = $.fn[name]; + $.fn[name] = plugin.jQueryInterface; + $.fn[name].Constructor = plugin; + $.fn[name].noConflict = () => { + $.fn[name] = JQUERY_NO_CONFLICT; + return plugin.jQueryInterface; + }; + } + }); + }; + const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => { + return typeof possibleCallback === 'function' ? possibleCallback(...args) : defaultValue; + }; + const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => { + if (!waitForTransition) { + execute(callback); + return; + } + const durationPadding = 5; + const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding; + let called = false; + const handler = ({ + target + }) => { + if (target !== transitionElement) { + return; + } + called = true; + transitionElement.removeEventListener(TRANSITION_END, handler); + execute(callback); + }; + transitionElement.addEventListener(TRANSITION_END, handler); + setTimeout(() => { + if (!called) { + triggerTransitionEnd(transitionElement); + } + }, emulatedDuration); + }; + + /** + * Return the previous/next element of a list. + * + * @param {array} list The list of elements + * @param activeElement The active element + * @param shouldGetNext Choose to get next or previous element + * @param isCycleAllowed + * @return {Element|elem} The proper element + */ + const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => { + const listLength = list.length; + let index = list.indexOf(activeElement); + + // if the element does not exist in the list return an element + // depending on the direction and if cycle is allowed + if (index === -1) { + return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0]; + } + index += shouldGetNext ? 1 : -1; + if (isCycleAllowed) { + index = (index + listLength) % listLength; + } + return list[Math.max(0, Math.min(index, listLength - 1))]; + }; + + /** + * -------------------------------------------------------------------------- + * Bootstrap dom/event-handler.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + + /** + * Constants + */ + + const namespaceRegex = /[^.]*(?=\..*)\.|.*/; + const stripNameRegex = /\..*/; + const stripUidRegex = /::\d+$/; + const eventRegistry = {}; // Events storage + let uidEvent = 1; + const customEvents = { + mouseenter: 'mouseover', + mouseleave: 'mouseout' + }; + const nativeEvents = new Set(['click', 'dblclick', 'mouseup', 'mousedown', 'contextmenu', 'mousewheel', 'DOMMouseScroll', 'mouseover', 'mouseout', 'mousemove', 'selectstart', 'selectend', 'keydown', 'keypress', 'keyup', 'orientationchange', 'touchstart', 'touchmove', 'touchend', 'touchcancel', 'pointerdown', 'pointermove', 'pointerup', 'pointerleave', 'pointercancel', 'gesturestart', 'gesturechange', 'gestureend', 'focus', 'blur', 'change', 'reset', 'select', 'submit', 'focusin', 'focusout', 'load', 'unload', 'beforeunload', 'resize', 'move', 'DOMContentLoaded', 'readystatechange', 'error', 'abort', 'scroll']); + + /** + * Private methods + */ + + function makeEventUid(element, uid) { + return uid && `${uid}::${uidEvent++}` || element.uidEvent || uidEvent++; + } + function getElementEvents(element) { + const uid = makeEventUid(element); + element.uidEvent = uid; + eventRegistry[uid] = eventRegistry[uid] || {}; + return eventRegistry[uid]; + } + function bootstrapHandler(element, fn) { + return function handler(event) { + hydrateObj(event, { + delegateTarget: element + }); + if (handler.oneOff) { + EventHandler.off(element, event.type, fn); + } + return fn.apply(element, [event]); + }; + } + function bootstrapDelegationHandler(element, selector, fn) { + return function handler(event) { + const domElements = element.querySelectorAll(selector); + for (let { + target + } = event; target && target !== this; target = target.parentNode) { + for (const domElement of domElements) { + if (domElement !== target) { + continue; + } + hydrateObj(event, { + delegateTarget: target + }); + if (handler.oneOff) { + EventHandler.off(element, event.type, selector, fn); + } + return fn.apply(target, [event]); + } + } + }; + } + function findHandler(events, callable, delegationSelector = null) { + return Object.values(events).find(event => event.callable === callable && event.delegationSelector === delegationSelector); + } + function normalizeParameters(originalTypeEvent, handler, delegationFunction) { + const isDelegated = typeof handler === 'string'; + // TODO: tooltip passes `false` instead of selector, so we need to check + const callable = isDelegated ? delegationFunction : handler || delegationFunction; + let typeEvent = getTypeEvent(originalTypeEvent); + if (!nativeEvents.has(typeEvent)) { + typeEvent = originalTypeEvent; + } + return [isDelegated, callable, typeEvent]; + } + function addHandler(element, originalTypeEvent, handler, delegationFunction, oneOff) { + if (typeof originalTypeEvent !== 'string' || !element) { + return; + } + let [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction); + + // in case of mouseenter or mouseleave wrap the handler within a function that checks for its DOM position + // this prevents the handler from being dispatched the same way as mouseover or mouseout does + if (originalTypeEvent in customEvents) { + const wrapFunction = fn => { + return function (event) { + if (!event.relatedTarget || event.relatedTarget !== event.delegateTarget && !event.delegateTarget.contains(event.relatedTarget)) { + return fn.call(this, event); + } + }; + }; + callable = wrapFunction(callable); + } + const events = getElementEvents(element); + const handlers = events[typeEvent] || (events[typeEvent] = {}); + const previousFunction = findHandler(handlers, callable, isDelegated ? handler : null); + if (previousFunction) { + previousFunction.oneOff = previousFunction.oneOff && oneOff; + return; + } + const uid = makeEventUid(callable, originalTypeEvent.replace(namespaceRegex, '')); + const fn = isDelegated ? bootstrapDelegationHandler(element, handler, callable) : bootstrapHandler(element, callable); + fn.delegationSelector = isDelegated ? handler : null; + fn.callable = callable; + fn.oneOff = oneOff; + fn.uidEvent = uid; + handlers[uid] = fn; + element.addEventListener(typeEvent, fn, isDelegated); + } + function removeHandler(element, events, typeEvent, handler, delegationSelector) { + const fn = findHandler(events[typeEvent], handler, delegationSelector); + if (!fn) { + return; + } + element.removeEventListener(typeEvent, fn, Boolean(delegationSelector)); + delete events[typeEvent][fn.uidEvent]; + } + function removeNamespacedHandlers(element, events, typeEvent, namespace) { + const storeElementEvent = events[typeEvent] || {}; + for (const [handlerKey, event] of Object.entries(storeElementEvent)) { + if (handlerKey.includes(namespace)) { + removeHandler(element, events, typeEvent, event.callable, event.delegationSelector); + } + } + } + function getTypeEvent(event) { + // allow to get the native events from namespaced events ('click.bs.button' --> 'click') + event = event.replace(stripNameRegex, ''); + return customEvents[event] || event; + } + const EventHandler = { + on(element, event, handler, delegationFunction) { + addHandler(element, event, handler, delegationFunction, false); + }, + one(element, event, handler, delegationFunction) { + addHandler(element, event, handler, delegationFunction, true); + }, + off(element, originalTypeEvent, handler, delegationFunction) { + if (typeof originalTypeEvent !== 'string' || !element) { + return; + } + const [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction); + const inNamespace = typeEvent !== originalTypeEvent; + const events = getElementEvents(element); + const storeElementEvent = events[typeEvent] || {}; + const isNamespace = originalTypeEvent.startsWith('.'); + if (typeof callable !== 'undefined') { + // Simplest case: handler is passed, remove that listener ONLY. + if (!Object.keys(storeElementEvent).length) { + return; + } + removeHandler(element, events, typeEvent, callable, isDelegated ? handler : null); + return; + } + if (isNamespace) { + for (const elementEvent of Object.keys(events)) { + removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.slice(1)); + } + } + for (const [keyHandlers, event] of Object.entries(storeElementEvent)) { + const handlerKey = keyHandlers.replace(stripUidRegex, ''); + if (!inNamespace || originalTypeEvent.includes(handlerKey)) { + removeHandler(element, events, typeEvent, event.callable, event.delegationSelector); + } + } + }, + trigger(element, event, args) { + if (typeof event !== 'string' || !element) { + return null; + } + const $ = getjQuery(); + const typeEvent = getTypeEvent(event); + const inNamespace = event !== typeEvent; + let jQueryEvent = null; + let bubbles = true; + let nativeDispatch = true; + let defaultPrevented = false; + if (inNamespace && $) { + jQueryEvent = $.Event(event, args); + $(element).trigger(jQueryEvent); + bubbles = !jQueryEvent.isPropagationStopped(); + nativeDispatch = !jQueryEvent.isImmediatePropagationStopped(); + defaultPrevented = jQueryEvent.isDefaultPrevented(); + } + const evt = hydrateObj(new Event(event, { + bubbles, + cancelable: true + }), args); + if (defaultPrevented) { + evt.preventDefault(); + } + if (nativeDispatch) { + element.dispatchEvent(evt); + } + if (evt.defaultPrevented && jQueryEvent) { + jQueryEvent.preventDefault(); + } + return evt; + } + }; + function hydrateObj(obj, meta = {}) { + for (const [key, value] of Object.entries(meta)) { + try { + obj[key] = value; + } catch (_unused) { + Object.defineProperty(obj, key, { + configurable: true, + get() { + return value; + } + }); + } + } + return obj; + } + + /** + * -------------------------------------------------------------------------- + * Bootstrap dom/manipulator.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + function normalizeData(value) { + if (value === 'true') { + return true; + } + if (value === 'false') { + return false; + } + if (value === Number(value).toString()) { + return Number(value); + } + if (value === '' || value === 'null') { + return null; + } + if (typeof value !== 'string') { + return value; + } + try { + return JSON.parse(decodeURIComponent(value)); + } catch (_unused) { + return value; + } + } + function normalizeDataKey(key) { + return key.replace(/[A-Z]/g, chr => `-${chr.toLowerCase()}`); + } + const Manipulator = { + setDataAttribute(element, key, value) { + element.setAttribute(`data-bs-${normalizeDataKey(key)}`, value); + }, + removeDataAttribute(element, key) { + element.removeAttribute(`data-bs-${normalizeDataKey(key)}`); + }, + getDataAttributes(element) { + if (!element) { + return {}; + } + const attributes = {}; + const bsKeys = Object.keys(element.dataset).filter(key => key.startsWith('bs') && !key.startsWith('bsConfig')); + for (const key of bsKeys) { + let pureKey = key.replace(/^bs/, ''); + pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1, pureKey.length); + attributes[pureKey] = normalizeData(element.dataset[key]); + } + return attributes; + }, + getDataAttribute(element, key) { + return normalizeData(element.getAttribute(`data-bs-${normalizeDataKey(key)}`)); + } + }; + + /** + * -------------------------------------------------------------------------- + * Bootstrap util/config.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + + /** + * Class definition + */ + + class Config { + // Getters + static get Default() { + return {}; + } + static get DefaultType() { + return {}; + } + static get NAME() { + throw new Error('You have to implement the static method "NAME", for each component!'); + } + _getConfig(config) { + config = this._mergeConfigObj(config); + config = this._configAfterMerge(config); + this._typeCheckConfig(config); + return config; + } + _configAfterMerge(config) { + return config; + } + _mergeConfigObj(config, element) { + const jsonConfig = isElement$1(element) ? Manipulator.getDataAttribute(element, 'config') : {}; // try to parse + + return { + ...this.constructor.Default, + ...(typeof jsonConfig === 'object' ? jsonConfig : {}), + ...(isElement$1(element) ? Manipulator.getDataAttributes(element) : {}), + ...(typeof config === 'object' ? config : {}) + }; + } + _typeCheckConfig(config, configTypes = this.constructor.DefaultType) { + for (const [property, expectedTypes] of Object.entries(configTypes)) { + const value = config[property]; + const valueType = isElement$1(value) ? 'element' : toType(value); + if (!new RegExp(expectedTypes).test(valueType)) { + throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`); + } + } + } + } + + /** + * -------------------------------------------------------------------------- + * Bootstrap base-component.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + + /** + * Constants + */ + + const VERSION = '5.3.1'; + + /** + * Class definition + */ + + class BaseComponent extends Config { + constructor(element, config) { + super(); + element = getElement(element); + if (!element) { + return; + } + this._element = element; + this._config = this._getConfig(config); + Data.set(this._element, this.constructor.DATA_KEY, this); + } + + // Public + dispose() { + Data.remove(this._element, this.constructor.DATA_KEY); + EventHandler.off(this._element, this.constructor.EVENT_KEY); + for (const propertyName of Object.getOwnPropertyNames(this)) { + this[propertyName] = null; + } + } + _queueCallback(callback, element, isAnimated = true) { + executeAfterTransition(callback, element, isAnimated); + } + _getConfig(config) { + config = this._mergeConfigObj(config, this._element); + config = this._configAfterMerge(config); + this._typeCheckConfig(config); + return config; + } + + // Static + static getInstance(element) { + return Data.get(getElement(element), this.DATA_KEY); + } + static getOrCreateInstance(element, config = {}) { + return this.getInstance(element) || new this(element, typeof config === 'object' ? config : null); + } + static get VERSION() { + return VERSION; + } + static get DATA_KEY() { + return `bs.${this.NAME}`; + } + static get EVENT_KEY() { + return `.${this.DATA_KEY}`; + } + static eventName(name) { + return `${name}${this.EVENT_KEY}`; + } + } + + /** + * -------------------------------------------------------------------------- + * Bootstrap dom/selector-engine.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + const getSelector = element => { + let selector = element.getAttribute('data-bs-target'); + if (!selector || selector === '#') { + let hrefAttribute = element.getAttribute('href'); + + // The only valid content that could double as a selector are IDs or classes, + // so everything starting with `#` or `.`. If a "real" URL is used as the selector, + // `document.querySelector` will rightfully complain it is invalid. + // See https://github.com/twbs/bootstrap/issues/32273 + if (!hrefAttribute || !hrefAttribute.includes('#') && !hrefAttribute.startsWith('.')) { + return null; + } + + // Just in case some CMS puts out a full URL with the anchor appended + if (hrefAttribute.includes('#') && !hrefAttribute.startsWith('#')) { + hrefAttribute = `#${hrefAttribute.split('#')[1]}`; + } + selector = hrefAttribute && hrefAttribute !== '#' ? hrefAttribute.trim() : null; + } + return parseSelector(selector); + }; + const SelectorEngine = { + find(selector, element = document.documentElement) { + return [].concat(...Element.prototype.querySelectorAll.call(element, selector)); + }, + findOne(selector, element = document.documentElement) { + return Element.prototype.querySelector.call(element, selector); + }, + children(element, selector) { + return [].concat(...element.children).filter(child => child.matches(selector)); + }, + parents(element, selector) { + const parents = []; + let ancestor = element.parentNode.closest(selector); + while (ancestor) { + parents.push(ancestor); + ancestor = ancestor.parentNode.closest(selector); + } + return parents; + }, + prev(element, selector) { + let previous = element.previousElementSibling; + while (previous) { + if (previous.matches(selector)) { + return [previous]; + } + previous = previous.previousElementSibling; + } + return []; + }, + // TODO: this is now unused; remove later along with prev() + next(element, selector) { + let next = element.nextElementSibling; + while (next) { + if (next.matches(selector)) { + return [next]; + } + next = next.nextElementSibling; + } + return []; + }, + focusableChildren(element) { + const focusables = ['a', 'button', 'input', 'textarea', 'select', 'details', '[tabindex]', '[contenteditable="true"]'].map(selector => `${selector}:not([tabindex^="-"])`).join(','); + return this.find(focusables, element).filter(el => !isDisabled(el) && isVisible(el)); + }, + getSelectorFromElement(element) { + const selector = getSelector(element); + if (selector) { + return SelectorEngine.findOne(selector) ? selector : null; + } + return null; + }, + getElementFromSelector(element) { + const selector = getSelector(element); + return selector ? SelectorEngine.findOne(selector) : null; + }, + getMultipleElementsFromSelector(element) { + const selector = getSelector(element); + return selector ? SelectorEngine.find(selector) : []; + } + }; + + /** + * -------------------------------------------------------------------------- + * Bootstrap util/component-functions.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + const enableDismissTrigger = (component, method = 'hide') => { + const clickEvent = `click.dismiss${component.EVENT_KEY}`; + const name = component.NAME; + EventHandler.on(document, clickEvent, `[data-bs-dismiss="${name}"]`, function (event) { + if (['A', 'AREA'].includes(this.tagName)) { + event.preventDefault(); + } + if (isDisabled(this)) { + return; + } + const target = SelectorEngine.getElementFromSelector(this) || this.closest(`.${name}`); + const instance = component.getOrCreateInstance(target); + + // Method argument is left, for Alert and only, as it doesn't implement the 'hide' method + instance[method](); + }); + }; + + /** + * -------------------------------------------------------------------------- + * Bootstrap alert.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + + /** + * Constants + */ + + const NAME$f = 'alert'; + const DATA_KEY$a = 'bs.alert'; + const EVENT_KEY$b = `.${DATA_KEY$a}`; + const EVENT_CLOSE = `close${EVENT_KEY$b}`; + const EVENT_CLOSED = `closed${EVENT_KEY$b}`; + const CLASS_NAME_FADE$5 = 'fade'; + const CLASS_NAME_SHOW$8 = 'show'; + + /** + * Class definition + */ + + class Alert extends BaseComponent { + // Getters + static get NAME() { + return NAME$f; + } + + // Public + close() { + const closeEvent = EventHandler.trigger(this._element, EVENT_CLOSE); + if (closeEvent.defaultPrevented) { + return; + } + this._element.classList.remove(CLASS_NAME_SHOW$8); + const isAnimated = this._element.classList.contains(CLASS_NAME_FADE$5); + this._queueCallback(() => this._destroyElement(), this._element, isAnimated); + } + + // Private + _destroyElement() { + this._element.remove(); + EventHandler.trigger(this._element, EVENT_CLOSED); + this.dispose(); + } + + // Static + static jQueryInterface(config) { + return this.each(function () { + const data = Alert.getOrCreateInstance(this); + if (typeof config !== 'string') { + return; + } + if (data[config] === undefined || config.startsWith('_') || config === 'constructor') { + throw new TypeError(`No method named "${config}"`); + } + data[config](this); + }); + } + } + + /** + * Data API implementation + */ + + enableDismissTrigger(Alert, 'close'); + + /** + * jQuery + */ + + defineJQueryPlugin(Alert); + + /** + * -------------------------------------------------------------------------- + * Bootstrap button.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + + /** + * Constants + */ + + const NAME$e = 'button'; + const DATA_KEY$9 = 'bs.button'; + const EVENT_KEY$a = `.${DATA_KEY$9}`; + const DATA_API_KEY$6 = '.data-api'; + const CLASS_NAME_ACTIVE$3 = 'active'; + const SELECTOR_DATA_TOGGLE$5 = '[data-bs-toggle="button"]'; + const EVENT_CLICK_DATA_API$6 = `click${EVENT_KEY$a}${DATA_API_KEY$6}`; + + /** + * Class definition + */ + + class Button extends BaseComponent { + // Getters + static get NAME() { + return NAME$e; + } + + // Public + toggle() { + // Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method + this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE$3)); + } + + // Static + static jQueryInterface(config) { + return this.each(function () { + const data = Button.getOrCreateInstance(this); + if (config === 'toggle') { + data[config](); + } + }); + } + } + + /** + * Data API implementation + */ + + EventHandler.on(document, EVENT_CLICK_DATA_API$6, SELECTOR_DATA_TOGGLE$5, event => { + event.preventDefault(); + const button = event.target.closest(SELECTOR_DATA_TOGGLE$5); + const data = Button.getOrCreateInstance(button); + data.toggle(); + }); + + /** + * jQuery + */ + + defineJQueryPlugin(Button); + + /** + * -------------------------------------------------------------------------- + * Bootstrap util/swipe.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + + /** + * Constants + */ + + const NAME$d = 'swipe'; + const EVENT_KEY$9 = '.bs.swipe'; + const EVENT_TOUCHSTART = `touchstart${EVENT_KEY$9}`; + const EVENT_TOUCHMOVE = `touchmove${EVENT_KEY$9}`; + const EVENT_TOUCHEND = `touchend${EVENT_KEY$9}`; + const EVENT_POINTERDOWN = `pointerdown${EVENT_KEY$9}`; + const EVENT_POINTERUP = `pointerup${EVENT_KEY$9}`; + const POINTER_TYPE_TOUCH = 'touch'; + const POINTER_TYPE_PEN = 'pen'; + const CLASS_NAME_POINTER_EVENT = 'pointer-event'; + const SWIPE_THRESHOLD = 40; + const Default$c = { + endCallback: null, + leftCallback: null, + rightCallback: null + }; + const DefaultType$c = { + endCallback: '(function|null)', + leftCallback: '(function|null)', + rightCallback: '(function|null)' + }; + + /** + * Class definition + */ + + class Swipe extends Config { + constructor(element, config) { + super(); + this._element = element; + if (!element || !Swipe.isSupported()) { + return; + } + this._config = this._getConfig(config); + this._deltaX = 0; + this._supportPointerEvents = Boolean(window.PointerEvent); + this._initEvents(); + } + + // Getters + static get Default() { + return Default$c; + } + static get DefaultType() { + return DefaultType$c; + } + static get NAME() { + return NAME$d; + } + + // Public + dispose() { + EventHandler.off(this._element, EVENT_KEY$9); + } + + // Private + _start(event) { + if (!this._supportPointerEvents) { + this._deltaX = event.touches[0].clientX; + return; + } + if (this._eventIsPointerPenTouch(event)) { + this._deltaX = event.clientX; + } + } + _end(event) { + if (this._eventIsPointerPenTouch(event)) { + this._deltaX = event.clientX - this._deltaX; + } + this._handleSwipe(); + execute(this._config.endCallback); + } + _move(event) { + this._deltaX = event.touches && event.touches.length > 1 ? 0 : event.touches[0].clientX - this._deltaX; + } + _handleSwipe() { + const absDeltaX = Math.abs(this._deltaX); + if (absDeltaX <= SWIPE_THRESHOLD) { + return; + } + const direction = absDeltaX / this._deltaX; + this._deltaX = 0; + if (!direction) { + return; + } + execute(direction > 0 ? this._config.rightCallback : this._config.leftCallback); + } + _initEvents() { + if (this._supportPointerEvents) { + EventHandler.on(this._element, EVENT_POINTERDOWN, event => this._start(event)); + EventHandler.on(this._element, EVENT_POINTERUP, event => this._end(event)); + this._element.classList.add(CLASS_NAME_POINTER_EVENT); + } else { + EventHandler.on(this._element, EVENT_TOUCHSTART, event => this._start(event)); + EventHandler.on(this._element, EVENT_TOUCHMOVE, event => this._move(event)); + EventHandler.on(this._element, EVENT_TOUCHEND, event => this._end(event)); + } + } + _eventIsPointerPenTouch(event) { + return this._supportPointerEvents && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH); + } + + // Static + static isSupported() { + return 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0; + } + } + + /** + * -------------------------------------------------------------------------- + * Bootstrap carousel.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + + /** + * Constants + */ + + const NAME$c = 'carousel'; + const DATA_KEY$8 = 'bs.carousel'; + const EVENT_KEY$8 = `.${DATA_KEY$8}`; + const DATA_API_KEY$5 = '.data-api'; + const ARROW_LEFT_KEY$1 = 'ArrowLeft'; + const ARROW_RIGHT_KEY$1 = 'ArrowRight'; + const TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch + + const ORDER_NEXT = 'next'; + const ORDER_PREV = 'prev'; + const DIRECTION_LEFT = 'left'; + const DIRECTION_RIGHT = 'right'; + const EVENT_SLIDE = `slide${EVENT_KEY$8}`; + const EVENT_SLID = `slid${EVENT_KEY$8}`; + const EVENT_KEYDOWN$1 = `keydown${EVENT_KEY$8}`; + const EVENT_MOUSEENTER$1 = `mouseenter${EVENT_KEY$8}`; + const EVENT_MOUSELEAVE$1 = `mouseleave${EVENT_KEY$8}`; + const EVENT_DRAG_START = `dragstart${EVENT_KEY$8}`; + const EVENT_LOAD_DATA_API$3 = `load${EVENT_KEY$8}${DATA_API_KEY$5}`; + const EVENT_CLICK_DATA_API$5 = `click${EVENT_KEY$8}${DATA_API_KEY$5}`; + const CLASS_NAME_CAROUSEL = 'carousel'; + const CLASS_NAME_ACTIVE$2 = 'active'; + const CLASS_NAME_SLIDE = 'slide'; + const CLASS_NAME_END = 'carousel-item-end'; + const CLASS_NAME_START = 'carousel-item-start'; + const CLASS_NAME_NEXT = 'carousel-item-next'; + const CLASS_NAME_PREV = 'carousel-item-prev'; + const SELECTOR_ACTIVE = '.active'; + const SELECTOR_ITEM = '.carousel-item'; + const SELECTOR_ACTIVE_ITEM = SELECTOR_ACTIVE + SELECTOR_ITEM; + const SELECTOR_ITEM_IMG = '.carousel-item img'; + const SELECTOR_INDICATORS = '.carousel-indicators'; + const SELECTOR_DATA_SLIDE = '[data-bs-slide], [data-bs-slide-to]'; + const SELECTOR_DATA_RIDE = '[data-bs-ride="carousel"]'; + const KEY_TO_DIRECTION = { + [ARROW_LEFT_KEY$1]: DIRECTION_RIGHT, + [ARROW_RIGHT_KEY$1]: DIRECTION_LEFT + }; + const Default$b = { + interval: 5000, + keyboard: true, + pause: 'hover', + ride: false, + touch: true, + wrap: true + }; + const DefaultType$b = { + interval: '(number|boolean)', + // TODO:v6 remove boolean support + keyboard: 'boolean', + pause: '(string|boolean)', + ride: '(boolean|string)', + touch: 'boolean', + wrap: 'boolean' + }; + + /** + * Class definition + */ + + class Carousel extends BaseComponent { + constructor(element, config) { + super(element, config); + this._interval = null; + this._activeElement = null; + this._isSliding = false; + this.touchTimeout = null; + this._swipeHelper = null; + this._indicatorsElement = SelectorEngine.findOne(SELECTOR_INDICATORS, this._element); + this._addEventListeners(); + if (this._config.ride === CLASS_NAME_CAROUSEL) { + this.cycle(); + } + } + + // Getters + static get Default() { + return Default$b; + } + static get DefaultType() { + return DefaultType$b; + } + static get NAME() { + return NAME$c; + } + + // Public + next() { + this._slide(ORDER_NEXT); + } + nextWhenVisible() { + // FIXME TODO use `document.visibilityState` + // Don't call next when the page isn't visible + // or the carousel or its parent isn't visible + if (!document.hidden && isVisible(this._element)) { + this.next(); + } + } + prev() { + this._slide(ORDER_PREV); + } + pause() { + if (this._isSliding) { + triggerTransitionEnd(this._element); + } + this._clearInterval(); + } + cycle() { + this._clearInterval(); + this._updateInterval(); + this._interval = setInterval(() => this.nextWhenVisible(), this._config.interval); + } + _maybeEnableCycle() { + if (!this._config.ride) { + return; + } + if (this._isSliding) { + EventHandler.one(this._element, EVENT_SLID, () => this.cycle()); + return; + } + this.cycle(); + } + to(index) { + const items = this._getItems(); + if (index > items.length - 1 || index < 0) { + return; + } + if (this._isSliding) { + EventHandler.one(this._element, EVENT_SLID, () => this.to(index)); + return; + } + const activeIndex = this._getItemIndex(this._getActive()); + if (activeIndex === index) { + return; + } + const order = index > activeIndex ? ORDER_NEXT : ORDER_PREV; + this._slide(order, items[index]); + } + dispose() { + if (this._swipeHelper) { + this._swipeHelper.dispose(); + } + super.dispose(); + } + + // Private + _configAfterMerge(config) { + config.defaultInterval = config.interval; + return config; + } + _addEventListeners() { + if (this._config.keyboard) { + EventHandler.on(this._element, EVENT_KEYDOWN$1, event => this._keydown(event)); + } + if (this._config.pause === 'hover') { + EventHandler.on(this._element, EVENT_MOUSEENTER$1, () => this.pause()); + EventHandler.on(this._element, EVENT_MOUSELEAVE$1, () => this._maybeEnableCycle()); + } + if (this._config.touch && Swipe.isSupported()) { + this._addTouchEventListeners(); + } + } + _addTouchEventListeners() { + for (const img of SelectorEngine.find(SELECTOR_ITEM_IMG, this._element)) { + EventHandler.on(img, EVENT_DRAG_START, event => event.preventDefault()); + } + const endCallBack = () => { + if (this._config.pause !== 'hover') { + return; + } + + // If it's a touch-enabled device, mouseenter/leave are fired as + // part of the mouse compatibility events on first tap - the carousel + // would stop cycling until user tapped out of it; + // here, we listen for touchend, explicitly pause the carousel + // (as if it's the second time we tap on it, mouseenter compat event + // is NOT fired) and after a timeout (to allow for mouse compatibility + // events to fire) we explicitly restart cycling + + this.pause(); + if (this.touchTimeout) { + clearTimeout(this.touchTimeout); + } + this.touchTimeout = setTimeout(() => this._maybeEnableCycle(), TOUCHEVENT_COMPAT_WAIT + this._config.interval); + }; + const swipeConfig = { + leftCallback: () => this._slide(this._directionToOrder(DIRECTION_LEFT)), + rightCallback: () => this._slide(this._directionToOrder(DIRECTION_RIGHT)), + endCallback: endCallBack + }; + this._swipeHelper = new Swipe(this._element, swipeConfig); + } + _keydown(event) { + if (/input|textarea/i.test(event.target.tagName)) { + return; + } + const direction = KEY_TO_DIRECTION[event.key]; + if (direction) { + event.preventDefault(); + this._slide(this._directionToOrder(direction)); + } + } + _getItemIndex(element) { + return this._getItems().indexOf(element); + } + _setActiveIndicatorElement(index) { + if (!this._indicatorsElement) { + return; + } + const activeIndicator = SelectorEngine.findOne(SELECTOR_ACTIVE, this._indicatorsElement); + activeIndicator.classList.remove(CLASS_NAME_ACTIVE$2); + activeIndicator.removeAttribute('aria-current'); + const newActiveIndicator = SelectorEngine.findOne(`[data-bs-slide-to="${index}"]`, this._indicatorsElement); + if (newActiveIndicator) { + newActiveIndicator.classList.add(CLASS_NAME_ACTIVE$2); + newActiveIndicator.setAttribute('aria-current', 'true'); + } + } + _updateInterval() { + const element = this._activeElement || this._getActive(); + if (!element) { + return; + } + const elementInterval = Number.parseInt(element.getAttribute('data-bs-interval'), 10); + this._config.interval = elementInterval || this._config.defaultInterval; + } + _slide(order, element = null) { + if (this._isSliding) { + return; + } + const activeElement = this._getActive(); + const isNext = order === ORDER_NEXT; + const nextElement = element || getNextActiveElement(this._getItems(), activeElement, isNext, this._config.wrap); + if (nextElement === activeElement) { + return; + } + const nextElementIndex = this._getItemIndex(nextElement); + const triggerEvent = eventName => { + return EventHandler.trigger(this._element, eventName, { + relatedTarget: nextElement, + direction: this._orderToDirection(order), + from: this._getItemIndex(activeElement), + to: nextElementIndex + }); + }; + const slideEvent = triggerEvent(EVENT_SLIDE); + if (slideEvent.defaultPrevented) { + return; + } + if (!activeElement || !nextElement) { + // Some weirdness is happening, so we bail + // TODO: change tests that use empty divs to avoid this check + return; + } + const isCycling = Boolean(this._interval); + this.pause(); + this._isSliding = true; + this._setActiveIndicatorElement(nextElementIndex); + this._activeElement = nextElement; + const directionalClassName = isNext ? CLASS_NAME_START : CLASS_NAME_END; + const orderClassName = isNext ? CLASS_NAME_NEXT : CLASS_NAME_PREV; + nextElement.classList.add(orderClassName); + reflow(nextElement); + activeElement.classList.add(directionalClassName); + nextElement.classList.add(directionalClassName); + const completeCallBack = () => { + nextElement.classList.remove(directionalClassName, orderClassName); + nextElement.classList.add(CLASS_NAME_ACTIVE$2); + activeElement.classList.remove(CLASS_NAME_ACTIVE$2, orderClassName, directionalClassName); + this._isSliding = false; + triggerEvent(EVENT_SLID); + }; + this._queueCallback(completeCallBack, activeElement, this._isAnimated()); + if (isCycling) { + this.cycle(); + } + } + _isAnimated() { + return this._element.classList.contains(CLASS_NAME_SLIDE); + } + _getActive() { + return SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element); + } + _getItems() { + return SelectorEngine.find(SELECTOR_ITEM, this._element); + } + _clearInterval() { + if (this._interval) { + clearInterval(this._interval); + this._interval = null; + } + } + _directionToOrder(direction) { + if (isRTL()) { + return direction === DIRECTION_LEFT ? ORDER_PREV : ORDER_NEXT; + } + return direction === DIRECTION_LEFT ? ORDER_NEXT : ORDER_PREV; + } + _orderToDirection(order) { + if (isRTL()) { + return order === ORDER_PREV ? DIRECTION_LEFT : DIRECTION_RIGHT; + } + return order === ORDER_PREV ? DIRECTION_RIGHT : DIRECTION_LEFT; + } + + // Static + static jQueryInterface(config) { + return this.each(function () { + const data = Carousel.getOrCreateInstance(this, config); + if (typeof config === 'number') { + data.to(config); + return; + } + if (typeof config === 'string') { + if (data[config] === undefined || config.startsWith('_') || config === 'constructor') { + throw new TypeError(`No method named "${config}"`); + } + data[config](); + } + }); + } + } + + /** + * Data API implementation + */ + + EventHandler.on(document, EVENT_CLICK_DATA_API$5, SELECTOR_DATA_SLIDE, function (event) { + const target = SelectorEngine.getElementFromSelector(this); + if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) { + return; + } + event.preventDefault(); + const carousel = Carousel.getOrCreateInstance(target); + const slideIndex = this.getAttribute('data-bs-slide-to'); + if (slideIndex) { + carousel.to(slideIndex); + carousel._maybeEnableCycle(); + return; + } + if (Manipulator.getDataAttribute(this, 'slide') === 'next') { + carousel.next(); + carousel._maybeEnableCycle(); + return; + } + carousel.prev(); + carousel._maybeEnableCycle(); + }); + EventHandler.on(window, EVENT_LOAD_DATA_API$3, () => { + const carousels = SelectorEngine.find(SELECTOR_DATA_RIDE); + for (const carousel of carousels) { + Carousel.getOrCreateInstance(carousel); + } + }); + + /** + * jQuery + */ + + defineJQueryPlugin(Carousel); + + /** + * -------------------------------------------------------------------------- + * Bootstrap collapse.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + + /** + * Constants + */ + + const NAME$b = 'collapse'; + const DATA_KEY$7 = 'bs.collapse'; + const EVENT_KEY$7 = `.${DATA_KEY$7}`; + const DATA_API_KEY$4 = '.data-api'; + const EVENT_SHOW$6 = `show${EVENT_KEY$7}`; + const EVENT_SHOWN$6 = `shown${EVENT_KEY$7}`; + const EVENT_HIDE$6 = `hide${EVENT_KEY$7}`; + const EVENT_HIDDEN$6 = `hidden${EVENT_KEY$7}`; + const EVENT_CLICK_DATA_API$4 = `click${EVENT_KEY$7}${DATA_API_KEY$4}`; + const CLASS_NAME_SHOW$7 = 'show'; + const CLASS_NAME_COLLAPSE = 'collapse'; + const CLASS_NAME_COLLAPSING = 'collapsing'; + const CLASS_NAME_COLLAPSED = 'collapsed'; + const CLASS_NAME_DEEPER_CHILDREN = `:scope .${CLASS_NAME_COLLAPSE} .${CLASS_NAME_COLLAPSE}`; + const CLASS_NAME_HORIZONTAL = 'collapse-horizontal'; + const WIDTH = 'width'; + const HEIGHT = 'height'; + const SELECTOR_ACTIVES = '.collapse.show, .collapse.collapsing'; + const SELECTOR_DATA_TOGGLE$4 = '[data-bs-toggle="collapse"]'; + const Default$a = { + parent: null, + toggle: true + }; + const DefaultType$a = { + parent: '(null|element)', + toggle: 'boolean' + }; + + /** + * Class definition + */ + + class Collapse extends BaseComponent { + constructor(element, config) { + super(element, config); + this._isTransitioning = false; + this._triggerArray = []; + const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE$4); + for (const elem of toggleList) { + const selector = SelectorEngine.getSelectorFromElement(elem); + const filterElement = SelectorEngine.find(selector).filter(foundElement => foundElement === this._element); + if (selector !== null && filterElement.length) { + this._triggerArray.push(elem); + } + } + this._initializeChildren(); + if (!this._config.parent) { + this._addAriaAndCollapsedClass(this._triggerArray, this._isShown()); + } + if (this._config.toggle) { + this.toggle(); + } + } + + // Getters + static get Default() { + return Default$a; + } + static get DefaultType() { + return DefaultType$a; + } + static get NAME() { + return NAME$b; + } + + // Public + toggle() { + if (this._isShown()) { + this.hide(); + } else { + this.show(); + } + } + show() { + if (this._isTransitioning || this._isShown()) { + return; + } + let activeChildren = []; + + // find active children + if (this._config.parent) { + activeChildren = this._getFirstLevelChildren(SELECTOR_ACTIVES).filter(element => element !== this._element).map(element => Collapse.getOrCreateInstance(element, { + toggle: false + })); + } + if (activeChildren.length && activeChildren[0]._isTransitioning) { + return; + } + const startEvent = EventHandler.trigger(this._element, EVENT_SHOW$6); + if (startEvent.defaultPrevented) { + return; + } + for (const activeInstance of activeChildren) { + activeInstance.hide(); + } + const dimension = this._getDimension(); + this._element.classList.remove(CLASS_NAME_COLLAPSE); + this._element.classList.add(CLASS_NAME_COLLAPSING); + this._element.style[dimension] = 0; + this._addAriaAndCollapsedClass(this._triggerArray, true); + this._isTransitioning = true; + const complete = () => { + this._isTransitioning = false; + this._element.classList.remove(CLASS_NAME_COLLAPSING); + this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW$7); + this._element.style[dimension] = ''; + EventHandler.trigger(this._element, EVENT_SHOWN$6); + }; + const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1); + const scrollSize = `scroll${capitalizedDimension}`; + this._queueCallback(complete, this._element, true); + this._element.style[dimension] = `${this._element[scrollSize]}px`; + } + hide() { + if (this._isTransitioning || !this._isShown()) { + return; + } + const startEvent = EventHandler.trigger(this._element, EVENT_HIDE$6); + if (startEvent.defaultPrevented) { + return; + } + const dimension = this._getDimension(); + this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`; + reflow(this._element); + this._element.classList.add(CLASS_NAME_COLLAPSING); + this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW$7); + for (const trigger of this._triggerArray) { + const element = SelectorEngine.getElementFromSelector(trigger); + if (element && !this._isShown(element)) { + this._addAriaAndCollapsedClass([trigger], false); + } + } + this._isTransitioning = true; + const complete = () => { + this._isTransitioning = false; + this._element.classList.remove(CLASS_NAME_COLLAPSING); + this._element.classList.add(CLASS_NAME_COLLAPSE); + EventHandler.trigger(this._element, EVENT_HIDDEN$6); + }; + this._element.style[dimension] = ''; + this._queueCallback(complete, this._element, true); + } + _isShown(element = this._element) { + return element.classList.contains(CLASS_NAME_SHOW$7); + } + + // Private + _configAfterMerge(config) { + config.toggle = Boolean(config.toggle); // Coerce string values + config.parent = getElement(config.parent); + return config; + } + _getDimension() { + return this._element.classList.contains(CLASS_NAME_HORIZONTAL) ? WIDTH : HEIGHT; + } + _initializeChildren() { + if (!this._config.parent) { + return; + } + const children = this._getFirstLevelChildren(SELECTOR_DATA_TOGGLE$4); + for (const element of children) { + const selected = SelectorEngine.getElementFromSelector(element); + if (selected) { + this._addAriaAndCollapsedClass([element], this._isShown(selected)); + } + } + } + _getFirstLevelChildren(selector) { + const children = SelectorEngine.find(CLASS_NAME_DEEPER_CHILDREN, this._config.parent); + // remove children if greater depth + return SelectorEngine.find(selector, this._config.parent).filter(element => !children.includes(element)); + } + _addAriaAndCollapsedClass(triggerArray, isOpen) { + if (!triggerArray.length) { + return; + } + for (const element of triggerArray) { + element.classList.toggle(CLASS_NAME_COLLAPSED, !isOpen); + element.setAttribute('aria-expanded', isOpen); + } + } + + // Static + static jQueryInterface(config) { + const _config = {}; + if (typeof config === 'string' && /show|hide/.test(config)) { + _config.toggle = false; + } + return this.each(function () { + const data = Collapse.getOrCreateInstance(this, _config); + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError(`No method named "${config}"`); + } + data[config](); + } + }); + } + } + + /** + * Data API implementation + */ + + EventHandler.on(document, EVENT_CLICK_DATA_API$4, SELECTOR_DATA_TOGGLE$4, function (event) { + // preventDefault only for elements (which change the URL) not inside the collapsible element + if (event.target.tagName === 'A' || event.delegateTarget && event.delegateTarget.tagName === 'A') { + event.preventDefault(); + } + for (const element of SelectorEngine.getMultipleElementsFromSelector(this)) { + Collapse.getOrCreateInstance(element, { + toggle: false + }).toggle(); + } + }); + + /** + * jQuery + */ + + defineJQueryPlugin(Collapse); + + var top = 'top'; + var bottom = 'bottom'; + var right = 'right'; + var left = 'left'; + var auto = 'auto'; + var basePlacements = [top, bottom, right, left]; + var start = 'start'; + var end = 'end'; + var clippingParents = 'clippingParents'; + var viewport = 'viewport'; + var popper = 'popper'; + var reference = 'reference'; + var variationPlacements = /*#__PURE__*/basePlacements.reduce(function (acc, placement) { + return acc.concat([placement + "-" + start, placement + "-" + end]); + }, []); + var placements = /*#__PURE__*/[].concat(basePlacements, [auto]).reduce(function (acc, placement) { + return acc.concat([placement, placement + "-" + start, placement + "-" + end]); + }, []); // modifiers that need to read the DOM + + var beforeRead = 'beforeRead'; + var read = 'read'; + var afterRead = 'afterRead'; // pure-logic modifiers + + var beforeMain = 'beforeMain'; + var main = 'main'; + var afterMain = 'afterMain'; // modifier with the purpose to write to the DOM (or write into a framework state) + + var beforeWrite = 'beforeWrite'; + var write = 'write'; + var afterWrite = 'afterWrite'; + var modifierPhases = [beforeRead, read, afterRead, beforeMain, main, afterMain, beforeWrite, write, afterWrite]; + + function getNodeName(element) { + return element ? (element.nodeName || '').toLowerCase() : null; + } + + function getWindow(node) { + if (node == null) { + return window; + } + + if (node.toString() !== '[object Window]') { + var ownerDocument = node.ownerDocument; + return ownerDocument ? ownerDocument.defaultView || window : window; + } + + return node; + } + + function isElement(node) { + var OwnElement = getWindow(node).Element; + return node instanceof OwnElement || node instanceof Element; + } + + function isHTMLElement(node) { + var OwnElement = getWindow(node).HTMLElement; + return node instanceof OwnElement || node instanceof HTMLElement; + } + + function isShadowRoot(node) { + // IE 11 has no ShadowRoot + if (typeof ShadowRoot === 'undefined') { + return false; + } + + var OwnElement = getWindow(node).ShadowRoot; + return node instanceof OwnElement || node instanceof ShadowRoot; + } + + // and applies them to the HTMLElements such as popper and arrow + + function applyStyles(_ref) { + var state = _ref.state; + Object.keys(state.elements).forEach(function (name) { + var style = state.styles[name] || {}; + var attributes = state.attributes[name] || {}; + var element = state.elements[name]; // arrow is optional + virtual elements + + if (!isHTMLElement(element) || !getNodeName(element)) { + return; + } // Flow doesn't support to extend this property, but it's the most + // effective way to apply styles to an HTMLElement + // $FlowFixMe[cannot-write] + + + Object.assign(element.style, style); + Object.keys(attributes).forEach(function (name) { + var value = attributes[name]; + + if (value === false) { + element.removeAttribute(name); + } else { + element.setAttribute(name, value === true ? '' : value); + } + }); + }); + } + + function effect$2(_ref2) { + var state = _ref2.state; + var initialStyles = { + popper: { + position: state.options.strategy, + left: '0', + top: '0', + margin: '0' + }, + arrow: { + position: 'absolute' + }, + reference: {} + }; + Object.assign(state.elements.popper.style, initialStyles.popper); + state.styles = initialStyles; + + if (state.elements.arrow) { + Object.assign(state.elements.arrow.style, initialStyles.arrow); + } + + return function () { + Object.keys(state.elements).forEach(function (name) { + var element = state.elements[name]; + var attributes = state.attributes[name] || {}; + var styleProperties = Object.keys(state.styles.hasOwnProperty(name) ? state.styles[name] : initialStyles[name]); // Set all values to an empty string to unset them + + var style = styleProperties.reduce(function (style, property) { + style[property] = ''; + return style; + }, {}); // arrow is optional + virtual elements + + if (!isHTMLElement(element) || !getNodeName(element)) { + return; + } + + Object.assign(element.style, style); + Object.keys(attributes).forEach(function (attribute) { + element.removeAttribute(attribute); + }); + }); + }; + } // eslint-disable-next-line import/no-unused-modules + + + const applyStyles$1 = { + name: 'applyStyles', + enabled: true, + phase: 'write', + fn: applyStyles, + effect: effect$2, + requires: ['computeStyles'] + }; + + function getBasePlacement(placement) { + return placement.split('-')[0]; + } + + var max = Math.max; + var min = Math.min; + var round = Math.round; + + function getUAString() { + var uaData = navigator.userAgentData; + + if (uaData != null && uaData.brands && Array.isArray(uaData.brands)) { + return uaData.brands.map(function (item) { + return item.brand + "/" + item.version; + }).join(' '); + } + + return navigator.userAgent; + } + + function isLayoutViewport() { + return !/^((?!chrome|android).)*safari/i.test(getUAString()); + } + + function getBoundingClientRect(element, includeScale, isFixedStrategy) { + if (includeScale === void 0) { + includeScale = false; + } + + if (isFixedStrategy === void 0) { + isFixedStrategy = false; + } + + var clientRect = element.getBoundingClientRect(); + var scaleX = 1; + var scaleY = 1; + + if (includeScale && isHTMLElement(element)) { + scaleX = element.offsetWidth > 0 ? round(clientRect.width) / element.offsetWidth || 1 : 1; + scaleY = element.offsetHeight > 0 ? round(clientRect.height) / element.offsetHeight || 1 : 1; + } + + var _ref = isElement(element) ? getWindow(element) : window, + visualViewport = _ref.visualViewport; + + var addVisualOffsets = !isLayoutViewport() && isFixedStrategy; + var x = (clientRect.left + (addVisualOffsets && visualViewport ? visualViewport.offsetLeft : 0)) / scaleX; + var y = (clientRect.top + (addVisualOffsets && visualViewport ? visualViewport.offsetTop : 0)) / scaleY; + var width = clientRect.width / scaleX; + var height = clientRect.height / scaleY; + return { + width: width, + height: height, + top: y, + right: x + width, + bottom: y + height, + left: x, + x: x, + y: y + }; + } + + // means it doesn't take into account transforms. + + function getLayoutRect(element) { + var clientRect = getBoundingClientRect(element); // Use the clientRect sizes if it's not been transformed. + // Fixes https://github.com/popperjs/popper-core/issues/1223 + + var width = element.offsetWidth; + var height = element.offsetHeight; + + if (Math.abs(clientRect.width - width) <= 1) { + width = clientRect.width; + } + + if (Math.abs(clientRect.height - height) <= 1) { + height = clientRect.height; + } + + return { + x: element.offsetLeft, + y: element.offsetTop, + width: width, + height: height + }; + } + + function contains(parent, child) { + var rootNode = child.getRootNode && child.getRootNode(); // First, attempt with faster native method + + if (parent.contains(child)) { + return true; + } // then fallback to custom implementation with Shadow DOM support + else if (rootNode && isShadowRoot(rootNode)) { + var next = child; + + do { + if (next && parent.isSameNode(next)) { + return true; + } // $FlowFixMe[prop-missing]: need a better way to handle this... + + + next = next.parentNode || next.host; + } while (next); + } // Give up, the result is false + + + return false; + } + + function getComputedStyle$1(element) { + return getWindow(element).getComputedStyle(element); + } + + function isTableElement(element) { + return ['table', 'td', 'th'].indexOf(getNodeName(element)) >= 0; + } + + function getDocumentElement(element) { + // $FlowFixMe[incompatible-return]: assume body is always available + return ((isElement(element) ? element.ownerDocument : // $FlowFixMe[prop-missing] + element.document) || window.document).documentElement; + } + + function getParentNode(element) { + if (getNodeName(element) === 'html') { + return element; + } + + return (// this is a quicker (but less type safe) way to save quite some bytes from the bundle + // $FlowFixMe[incompatible-return] + // $FlowFixMe[prop-missing] + element.assignedSlot || // step into the shadow DOM of the parent of a slotted node + element.parentNode || ( // DOM Element detected + isShadowRoot(element) ? element.host : null) || // ShadowRoot detected + // $FlowFixMe[incompatible-call]: HTMLElement is a Node + getDocumentElement(element) // fallback + + ); + } + + function getTrueOffsetParent(element) { + if (!isHTMLElement(element) || // https://github.com/popperjs/popper-core/issues/837 + getComputedStyle$1(element).position === 'fixed') { + return null; + } + + return element.offsetParent; + } // `.offsetParent` reports `null` for fixed elements, while absolute elements + // return the containing block + + + function getContainingBlock(element) { + var isFirefox = /firefox/i.test(getUAString()); + var isIE = /Trident/i.test(getUAString()); + + if (isIE && isHTMLElement(element)) { + // In IE 9, 10 and 11 fixed elements containing block is always established by the viewport + var elementCss = getComputedStyle$1(element); + + if (elementCss.position === 'fixed') { + return null; + } + } + + var currentNode = getParentNode(element); + + if (isShadowRoot(currentNode)) { + currentNode = currentNode.host; + } + + while (isHTMLElement(currentNode) && ['html', 'body'].indexOf(getNodeName(currentNode)) < 0) { + var css = getComputedStyle$1(currentNode); // This is non-exhaustive but covers the most common CSS properties that + // create a containing block. + // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block + + if (css.transform !== 'none' || css.perspective !== 'none' || css.contain === 'paint' || ['transform', 'perspective'].indexOf(css.willChange) !== -1 || isFirefox && css.willChange === 'filter' || isFirefox && css.filter && css.filter !== 'none') { + return currentNode; + } else { + currentNode = currentNode.parentNode; + } + } + + return null; + } // Gets the closest ancestor positioned element. Handles some edge cases, + // such as table ancestors and cross browser bugs. + + + function getOffsetParent(element) { + var window = getWindow(element); + var offsetParent = getTrueOffsetParent(element); + + while (offsetParent && isTableElement(offsetParent) && getComputedStyle$1(offsetParent).position === 'static') { + offsetParent = getTrueOffsetParent(offsetParent); + } + + if (offsetParent && (getNodeName(offsetParent) === 'html' || getNodeName(offsetParent) === 'body' && getComputedStyle$1(offsetParent).position === 'static')) { + return window; + } + + return offsetParent || getContainingBlock(element) || window; + } + + function getMainAxisFromPlacement(placement) { + return ['top', 'bottom'].indexOf(placement) >= 0 ? 'x' : 'y'; + } + + function within(min$1, value, max$1) { + return max(min$1, min(value, max$1)); + } + function withinMaxClamp(min, value, max) { + var v = within(min, value, max); + return v > max ? max : v; + } + + function getFreshSideObject() { + return { + top: 0, + right: 0, + bottom: 0, + left: 0 + }; + } + + function mergePaddingObject(paddingObject) { + return Object.assign({}, getFreshSideObject(), paddingObject); + } + + function expandToHashMap(value, keys) { + return keys.reduce(function (hashMap, key) { + hashMap[key] = value; + return hashMap; + }, {}); + } + + var toPaddingObject = function toPaddingObject(padding, state) { + padding = typeof padding === 'function' ? padding(Object.assign({}, state.rects, { + placement: state.placement + })) : padding; + return mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements)); + }; + + function arrow(_ref) { + var _state$modifiersData$; + + var state = _ref.state, + name = _ref.name, + options = _ref.options; + var arrowElement = state.elements.arrow; + var popperOffsets = state.modifiersData.popperOffsets; + var basePlacement = getBasePlacement(state.placement); + var axis = getMainAxisFromPlacement(basePlacement); + var isVertical = [left, right].indexOf(basePlacement) >= 0; + var len = isVertical ? 'height' : 'width'; + + if (!arrowElement || !popperOffsets) { + return; + } + + var paddingObject = toPaddingObject(options.padding, state); + var arrowRect = getLayoutRect(arrowElement); + var minProp = axis === 'y' ? top : left; + var maxProp = axis === 'y' ? bottom : right; + var endDiff = state.rects.reference[len] + state.rects.reference[axis] - popperOffsets[axis] - state.rects.popper[len]; + var startDiff = popperOffsets[axis] - state.rects.reference[axis]; + var arrowOffsetParent = getOffsetParent(arrowElement); + var clientSize = arrowOffsetParent ? axis === 'y' ? arrowOffsetParent.clientHeight || 0 : arrowOffsetParent.clientWidth || 0 : 0; + var centerToReference = endDiff / 2 - startDiff / 2; // Make sure the arrow doesn't overflow the popper if the center point is + // outside of the popper bounds + + var min = paddingObject[minProp]; + var max = clientSize - arrowRect[len] - paddingObject[maxProp]; + var center = clientSize / 2 - arrowRect[len] / 2 + centerToReference; + var offset = within(min, center, max); // Prevents breaking syntax highlighting... + + var axisProp = axis; + state.modifiersData[name] = (_state$modifiersData$ = {}, _state$modifiersData$[axisProp] = offset, _state$modifiersData$.centerOffset = offset - center, _state$modifiersData$); + } + + function effect$1(_ref2) { + var state = _ref2.state, + options = _ref2.options; + var _options$element = options.element, + arrowElement = _options$element === void 0 ? '[data-popper-arrow]' : _options$element; + + if (arrowElement == null) { + return; + } // CSS selector + + + if (typeof arrowElement === 'string') { + arrowElement = state.elements.popper.querySelector(arrowElement); + + if (!arrowElement) { + return; + } + } + + if (!contains(state.elements.popper, arrowElement)) { + return; + } + + state.elements.arrow = arrowElement; + } // eslint-disable-next-line import/no-unused-modules + + + const arrow$1 = { + name: 'arrow', + enabled: true, + phase: 'main', + fn: arrow, + effect: effect$1, + requires: ['popperOffsets'], + requiresIfExists: ['preventOverflow'] + }; + + function getVariation(placement) { + return placement.split('-')[1]; + } + + var unsetSides = { + top: 'auto', + right: 'auto', + bottom: 'auto', + left: 'auto' + }; // Round the offsets to the nearest suitable subpixel based on the DPR. + // Zooming can change the DPR, but it seems to report a value that will + // cleanly divide the values into the appropriate subpixels. + + function roundOffsetsByDPR(_ref, win) { + var x = _ref.x, + y = _ref.y; + var dpr = win.devicePixelRatio || 1; + return { + x: round(x * dpr) / dpr || 0, + y: round(y * dpr) / dpr || 0 + }; + } + + function mapToStyles(_ref2) { + var _Object$assign2; + + var popper = _ref2.popper, + popperRect = _ref2.popperRect, + placement = _ref2.placement, + variation = _ref2.variation, + offsets = _ref2.offsets, + position = _ref2.position, + gpuAcceleration = _ref2.gpuAcceleration, + adaptive = _ref2.adaptive, + roundOffsets = _ref2.roundOffsets, + isFixed = _ref2.isFixed; + var _offsets$x = offsets.x, + x = _offsets$x === void 0 ? 0 : _offsets$x, + _offsets$y = offsets.y, + y = _offsets$y === void 0 ? 0 : _offsets$y; + + var _ref3 = typeof roundOffsets === 'function' ? roundOffsets({ + x: x, + y: y + }) : { + x: x, + y: y + }; + + x = _ref3.x; + y = _ref3.y; + var hasX = offsets.hasOwnProperty('x'); + var hasY = offsets.hasOwnProperty('y'); + var sideX = left; + var sideY = top; + var win = window; + + if (adaptive) { + var offsetParent = getOffsetParent(popper); + var heightProp = 'clientHeight'; + var widthProp = 'clientWidth'; + + if (offsetParent === getWindow(popper)) { + offsetParent = getDocumentElement(popper); + + if (getComputedStyle$1(offsetParent).position !== 'static' && position === 'absolute') { + heightProp = 'scrollHeight'; + widthProp = 'scrollWidth'; + } + } // $FlowFixMe[incompatible-cast]: force type refinement, we compare offsetParent with window above, but Flow doesn't detect it + + + offsetParent = offsetParent; + + if (placement === top || (placement === left || placement === right) && variation === end) { + sideY = bottom; + var offsetY = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.height : // $FlowFixMe[prop-missing] + offsetParent[heightProp]; + y -= offsetY - popperRect.height; + y *= gpuAcceleration ? 1 : -1; + } + + if (placement === left || (placement === top || placement === bottom) && variation === end) { + sideX = right; + var offsetX = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.width : // $FlowFixMe[prop-missing] + offsetParent[widthProp]; + x -= offsetX - popperRect.width; + x *= gpuAcceleration ? 1 : -1; + } + } + + var commonStyles = Object.assign({ + position: position + }, adaptive && unsetSides); + + var _ref4 = roundOffsets === true ? roundOffsetsByDPR({ + x: x, + y: y + }, getWindow(popper)) : { + x: x, + y: y + }; + + x = _ref4.x; + y = _ref4.y; + + if (gpuAcceleration) { + var _Object$assign; + + return Object.assign({}, commonStyles, (_Object$assign = {}, _Object$assign[sideY] = hasY ? '0' : '', _Object$assign[sideX] = hasX ? '0' : '', _Object$assign.transform = (win.devicePixelRatio || 1) <= 1 ? "translate(" + x + "px, " + y + "px)" : "translate3d(" + x + "px, " + y + "px, 0)", _Object$assign)); + } + + return Object.assign({}, commonStyles, (_Object$assign2 = {}, _Object$assign2[sideY] = hasY ? y + "px" : '', _Object$assign2[sideX] = hasX ? x + "px" : '', _Object$assign2.transform = '', _Object$assign2)); + } + + function computeStyles(_ref5) { + var state = _ref5.state, + options = _ref5.options; + var _options$gpuAccelerat = options.gpuAcceleration, + gpuAcceleration = _options$gpuAccelerat === void 0 ? true : _options$gpuAccelerat, + _options$adaptive = options.adaptive, + adaptive = _options$adaptive === void 0 ? true : _options$adaptive, + _options$roundOffsets = options.roundOffsets, + roundOffsets = _options$roundOffsets === void 0 ? true : _options$roundOffsets; + var commonStyles = { + placement: getBasePlacement(state.placement), + variation: getVariation(state.placement), + popper: state.elements.popper, + popperRect: state.rects.popper, + gpuAcceleration: gpuAcceleration, + isFixed: state.options.strategy === 'fixed' + }; + + if (state.modifiersData.popperOffsets != null) { + state.styles.popper = Object.assign({}, state.styles.popper, mapToStyles(Object.assign({}, commonStyles, { + offsets: state.modifiersData.popperOffsets, + position: state.options.strategy, + adaptive: adaptive, + roundOffsets: roundOffsets + }))); + } + + if (state.modifiersData.arrow != null) { + state.styles.arrow = Object.assign({}, state.styles.arrow, mapToStyles(Object.assign({}, commonStyles, { + offsets: state.modifiersData.arrow, + position: 'absolute', + adaptive: false, + roundOffsets: roundOffsets + }))); + } + + state.attributes.popper = Object.assign({}, state.attributes.popper, { + 'data-popper-placement': state.placement + }); + } // eslint-disable-next-line import/no-unused-modules + + + const computeStyles$1 = { + name: 'computeStyles', + enabled: true, + phase: 'beforeWrite', + fn: computeStyles, + data: {} + }; + + var passive = { + passive: true + }; + + function effect(_ref) { + var state = _ref.state, + instance = _ref.instance, + options = _ref.options; + var _options$scroll = options.scroll, + scroll = _options$scroll === void 0 ? true : _options$scroll, + _options$resize = options.resize, + resize = _options$resize === void 0 ? true : _options$resize; + var window = getWindow(state.elements.popper); + var scrollParents = [].concat(state.scrollParents.reference, state.scrollParents.popper); + + if (scroll) { + scrollParents.forEach(function (scrollParent) { + scrollParent.addEventListener('scroll', instance.update, passive); + }); + } + + if (resize) { + window.addEventListener('resize', instance.update, passive); + } + + return function () { + if (scroll) { + scrollParents.forEach(function (scrollParent) { + scrollParent.removeEventListener('scroll', instance.update, passive); + }); + } + + if (resize) { + window.removeEventListener('resize', instance.update, passive); + } + }; + } // eslint-disable-next-line import/no-unused-modules + + + const eventListeners = { + name: 'eventListeners', + enabled: true, + phase: 'write', + fn: function fn() {}, + effect: effect, + data: {} + }; + + var hash$1 = { + left: 'right', + right: 'left', + bottom: 'top', + top: 'bottom' + }; + function getOppositePlacement(placement) { + return placement.replace(/left|right|bottom|top/g, function (matched) { + return hash$1[matched]; + }); + } + + var hash = { + start: 'end', + end: 'start' + }; + function getOppositeVariationPlacement(placement) { + return placement.replace(/start|end/g, function (matched) { + return hash[matched]; + }); + } + + function getWindowScroll(node) { + var win = getWindow(node); + var scrollLeft = win.pageXOffset; + var scrollTop = win.pageYOffset; + return { + scrollLeft: scrollLeft, + scrollTop: scrollTop + }; + } + + function getWindowScrollBarX(element) { + // If has a CSS width greater than the viewport, then this will be + // incorrect for RTL. + // Popper 1 is broken in this case and never had a bug report so let's assume + // it's not an issue. I don't think anyone ever specifies width on + // anyway. + // Browsers where the left scrollbar doesn't cause an issue report `0` for + // this (e.g. Edge 2019, IE11, Safari) + return getBoundingClientRect(getDocumentElement(element)).left + getWindowScroll(element).scrollLeft; + } + + function getViewportRect(element, strategy) { + var win = getWindow(element); + var html = getDocumentElement(element); + var visualViewport = win.visualViewport; + var width = html.clientWidth; + var height = html.clientHeight; + var x = 0; + var y = 0; + + if (visualViewport) { + width = visualViewport.width; + height = visualViewport.height; + var layoutViewport = isLayoutViewport(); + + if (layoutViewport || !layoutViewport && strategy === 'fixed') { + x = visualViewport.offsetLeft; + y = visualViewport.offsetTop; + } + } + + return { + width: width, + height: height, + x: x + getWindowScrollBarX(element), + y: y + }; + } + + // of the `` and `` rect bounds if horizontally scrollable + + function getDocumentRect(element) { + var _element$ownerDocumen; + + var html = getDocumentElement(element); + var winScroll = getWindowScroll(element); + var body = (_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body; + var width = max(html.scrollWidth, html.clientWidth, body ? body.scrollWidth : 0, body ? body.clientWidth : 0); + var height = max(html.scrollHeight, html.clientHeight, body ? body.scrollHeight : 0, body ? body.clientHeight : 0); + var x = -winScroll.scrollLeft + getWindowScrollBarX(element); + var y = -winScroll.scrollTop; + + if (getComputedStyle$1(body || html).direction === 'rtl') { + x += max(html.clientWidth, body ? body.clientWidth : 0) - width; + } + + return { + width: width, + height: height, + x: x, + y: y + }; + } + + function isScrollParent(element) { + // Firefox wants us to check `-x` and `-y` variations as well + var _getComputedStyle = getComputedStyle$1(element), + overflow = _getComputedStyle.overflow, + overflowX = _getComputedStyle.overflowX, + overflowY = _getComputedStyle.overflowY; + + return /auto|scroll|overlay|hidden/.test(overflow + overflowY + overflowX); + } + + function getScrollParent(node) { + if (['html', 'body', '#document'].indexOf(getNodeName(node)) >= 0) { + // $FlowFixMe[incompatible-return]: assume body is always available + return node.ownerDocument.body; + } + + if (isHTMLElement(node) && isScrollParent(node)) { + return node; + } + + return getScrollParent(getParentNode(node)); + } + + /* + given a DOM element, return the list of all scroll parents, up the list of ancesors + until we get to the top window object. This list is what we attach scroll listeners + to, because if any of these parent elements scroll, we'll need to re-calculate the + reference element's position. + */ + + function listScrollParents(element, list) { + var _element$ownerDocumen; + + if (list === void 0) { + list = []; + } + + var scrollParent = getScrollParent(element); + var isBody = scrollParent === ((_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body); + var win = getWindow(scrollParent); + var target = isBody ? [win].concat(win.visualViewport || [], isScrollParent(scrollParent) ? scrollParent : []) : scrollParent; + var updatedList = list.concat(target); + return isBody ? updatedList : // $FlowFixMe[incompatible-call]: isBody tells us target will be an HTMLElement here + updatedList.concat(listScrollParents(getParentNode(target))); + } + + function rectToClientRect(rect) { + return Object.assign({}, rect, { + left: rect.x, + top: rect.y, + right: rect.x + rect.width, + bottom: rect.y + rect.height + }); + } + + function getInnerBoundingClientRect(element, strategy) { + var rect = getBoundingClientRect(element, false, strategy === 'fixed'); + rect.top = rect.top + element.clientTop; + rect.left = rect.left + element.clientLeft; + rect.bottom = rect.top + element.clientHeight; + rect.right = rect.left + element.clientWidth; + rect.width = element.clientWidth; + rect.height = element.clientHeight; + rect.x = rect.left; + rect.y = rect.top; + return rect; + } + + function getClientRectFromMixedType(element, clippingParent, strategy) { + return clippingParent === viewport ? rectToClientRect(getViewportRect(element, strategy)) : isElement(clippingParent) ? getInnerBoundingClientRect(clippingParent, strategy) : rectToClientRect(getDocumentRect(getDocumentElement(element))); + } // A "clipping parent" is an overflowable container with the characteristic of + // clipping (or hiding) overflowing elements with a position different from + // `initial` + + + function getClippingParents(element) { + var clippingParents = listScrollParents(getParentNode(element)); + var canEscapeClipping = ['absolute', 'fixed'].indexOf(getComputedStyle$1(element).position) >= 0; + var clipperElement = canEscapeClipping && isHTMLElement(element) ? getOffsetParent(element) : element; + + if (!isElement(clipperElement)) { + return []; + } // $FlowFixMe[incompatible-return]: https://github.com/facebook/flow/issues/1414 + + + return clippingParents.filter(function (clippingParent) { + return isElement(clippingParent) && contains(clippingParent, clipperElement) && getNodeName(clippingParent) !== 'body'; + }); + } // Gets the maximum area that the element is visible in due to any number of + // clipping parents + + + function getClippingRect(element, boundary, rootBoundary, strategy) { + var mainClippingParents = boundary === 'clippingParents' ? getClippingParents(element) : [].concat(boundary); + var clippingParents = [].concat(mainClippingParents, [rootBoundary]); + var firstClippingParent = clippingParents[0]; + var clippingRect = clippingParents.reduce(function (accRect, clippingParent) { + var rect = getClientRectFromMixedType(element, clippingParent, strategy); + accRect.top = max(rect.top, accRect.top); + accRect.right = min(rect.right, accRect.right); + accRect.bottom = min(rect.bottom, accRect.bottom); + accRect.left = max(rect.left, accRect.left); + return accRect; + }, getClientRectFromMixedType(element, firstClippingParent, strategy)); + clippingRect.width = clippingRect.right - clippingRect.left; + clippingRect.height = clippingRect.bottom - clippingRect.top; + clippingRect.x = clippingRect.left; + clippingRect.y = clippingRect.top; + return clippingRect; + } + + function computeOffsets(_ref) { + var reference = _ref.reference, + element = _ref.element, + placement = _ref.placement; + var basePlacement = placement ? getBasePlacement(placement) : null; + var variation = placement ? getVariation(placement) : null; + var commonX = reference.x + reference.width / 2 - element.width / 2; + var commonY = reference.y + reference.height / 2 - element.height / 2; + var offsets; + + switch (basePlacement) { + case top: + offsets = { + x: commonX, + y: reference.y - element.height + }; + break; + + case bottom: + offsets = { + x: commonX, + y: reference.y + reference.height + }; + break; + + case right: + offsets = { + x: reference.x + reference.width, + y: commonY + }; + break; + + case left: + offsets = { + x: reference.x - element.width, + y: commonY + }; + break; + + default: + offsets = { + x: reference.x, + y: reference.y + }; + } + + var mainAxis = basePlacement ? getMainAxisFromPlacement(basePlacement) : null; + + if (mainAxis != null) { + var len = mainAxis === 'y' ? 'height' : 'width'; + + switch (variation) { + case start: + offsets[mainAxis] = offsets[mainAxis] - (reference[len] / 2 - element[len] / 2); + break; + + case end: + offsets[mainAxis] = offsets[mainAxis] + (reference[len] / 2 - element[len] / 2); + break; + } + } + + return offsets; + } + + function detectOverflow(state, options) { + if (options === void 0) { + options = {}; + } + + var _options = options, + _options$placement = _options.placement, + placement = _options$placement === void 0 ? state.placement : _options$placement, + _options$strategy = _options.strategy, + strategy = _options$strategy === void 0 ? state.strategy : _options$strategy, + _options$boundary = _options.boundary, + boundary = _options$boundary === void 0 ? clippingParents : _options$boundary, + _options$rootBoundary = _options.rootBoundary, + rootBoundary = _options$rootBoundary === void 0 ? viewport : _options$rootBoundary, + _options$elementConte = _options.elementContext, + elementContext = _options$elementConte === void 0 ? popper : _options$elementConte, + _options$altBoundary = _options.altBoundary, + altBoundary = _options$altBoundary === void 0 ? false : _options$altBoundary, + _options$padding = _options.padding, + padding = _options$padding === void 0 ? 0 : _options$padding; + var paddingObject = mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements)); + var altContext = elementContext === popper ? reference : popper; + var popperRect = state.rects.popper; + var element = state.elements[altBoundary ? altContext : elementContext]; + var clippingClientRect = getClippingRect(isElement(element) ? element : element.contextElement || getDocumentElement(state.elements.popper), boundary, rootBoundary, strategy); + var referenceClientRect = getBoundingClientRect(state.elements.reference); + var popperOffsets = computeOffsets({ + reference: referenceClientRect, + element: popperRect, + strategy: 'absolute', + placement: placement + }); + var popperClientRect = rectToClientRect(Object.assign({}, popperRect, popperOffsets)); + var elementClientRect = elementContext === popper ? popperClientRect : referenceClientRect; // positive = overflowing the clipping rect + // 0 or negative = within the clipping rect + + var overflowOffsets = { + top: clippingClientRect.top - elementClientRect.top + paddingObject.top, + bottom: elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom, + left: clippingClientRect.left - elementClientRect.left + paddingObject.left, + right: elementClientRect.right - clippingClientRect.right + paddingObject.right + }; + var offsetData = state.modifiersData.offset; // Offsets can be applied only to the popper element + + if (elementContext === popper && offsetData) { + var offset = offsetData[placement]; + Object.keys(overflowOffsets).forEach(function (key) { + var multiply = [right, bottom].indexOf(key) >= 0 ? 1 : -1; + var axis = [top, bottom].indexOf(key) >= 0 ? 'y' : 'x'; + overflowOffsets[key] += offset[axis] * multiply; + }); + } + + return overflowOffsets; + } + + function computeAutoPlacement(state, options) { + if (options === void 0) { + options = {}; + } + + var _options = options, + placement = _options.placement, + boundary = _options.boundary, + rootBoundary = _options.rootBoundary, + padding = _options.padding, + flipVariations = _options.flipVariations, + _options$allowedAutoP = _options.allowedAutoPlacements, + allowedAutoPlacements = _options$allowedAutoP === void 0 ? placements : _options$allowedAutoP; + var variation = getVariation(placement); + var placements$1 = variation ? flipVariations ? variationPlacements : variationPlacements.filter(function (placement) { + return getVariation(placement) === variation; + }) : basePlacements; + var allowedPlacements = placements$1.filter(function (placement) { + return allowedAutoPlacements.indexOf(placement) >= 0; + }); + + if (allowedPlacements.length === 0) { + allowedPlacements = placements$1; + } // $FlowFixMe[incompatible-type]: Flow seems to have problems with two array unions... + + + var overflows = allowedPlacements.reduce(function (acc, placement) { + acc[placement] = detectOverflow(state, { + placement: placement, + boundary: boundary, + rootBoundary: rootBoundary, + padding: padding + })[getBasePlacement(placement)]; + return acc; + }, {}); + return Object.keys(overflows).sort(function (a, b) { + return overflows[a] - overflows[b]; + }); + } + + function getExpandedFallbackPlacements(placement) { + if (getBasePlacement(placement) === auto) { + return []; + } + + var oppositePlacement = getOppositePlacement(placement); + return [getOppositeVariationPlacement(placement), oppositePlacement, getOppositeVariationPlacement(oppositePlacement)]; + } + + function flip(_ref) { + var state = _ref.state, + options = _ref.options, + name = _ref.name; + + if (state.modifiersData[name]._skip) { + return; + } + + var _options$mainAxis = options.mainAxis, + checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis, + _options$altAxis = options.altAxis, + checkAltAxis = _options$altAxis === void 0 ? true : _options$altAxis, + specifiedFallbackPlacements = options.fallbackPlacements, + padding = options.padding, + boundary = options.boundary, + rootBoundary = options.rootBoundary, + altBoundary = options.altBoundary, + _options$flipVariatio = options.flipVariations, + flipVariations = _options$flipVariatio === void 0 ? true : _options$flipVariatio, + allowedAutoPlacements = options.allowedAutoPlacements; + var preferredPlacement = state.options.placement; + var basePlacement = getBasePlacement(preferredPlacement); + var isBasePlacement = basePlacement === preferredPlacement; + var fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipVariations ? [getOppositePlacement(preferredPlacement)] : getExpandedFallbackPlacements(preferredPlacement)); + var placements = [preferredPlacement].concat(fallbackPlacements).reduce(function (acc, placement) { + return acc.concat(getBasePlacement(placement) === auto ? computeAutoPlacement(state, { + placement: placement, + boundary: boundary, + rootBoundary: rootBoundary, + padding: padding, + flipVariations: flipVariations, + allowedAutoPlacements: allowedAutoPlacements + }) : placement); + }, []); + var referenceRect = state.rects.reference; + var popperRect = state.rects.popper; + var checksMap = new Map(); + var makeFallbackChecks = true; + var firstFittingPlacement = placements[0]; + + for (var i = 0; i < placements.length; i++) { + var placement = placements[i]; + + var _basePlacement = getBasePlacement(placement); + + var isStartVariation = getVariation(placement) === start; + var isVertical = [top, bottom].indexOf(_basePlacement) >= 0; + var len = isVertical ? 'width' : 'height'; + var overflow = detectOverflow(state, { + placement: placement, + boundary: boundary, + rootBoundary: rootBoundary, + altBoundary: altBoundary, + padding: padding + }); + var mainVariationSide = isVertical ? isStartVariation ? right : left : isStartVariation ? bottom : top; + + if (referenceRect[len] > popperRect[len]) { + mainVariationSide = getOppositePlacement(mainVariationSide); + } + + var altVariationSide = getOppositePlacement(mainVariationSide); + var checks = []; + + if (checkMainAxis) { + checks.push(overflow[_basePlacement] <= 0); + } + + if (checkAltAxis) { + checks.push(overflow[mainVariationSide] <= 0, overflow[altVariationSide] <= 0); + } + + if (checks.every(function (check) { + return check; + })) { + firstFittingPlacement = placement; + makeFallbackChecks = false; + break; + } + + checksMap.set(placement, checks); + } + + if (makeFallbackChecks) { + // `2` may be desired in some cases – research later + var numberOfChecks = flipVariations ? 3 : 1; + + var _loop = function _loop(_i) { + var fittingPlacement = placements.find(function (placement) { + var checks = checksMap.get(placement); + + if (checks) { + return checks.slice(0, _i).every(function (check) { + return check; + }); + } + }); + + if (fittingPlacement) { + firstFittingPlacement = fittingPlacement; + return "break"; + } + }; + + for (var _i = numberOfChecks; _i > 0; _i--) { + var _ret = _loop(_i); + + if (_ret === "break") break; + } + } + + if (state.placement !== firstFittingPlacement) { + state.modifiersData[name]._skip = true; + state.placement = firstFittingPlacement; + state.reset = true; + } + } // eslint-disable-next-line import/no-unused-modules + + + const flip$1 = { + name: 'flip', + enabled: true, + phase: 'main', + fn: flip, + requiresIfExists: ['offset'], + data: { + _skip: false + } + }; + + function getSideOffsets(overflow, rect, preventedOffsets) { + if (preventedOffsets === void 0) { + preventedOffsets = { + x: 0, + y: 0 + }; + } + + return { + top: overflow.top - rect.height - preventedOffsets.y, + right: overflow.right - rect.width + preventedOffsets.x, + bottom: overflow.bottom - rect.height + preventedOffsets.y, + left: overflow.left - rect.width - preventedOffsets.x + }; + } + + function isAnySideFullyClipped(overflow) { + return [top, right, bottom, left].some(function (side) { + return overflow[side] >= 0; + }); + } + + function hide(_ref) { + var state = _ref.state, + name = _ref.name; + var referenceRect = state.rects.reference; + var popperRect = state.rects.popper; + var preventedOffsets = state.modifiersData.preventOverflow; + var referenceOverflow = detectOverflow(state, { + elementContext: 'reference' + }); + var popperAltOverflow = detectOverflow(state, { + altBoundary: true + }); + var referenceClippingOffsets = getSideOffsets(referenceOverflow, referenceRect); + var popperEscapeOffsets = getSideOffsets(popperAltOverflow, popperRect, preventedOffsets); + var isReferenceHidden = isAnySideFullyClipped(referenceClippingOffsets); + var hasPopperEscaped = isAnySideFullyClipped(popperEscapeOffsets); + state.modifiersData[name] = { + referenceClippingOffsets: referenceClippingOffsets, + popperEscapeOffsets: popperEscapeOffsets, + isReferenceHidden: isReferenceHidden, + hasPopperEscaped: hasPopperEscaped + }; + state.attributes.popper = Object.assign({}, state.attributes.popper, { + 'data-popper-reference-hidden': isReferenceHidden, + 'data-popper-escaped': hasPopperEscaped + }); + } // eslint-disable-next-line import/no-unused-modules + + + const hide$1 = { + name: 'hide', + enabled: true, + phase: 'main', + requiresIfExists: ['preventOverflow'], + fn: hide + }; + + function distanceAndSkiddingToXY(placement, rects, offset) { + var basePlacement = getBasePlacement(placement); + var invertDistance = [left, top].indexOf(basePlacement) >= 0 ? -1 : 1; + + var _ref = typeof offset === 'function' ? offset(Object.assign({}, rects, { + placement: placement + })) : offset, + skidding = _ref[0], + distance = _ref[1]; + + skidding = skidding || 0; + distance = (distance || 0) * invertDistance; + return [left, right].indexOf(basePlacement) >= 0 ? { + x: distance, + y: skidding + } : { + x: skidding, + y: distance + }; + } + + function offset(_ref2) { + var state = _ref2.state, + options = _ref2.options, + name = _ref2.name; + var _options$offset = options.offset, + offset = _options$offset === void 0 ? [0, 0] : _options$offset; + var data = placements.reduce(function (acc, placement) { + acc[placement] = distanceAndSkiddingToXY(placement, state.rects, offset); + return acc; + }, {}); + var _data$state$placement = data[state.placement], + x = _data$state$placement.x, + y = _data$state$placement.y; + + if (state.modifiersData.popperOffsets != null) { + state.modifiersData.popperOffsets.x += x; + state.modifiersData.popperOffsets.y += y; + } + + state.modifiersData[name] = data; + } // eslint-disable-next-line import/no-unused-modules + + + const offset$1 = { + name: 'offset', + enabled: true, + phase: 'main', + requires: ['popperOffsets'], + fn: offset + }; + + function popperOffsets(_ref) { + var state = _ref.state, + name = _ref.name; + // Offsets are the actual position the popper needs to have to be + // properly positioned near its reference element + // This is the most basic placement, and will be adjusted by + // the modifiers in the next step + state.modifiersData[name] = computeOffsets({ + reference: state.rects.reference, + element: state.rects.popper, + strategy: 'absolute', + placement: state.placement + }); + } // eslint-disable-next-line import/no-unused-modules + + + const popperOffsets$1 = { + name: 'popperOffsets', + enabled: true, + phase: 'read', + fn: popperOffsets, + data: {} + }; + + function getAltAxis(axis) { + return axis === 'x' ? 'y' : 'x'; + } + + function preventOverflow(_ref) { + var state = _ref.state, + options = _ref.options, + name = _ref.name; + var _options$mainAxis = options.mainAxis, + checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis, + _options$altAxis = options.altAxis, + checkAltAxis = _options$altAxis === void 0 ? false : _options$altAxis, + boundary = options.boundary, + rootBoundary = options.rootBoundary, + altBoundary = options.altBoundary, + padding = options.padding, + _options$tether = options.tether, + tether = _options$tether === void 0 ? true : _options$tether, + _options$tetherOffset = options.tetherOffset, + tetherOffset = _options$tetherOffset === void 0 ? 0 : _options$tetherOffset; + var overflow = detectOverflow(state, { + boundary: boundary, + rootBoundary: rootBoundary, + padding: padding, + altBoundary: altBoundary + }); + var basePlacement = getBasePlacement(state.placement); + var variation = getVariation(state.placement); + var isBasePlacement = !variation; + var mainAxis = getMainAxisFromPlacement(basePlacement); + var altAxis = getAltAxis(mainAxis); + var popperOffsets = state.modifiersData.popperOffsets; + var referenceRect = state.rects.reference; + var popperRect = state.rects.popper; + var tetherOffsetValue = typeof tetherOffset === 'function' ? tetherOffset(Object.assign({}, state.rects, { + placement: state.placement + })) : tetherOffset; + var normalizedTetherOffsetValue = typeof tetherOffsetValue === 'number' ? { + mainAxis: tetherOffsetValue, + altAxis: tetherOffsetValue + } : Object.assign({ + mainAxis: 0, + altAxis: 0 + }, tetherOffsetValue); + var offsetModifierState = state.modifiersData.offset ? state.modifiersData.offset[state.placement] : null; + var data = { + x: 0, + y: 0 + }; + + if (!popperOffsets) { + return; + } + + if (checkMainAxis) { + var _offsetModifierState$; + + var mainSide = mainAxis === 'y' ? top : left; + var altSide = mainAxis === 'y' ? bottom : right; + var len = mainAxis === 'y' ? 'height' : 'width'; + var offset = popperOffsets[mainAxis]; + var min$1 = offset + overflow[mainSide]; + var max$1 = offset - overflow[altSide]; + var additive = tether ? -popperRect[len] / 2 : 0; + var minLen = variation === start ? referenceRect[len] : popperRect[len]; + var maxLen = variation === start ? -popperRect[len] : -referenceRect[len]; // We need to include the arrow in the calculation so the arrow doesn't go + // outside the reference bounds + + var arrowElement = state.elements.arrow; + var arrowRect = tether && arrowElement ? getLayoutRect(arrowElement) : { + width: 0, + height: 0 + }; + var arrowPaddingObject = state.modifiersData['arrow#persistent'] ? state.modifiersData['arrow#persistent'].padding : getFreshSideObject(); + var arrowPaddingMin = arrowPaddingObject[mainSide]; + var arrowPaddingMax = arrowPaddingObject[altSide]; // If the reference length is smaller than the arrow length, we don't want + // to include its full size in the calculation. If the reference is small + // and near the edge of a boundary, the popper can overflow even if the + // reference is not overflowing as well (e.g. virtual elements with no + // width or height) + + var arrowLen = within(0, referenceRect[len], arrowRect[len]); + var minOffset = isBasePlacement ? referenceRect[len] / 2 - additive - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis : minLen - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis; + var maxOffset = isBasePlacement ? -referenceRect[len] / 2 + additive + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis : maxLen + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis; + var arrowOffsetParent = state.elements.arrow && getOffsetParent(state.elements.arrow); + var clientOffset = arrowOffsetParent ? mainAxis === 'y' ? arrowOffsetParent.clientTop || 0 : arrowOffsetParent.clientLeft || 0 : 0; + var offsetModifierValue = (_offsetModifierState$ = offsetModifierState == null ? void 0 : offsetModifierState[mainAxis]) != null ? _offsetModifierState$ : 0; + var tetherMin = offset + minOffset - offsetModifierValue - clientOffset; + var tetherMax = offset + maxOffset - offsetModifierValue; + var preventedOffset = within(tether ? min(min$1, tetherMin) : min$1, offset, tether ? max(max$1, tetherMax) : max$1); + popperOffsets[mainAxis] = preventedOffset; + data[mainAxis] = preventedOffset - offset; + } + + if (checkAltAxis) { + var _offsetModifierState$2; + + var _mainSide = mainAxis === 'x' ? top : left; + + var _altSide = mainAxis === 'x' ? bottom : right; + + var _offset = popperOffsets[altAxis]; + + var _len = altAxis === 'y' ? 'height' : 'width'; + + var _min = _offset + overflow[_mainSide]; + + var _max = _offset - overflow[_altSide]; + + var isOriginSide = [top, left].indexOf(basePlacement) !== -1; + + var _offsetModifierValue = (_offsetModifierState$2 = offsetModifierState == null ? void 0 : offsetModifierState[altAxis]) != null ? _offsetModifierState$2 : 0; + + var _tetherMin = isOriginSide ? _min : _offset - referenceRect[_len] - popperRect[_len] - _offsetModifierValue + normalizedTetherOffsetValue.altAxis; + + var _tetherMax = isOriginSide ? _offset + referenceRect[_len] + popperRect[_len] - _offsetModifierValue - normalizedTetherOffsetValue.altAxis : _max; + + var _preventedOffset = tether && isOriginSide ? withinMaxClamp(_tetherMin, _offset, _tetherMax) : within(tether ? _tetherMin : _min, _offset, tether ? _tetherMax : _max); + + popperOffsets[altAxis] = _preventedOffset; + data[altAxis] = _preventedOffset - _offset; + } + + state.modifiersData[name] = data; + } // eslint-disable-next-line import/no-unused-modules + + + const preventOverflow$1 = { + name: 'preventOverflow', + enabled: true, + phase: 'main', + fn: preventOverflow, + requiresIfExists: ['offset'] + }; + + function getHTMLElementScroll(element) { + return { + scrollLeft: element.scrollLeft, + scrollTop: element.scrollTop + }; + } + + function getNodeScroll(node) { + if (node === getWindow(node) || !isHTMLElement(node)) { + return getWindowScroll(node); + } else { + return getHTMLElementScroll(node); + } + } + + function isElementScaled(element) { + var rect = element.getBoundingClientRect(); + var scaleX = round(rect.width) / element.offsetWidth || 1; + var scaleY = round(rect.height) / element.offsetHeight || 1; + return scaleX !== 1 || scaleY !== 1; + } // Returns the composite rect of an element relative to its offsetParent. + // Composite means it takes into account transforms as well as layout. + + + function getCompositeRect(elementOrVirtualElement, offsetParent, isFixed) { + if (isFixed === void 0) { + isFixed = false; + } + + var isOffsetParentAnElement = isHTMLElement(offsetParent); + var offsetParentIsScaled = isHTMLElement(offsetParent) && isElementScaled(offsetParent); + var documentElement = getDocumentElement(offsetParent); + var rect = getBoundingClientRect(elementOrVirtualElement, offsetParentIsScaled, isFixed); + var scroll = { + scrollLeft: 0, + scrollTop: 0 + }; + var offsets = { + x: 0, + y: 0 + }; + + if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) { + if (getNodeName(offsetParent) !== 'body' || // https://github.com/popperjs/popper-core/issues/1078 + isScrollParent(documentElement)) { + scroll = getNodeScroll(offsetParent); + } + + if (isHTMLElement(offsetParent)) { + offsets = getBoundingClientRect(offsetParent, true); + offsets.x += offsetParent.clientLeft; + offsets.y += offsetParent.clientTop; + } else if (documentElement) { + offsets.x = getWindowScrollBarX(documentElement); + } + } + + return { + x: rect.left + scroll.scrollLeft - offsets.x, + y: rect.top + scroll.scrollTop - offsets.y, + width: rect.width, + height: rect.height + }; + } + + function order(modifiers) { + var map = new Map(); + var visited = new Set(); + var result = []; + modifiers.forEach(function (modifier) { + map.set(modifier.name, modifier); + }); // On visiting object, check for its dependencies and visit them recursively + + function sort(modifier) { + visited.add(modifier.name); + var requires = [].concat(modifier.requires || [], modifier.requiresIfExists || []); + requires.forEach(function (dep) { + if (!visited.has(dep)) { + var depModifier = map.get(dep); + + if (depModifier) { + sort(depModifier); + } + } + }); + result.push(modifier); + } + + modifiers.forEach(function (modifier) { + if (!visited.has(modifier.name)) { + // check for visited object + sort(modifier); + } + }); + return result; + } + + function orderModifiers(modifiers) { + // order based on dependencies + var orderedModifiers = order(modifiers); // order based on phase + + return modifierPhases.reduce(function (acc, phase) { + return acc.concat(orderedModifiers.filter(function (modifier) { + return modifier.phase === phase; + })); + }, []); + } + + function debounce(fn) { + var pending; + return function () { + if (!pending) { + pending = new Promise(function (resolve) { + Promise.resolve().then(function () { + pending = undefined; + resolve(fn()); + }); + }); + } + + return pending; + }; + } + + function mergeByName(modifiers) { + var merged = modifiers.reduce(function (merged, current) { + var existing = merged[current.name]; + merged[current.name] = existing ? Object.assign({}, existing, current, { + options: Object.assign({}, existing.options, current.options), + data: Object.assign({}, existing.data, current.data) + }) : current; + return merged; + }, {}); // IE11 does not support Object.values + + return Object.keys(merged).map(function (key) { + return merged[key]; + }); + } + + var DEFAULT_OPTIONS = { + placement: 'bottom', + modifiers: [], + strategy: 'absolute' + }; + + function areValidElements() { + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + return !args.some(function (element) { + return !(element && typeof element.getBoundingClientRect === 'function'); + }); + } + + function popperGenerator(generatorOptions) { + if (generatorOptions === void 0) { + generatorOptions = {}; + } + + var _generatorOptions = generatorOptions, + _generatorOptions$def = _generatorOptions.defaultModifiers, + defaultModifiers = _generatorOptions$def === void 0 ? [] : _generatorOptions$def, + _generatorOptions$def2 = _generatorOptions.defaultOptions, + defaultOptions = _generatorOptions$def2 === void 0 ? DEFAULT_OPTIONS : _generatorOptions$def2; + return function createPopper(reference, popper, options) { + if (options === void 0) { + options = defaultOptions; + } + + var state = { + placement: 'bottom', + orderedModifiers: [], + options: Object.assign({}, DEFAULT_OPTIONS, defaultOptions), + modifiersData: {}, + elements: { + reference: reference, + popper: popper + }, + attributes: {}, + styles: {} + }; + var effectCleanupFns = []; + var isDestroyed = false; + var instance = { + state: state, + setOptions: function setOptions(setOptionsAction) { + var options = typeof setOptionsAction === 'function' ? setOptionsAction(state.options) : setOptionsAction; + cleanupModifierEffects(); + state.options = Object.assign({}, defaultOptions, state.options, options); + state.scrollParents = { + reference: isElement(reference) ? listScrollParents(reference) : reference.contextElement ? listScrollParents(reference.contextElement) : [], + popper: listScrollParents(popper) + }; // Orders the modifiers based on their dependencies and `phase` + // properties + + var orderedModifiers = orderModifiers(mergeByName([].concat(defaultModifiers, state.options.modifiers))); // Strip out disabled modifiers + + state.orderedModifiers = orderedModifiers.filter(function (m) { + return m.enabled; + }); + runModifierEffects(); + return instance.update(); + }, + // Sync update – it will always be executed, even if not necessary. This + // is useful for low frequency updates where sync behavior simplifies the + // logic. + // For high frequency updates (e.g. `resize` and `scroll` events), always + // prefer the async Popper#update method + forceUpdate: function forceUpdate() { + if (isDestroyed) { + return; + } + + var _state$elements = state.elements, + reference = _state$elements.reference, + popper = _state$elements.popper; // Don't proceed if `reference` or `popper` are not valid elements + // anymore + + if (!areValidElements(reference, popper)) { + return; + } // Store the reference and popper rects to be read by modifiers + + + state.rects = { + reference: getCompositeRect(reference, getOffsetParent(popper), state.options.strategy === 'fixed'), + popper: getLayoutRect(popper) + }; // Modifiers have the ability to reset the current update cycle. The + // most common use case for this is the `flip` modifier changing the + // placement, which then needs to re-run all the modifiers, because the + // logic was previously ran for the previous placement and is therefore + // stale/incorrect + + state.reset = false; + state.placement = state.options.placement; // On each update cycle, the `modifiersData` property for each modifier + // is filled with the initial data specified by the modifier. This means + // it doesn't persist and is fresh on each update. + // To ensure persistent data, use `${name}#persistent` + + state.orderedModifiers.forEach(function (modifier) { + return state.modifiersData[modifier.name] = Object.assign({}, modifier.data); + }); + + for (var index = 0; index < state.orderedModifiers.length; index++) { + if (state.reset === true) { + state.reset = false; + index = -1; + continue; + } + + var _state$orderedModifie = state.orderedModifiers[index], + fn = _state$orderedModifie.fn, + _state$orderedModifie2 = _state$orderedModifie.options, + _options = _state$orderedModifie2 === void 0 ? {} : _state$orderedModifie2, + name = _state$orderedModifie.name; + + if (typeof fn === 'function') { + state = fn({ + state: state, + options: _options, + name: name, + instance: instance + }) || state; + } + } + }, + // Async and optimistically optimized update – it will not be executed if + // not necessary (debounced to run at most once-per-tick) + update: debounce(function () { + return new Promise(function (resolve) { + instance.forceUpdate(); + resolve(state); + }); + }), + destroy: function destroy() { + cleanupModifierEffects(); + isDestroyed = true; + } + }; + + if (!areValidElements(reference, popper)) { + return instance; + } + + instance.setOptions(options).then(function (state) { + if (!isDestroyed && options.onFirstUpdate) { + options.onFirstUpdate(state); + } + }); // Modifiers have the ability to execute arbitrary code before the first + // update cycle runs. They will be executed in the same order as the update + // cycle. This is useful when a modifier adds some persistent data that + // other modifiers need to use, but the modifier is run after the dependent + // one. + + function runModifierEffects() { + state.orderedModifiers.forEach(function (_ref) { + var name = _ref.name, + _ref$options = _ref.options, + options = _ref$options === void 0 ? {} : _ref$options, + effect = _ref.effect; + + if (typeof effect === 'function') { + var cleanupFn = effect({ + state: state, + name: name, + instance: instance, + options: options + }); + + var noopFn = function noopFn() {}; + + effectCleanupFns.push(cleanupFn || noopFn); + } + }); + } + + function cleanupModifierEffects() { + effectCleanupFns.forEach(function (fn) { + return fn(); + }); + effectCleanupFns = []; + } + + return instance; + }; + } + var createPopper$2 = /*#__PURE__*/popperGenerator(); // eslint-disable-next-line import/no-unused-modules + + var defaultModifiers$1 = [eventListeners, popperOffsets$1, computeStyles$1, applyStyles$1]; + var createPopper$1 = /*#__PURE__*/popperGenerator({ + defaultModifiers: defaultModifiers$1 + }); // eslint-disable-next-line import/no-unused-modules + + var defaultModifiers = [eventListeners, popperOffsets$1, computeStyles$1, applyStyles$1, offset$1, flip$1, preventOverflow$1, arrow$1, hide$1]; + var createPopper = /*#__PURE__*/popperGenerator({ + defaultModifiers: defaultModifiers + }); // eslint-disable-next-line import/no-unused-modules + + const Popper = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({ + __proto__: null, + afterMain, + afterRead, + afterWrite, + applyStyles: applyStyles$1, + arrow: arrow$1, + auto, + basePlacements, + beforeMain, + beforeRead, + beforeWrite, + bottom, + clippingParents, + computeStyles: computeStyles$1, + createPopper, + createPopperBase: createPopper$2, + createPopperLite: createPopper$1, + detectOverflow, + end, + eventListeners, + flip: flip$1, + hide: hide$1, + left, + main, + modifierPhases, + offset: offset$1, + placements, + popper, + popperGenerator, + popperOffsets: popperOffsets$1, + preventOverflow: preventOverflow$1, + read, + reference, + right, + start, + top, + variationPlacements, + viewport, + write + }, Symbol.toStringTag, { value: 'Module' })); + + /** + * -------------------------------------------------------------------------- + * Bootstrap dropdown.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + + /** + * Constants + */ + + const NAME$a = 'dropdown'; + const DATA_KEY$6 = 'bs.dropdown'; + const EVENT_KEY$6 = `.${DATA_KEY$6}`; + const DATA_API_KEY$3 = '.data-api'; + const ESCAPE_KEY$2 = 'Escape'; + const TAB_KEY$1 = 'Tab'; + const ARROW_UP_KEY$1 = 'ArrowUp'; + const ARROW_DOWN_KEY$1 = 'ArrowDown'; + const RIGHT_MOUSE_BUTTON = 2; // MouseEvent.button value for the secondary button, usually the right button + + const EVENT_HIDE$5 = `hide${EVENT_KEY$6}`; + const EVENT_HIDDEN$5 = `hidden${EVENT_KEY$6}`; + const EVENT_SHOW$5 = `show${EVENT_KEY$6}`; + const EVENT_SHOWN$5 = `shown${EVENT_KEY$6}`; + const EVENT_CLICK_DATA_API$3 = `click${EVENT_KEY$6}${DATA_API_KEY$3}`; + const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY$6}${DATA_API_KEY$3}`; + const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY$6}${DATA_API_KEY$3}`; + const CLASS_NAME_SHOW$6 = 'show'; + const CLASS_NAME_DROPUP = 'dropup'; + const CLASS_NAME_DROPEND = 'dropend'; + const CLASS_NAME_DROPSTART = 'dropstart'; + const CLASS_NAME_DROPUP_CENTER = 'dropup-center'; + const CLASS_NAME_DROPDOWN_CENTER = 'dropdown-center'; + const SELECTOR_DATA_TOGGLE$3 = '[data-bs-toggle="dropdown"]:not(.disabled):not(:disabled)'; + const SELECTOR_DATA_TOGGLE_SHOWN = `${SELECTOR_DATA_TOGGLE$3}.${CLASS_NAME_SHOW$6}`; + const SELECTOR_MENU = '.dropdown-menu'; + const SELECTOR_NAVBAR = '.navbar'; + const SELECTOR_NAVBAR_NAV = '.navbar-nav'; + const SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)'; + const PLACEMENT_TOP = isRTL() ? 'top-end' : 'top-start'; + const PLACEMENT_TOPEND = isRTL() ? 'top-start' : 'top-end'; + const PLACEMENT_BOTTOM = isRTL() ? 'bottom-end' : 'bottom-start'; + const PLACEMENT_BOTTOMEND = isRTL() ? 'bottom-start' : 'bottom-end'; + const PLACEMENT_RIGHT = isRTL() ? 'left-start' : 'right-start'; + const PLACEMENT_LEFT = isRTL() ? 'right-start' : 'left-start'; + const PLACEMENT_TOPCENTER = 'top'; + const PLACEMENT_BOTTOMCENTER = 'bottom'; + const Default$9 = { + autoClose: true, + boundary: 'clippingParents', + display: 'dynamic', + offset: [0, 2], + popperConfig: null, + reference: 'toggle' + }; + const DefaultType$9 = { + autoClose: '(boolean|string)', + boundary: '(string|element)', + display: 'string', + offset: '(array|string|function)', + popperConfig: '(null|object|function)', + reference: '(string|element|object)' + }; + + /** + * Class definition + */ + + class Dropdown extends BaseComponent { + constructor(element, config) { + super(element, config); + this._popper = null; + this._parent = this._element.parentNode; // dropdown wrapper + // TODO: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.3/forms/input-group/ + this._menu = SelectorEngine.next(this._element, SELECTOR_MENU)[0] || SelectorEngine.prev(this._element, SELECTOR_MENU)[0] || SelectorEngine.findOne(SELECTOR_MENU, this._parent); + this._inNavbar = this._detectNavbar(); + } + + // Getters + static get Default() { + return Default$9; + } + static get DefaultType() { + return DefaultType$9; + } + static get NAME() { + return NAME$a; + } + + // Public + toggle() { + return this._isShown() ? this.hide() : this.show(); + } + show() { + if (isDisabled(this._element) || this._isShown()) { + return; + } + const relatedTarget = { + relatedTarget: this._element + }; + const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$5, relatedTarget); + if (showEvent.defaultPrevented) { + return; + } + this._createPopper(); + + // If this is a touch-enabled device we add extra + // empty mouseover listeners to the body's immediate children; + // only needed because of broken event delegation on iOS + // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html + if ('ontouchstart' in document.documentElement && !this._parent.closest(SELECTOR_NAVBAR_NAV)) { + for (const element of [].concat(...document.body.children)) { + EventHandler.on(element, 'mouseover', noop); + } + } + this._element.focus(); + this._element.setAttribute('aria-expanded', true); + this._menu.classList.add(CLASS_NAME_SHOW$6); + this._element.classList.add(CLASS_NAME_SHOW$6); + EventHandler.trigger(this._element, EVENT_SHOWN$5, relatedTarget); + } + hide() { + if (isDisabled(this._element) || !this._isShown()) { + return; + } + const relatedTarget = { + relatedTarget: this._element + }; + this._completeHide(relatedTarget); + } + dispose() { + if (this._popper) { + this._popper.destroy(); + } + super.dispose(); + } + update() { + this._inNavbar = this._detectNavbar(); + if (this._popper) { + this._popper.update(); + } + } + + // Private + _completeHide(relatedTarget) { + const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$5, relatedTarget); + if (hideEvent.defaultPrevented) { + return; + } + + // If this is a touch-enabled device we remove the extra + // empty mouseover listeners we added for iOS support + if ('ontouchstart' in document.documentElement) { + for (const element of [].concat(...document.body.children)) { + EventHandler.off(element, 'mouseover', noop); + } + } + if (this._popper) { + this._popper.destroy(); + } + this._menu.classList.remove(CLASS_NAME_SHOW$6); + this._element.classList.remove(CLASS_NAME_SHOW$6); + this._element.setAttribute('aria-expanded', 'false'); + Manipulator.removeDataAttribute(this._menu, 'popper'); + EventHandler.trigger(this._element, EVENT_HIDDEN$5, relatedTarget); + } + _getConfig(config) { + config = super._getConfig(config); + if (typeof config.reference === 'object' && !isElement$1(config.reference) && typeof config.reference.getBoundingClientRect !== 'function') { + // Popper virtual elements require a getBoundingClientRect method + throw new TypeError(`${NAME$a.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`); + } + return config; + } + _createPopper() { + if (typeof Popper === 'undefined') { + throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org)'); + } + let referenceElement = this._element; + if (this._config.reference === 'parent') { + referenceElement = this._parent; + } else if (isElement$1(this._config.reference)) { + referenceElement = getElement(this._config.reference); + } else if (typeof this._config.reference === 'object') { + referenceElement = this._config.reference; + } + const popperConfig = this._getPopperConfig(); + this._popper = createPopper(referenceElement, this._menu, popperConfig); + } + _isShown() { + return this._menu.classList.contains(CLASS_NAME_SHOW$6); + } + _getPlacement() { + const parentDropdown = this._parent; + if (parentDropdown.classList.contains(CLASS_NAME_DROPEND)) { + return PLACEMENT_RIGHT; + } + if (parentDropdown.classList.contains(CLASS_NAME_DROPSTART)) { + return PLACEMENT_LEFT; + } + if (parentDropdown.classList.contains(CLASS_NAME_DROPUP_CENTER)) { + return PLACEMENT_TOPCENTER; + } + if (parentDropdown.classList.contains(CLASS_NAME_DROPDOWN_CENTER)) { + return PLACEMENT_BOTTOMCENTER; + } + + // We need to trim the value because custom properties can also include spaces + const isEnd = getComputedStyle(this._menu).getPropertyValue('--bs-position').trim() === 'end'; + if (parentDropdown.classList.contains(CLASS_NAME_DROPUP)) { + return isEnd ? PLACEMENT_TOPEND : PLACEMENT_TOP; + } + return isEnd ? PLACEMENT_BOTTOMEND : PLACEMENT_BOTTOM; + } + _detectNavbar() { + return this._element.closest(SELECTOR_NAVBAR) !== null; + } + _getOffset() { + const { + offset + } = this._config; + if (typeof offset === 'string') { + return offset.split(',').map(value => Number.parseInt(value, 10)); + } + if (typeof offset === 'function') { + return popperData => offset(popperData, this._element); + } + return offset; + } + _getPopperConfig() { + const defaultBsPopperConfig = { + placement: this._getPlacement(), + modifiers: [{ + name: 'preventOverflow', + options: { + boundary: this._config.boundary + } + }, { + name: 'offset', + options: { + offset: this._getOffset() + } + }] + }; + + // Disable Popper if we have a static display or Dropdown is in Navbar + if (this._inNavbar || this._config.display === 'static') { + Manipulator.setDataAttribute(this._menu, 'popper', 'static'); // TODO: v6 remove + defaultBsPopperConfig.modifiers = [{ + name: 'applyStyles', + enabled: false + }]; + } + return { + ...defaultBsPopperConfig, + ...execute(this._config.popperConfig, [defaultBsPopperConfig]) + }; + } + _selectMenuItem({ + key, + target + }) { + const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(element => isVisible(element)); + if (!items.length) { + return; + } + + // if target isn't included in items (e.g. when expanding the dropdown) + // allow cycling to get the last item in case key equals ARROW_UP_KEY + getNextActiveElement(items, target, key === ARROW_DOWN_KEY$1, !items.includes(target)).focus(); + } + + // Static + static jQueryInterface(config) { + return this.each(function () { + const data = Dropdown.getOrCreateInstance(this, config); + if (typeof config !== 'string') { + return; + } + if (typeof data[config] === 'undefined') { + throw new TypeError(`No method named "${config}"`); + } + data[config](); + }); + } + static clearMenus(event) { + if (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY$1) { + return; + } + const openToggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE_SHOWN); + for (const toggle of openToggles) { + const context = Dropdown.getInstance(toggle); + if (!context || context._config.autoClose === false) { + continue; + } + const composedPath = event.composedPath(); + const isMenuTarget = composedPath.includes(context._menu); + if (composedPath.includes(context._element) || context._config.autoClose === 'inside' && !isMenuTarget || context._config.autoClose === 'outside' && isMenuTarget) { + continue; + } + + // Tab navigation through the dropdown menu or events from contained inputs shouldn't close the menu + if (context._menu.contains(event.target) && (event.type === 'keyup' && event.key === TAB_KEY$1 || /input|select|option|textarea|form/i.test(event.target.tagName))) { + continue; + } + const relatedTarget = { + relatedTarget: context._element + }; + if (event.type === 'click') { + relatedTarget.clickEvent = event; + } + context._completeHide(relatedTarget); + } + } + static dataApiKeydownHandler(event) { + // If not an UP | DOWN | ESCAPE key => not a dropdown command + // If input/textarea && if key is other than ESCAPE => not a dropdown command + + const isInput = /input|textarea/i.test(event.target.tagName); + const isEscapeEvent = event.key === ESCAPE_KEY$2; + const isUpOrDownEvent = [ARROW_UP_KEY$1, ARROW_DOWN_KEY$1].includes(event.key); + if (!isUpOrDownEvent && !isEscapeEvent) { + return; + } + if (isInput && !isEscapeEvent) { + return; + } + event.preventDefault(); + + // TODO: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.3/forms/input-group/ + const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE$3) ? this : SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE$3)[0] || SelectorEngine.next(this, SELECTOR_DATA_TOGGLE$3)[0] || SelectorEngine.findOne(SELECTOR_DATA_TOGGLE$3, event.delegateTarget.parentNode); + const instance = Dropdown.getOrCreateInstance(getToggleButton); + if (isUpOrDownEvent) { + event.stopPropagation(); + instance.show(); + instance._selectMenuItem(event); + return; + } + if (instance._isShown()) { + // else is escape and we check if it is shown + event.stopPropagation(); + instance.hide(); + getToggleButton.focus(); + } + } + } + + /** + * Data API implementation + */ + + EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE$3, Dropdown.dataApiKeydownHandler); + EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown.dataApiKeydownHandler); + EventHandler.on(document, EVENT_CLICK_DATA_API$3, Dropdown.clearMenus); + EventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus); + EventHandler.on(document, EVENT_CLICK_DATA_API$3, SELECTOR_DATA_TOGGLE$3, function (event) { + event.preventDefault(); + Dropdown.getOrCreateInstance(this).toggle(); + }); + + /** + * jQuery + */ + + defineJQueryPlugin(Dropdown); + + /** + * -------------------------------------------------------------------------- + * Bootstrap util/backdrop.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + + /** + * Constants + */ + + const NAME$9 = 'backdrop'; + const CLASS_NAME_FADE$4 = 'fade'; + const CLASS_NAME_SHOW$5 = 'show'; + const EVENT_MOUSEDOWN = `mousedown.bs.${NAME$9}`; + const Default$8 = { + className: 'modal-backdrop', + clickCallback: null, + isAnimated: false, + isVisible: true, + // if false, we use the backdrop helper without adding any element to the dom + rootElement: 'body' // give the choice to place backdrop under different elements + }; + + const DefaultType$8 = { + className: 'string', + clickCallback: '(function|null)', + isAnimated: 'boolean', + isVisible: 'boolean', + rootElement: '(element|string)' + }; + + /** + * Class definition + */ + + class Backdrop extends Config { + constructor(config) { + super(); + this._config = this._getConfig(config); + this._isAppended = false; + this._element = null; + } + + // Getters + static get Default() { + return Default$8; + } + static get DefaultType() { + return DefaultType$8; + } + static get NAME() { + return NAME$9; + } + + // Public + show(callback) { + if (!this._config.isVisible) { + execute(callback); + return; + } + this._append(); + const element = this._getElement(); + if (this._config.isAnimated) { + reflow(element); + } + element.classList.add(CLASS_NAME_SHOW$5); + this._emulateAnimation(() => { + execute(callback); + }); + } + hide(callback) { + if (!this._config.isVisible) { + execute(callback); + return; + } + this._getElement().classList.remove(CLASS_NAME_SHOW$5); + this._emulateAnimation(() => { + this.dispose(); + execute(callback); + }); + } + dispose() { + if (!this._isAppended) { + return; + } + EventHandler.off(this._element, EVENT_MOUSEDOWN); + this._element.remove(); + this._isAppended = false; + } + + // Private + _getElement() { + if (!this._element) { + const backdrop = document.createElement('div'); + backdrop.className = this._config.className; + if (this._config.isAnimated) { + backdrop.classList.add(CLASS_NAME_FADE$4); + } + this._element = backdrop; + } + return this._element; + } + _configAfterMerge(config) { + // use getElement() with the default "body" to get a fresh Element on each instantiation + config.rootElement = getElement(config.rootElement); + return config; + } + _append() { + if (this._isAppended) { + return; + } + const element = this._getElement(); + this._config.rootElement.append(element); + EventHandler.on(element, EVENT_MOUSEDOWN, () => { + execute(this._config.clickCallback); + }); + this._isAppended = true; + } + _emulateAnimation(callback) { + executeAfterTransition(callback, this._getElement(), this._config.isAnimated); + } + } + + /** + * -------------------------------------------------------------------------- + * Bootstrap util/focustrap.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + + /** + * Constants + */ + + const NAME$8 = 'focustrap'; + const DATA_KEY$5 = 'bs.focustrap'; + const EVENT_KEY$5 = `.${DATA_KEY$5}`; + const EVENT_FOCUSIN$2 = `focusin${EVENT_KEY$5}`; + const EVENT_KEYDOWN_TAB = `keydown.tab${EVENT_KEY$5}`; + const TAB_KEY = 'Tab'; + const TAB_NAV_FORWARD = 'forward'; + const TAB_NAV_BACKWARD = 'backward'; + const Default$7 = { + autofocus: true, + trapElement: null // The element to trap focus inside of + }; + + const DefaultType$7 = { + autofocus: 'boolean', + trapElement: 'element' + }; + + /** + * Class definition + */ + + class FocusTrap extends Config { + constructor(config) { + super(); + this._config = this._getConfig(config); + this._isActive = false; + this._lastTabNavDirection = null; + } + + // Getters + static get Default() { + return Default$7; + } + static get DefaultType() { + return DefaultType$7; + } + static get NAME() { + return NAME$8; + } + + // Public + activate() { + if (this._isActive) { + return; + } + if (this._config.autofocus) { + this._config.trapElement.focus(); + } + EventHandler.off(document, EVENT_KEY$5); // guard against infinite focus loop + EventHandler.on(document, EVENT_FOCUSIN$2, event => this._handleFocusin(event)); + EventHandler.on(document, EVENT_KEYDOWN_TAB, event => this._handleKeydown(event)); + this._isActive = true; + } + deactivate() { + if (!this._isActive) { + return; + } + this._isActive = false; + EventHandler.off(document, EVENT_KEY$5); + } + + // Private + _handleFocusin(event) { + const { + trapElement + } = this._config; + if (event.target === document || event.target === trapElement || trapElement.contains(event.target)) { + return; + } + const elements = SelectorEngine.focusableChildren(trapElement); + if (elements.length === 0) { + trapElement.focus(); + } else if (this._lastTabNavDirection === TAB_NAV_BACKWARD) { + elements[elements.length - 1].focus(); + } else { + elements[0].focus(); + } + } + _handleKeydown(event) { + if (event.key !== TAB_KEY) { + return; + } + this._lastTabNavDirection = event.shiftKey ? TAB_NAV_BACKWARD : TAB_NAV_FORWARD; + } + } + + /** + * -------------------------------------------------------------------------- + * Bootstrap util/scrollBar.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + + /** + * Constants + */ + + const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top'; + const SELECTOR_STICKY_CONTENT = '.sticky-top'; + const PROPERTY_PADDING = 'padding-right'; + const PROPERTY_MARGIN = 'margin-right'; + + /** + * Class definition + */ + + class ScrollBarHelper { + constructor() { + this._element = document.body; + } + + // Public + getWidth() { + // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes + const documentWidth = document.documentElement.clientWidth; + return Math.abs(window.innerWidth - documentWidth); + } + hide() { + const width = this.getWidth(); + this._disableOverFlow(); + // give padding to element to balance the hidden scrollbar width + this._setElementAttributes(this._element, PROPERTY_PADDING, calculatedValue => calculatedValue + width); + // trick: We adjust positive paddingRight and negative marginRight to sticky-top elements to keep showing fullwidth + this._setElementAttributes(SELECTOR_FIXED_CONTENT, PROPERTY_PADDING, calculatedValue => calculatedValue + width); + this._setElementAttributes(SELECTOR_STICKY_CONTENT, PROPERTY_MARGIN, calculatedValue => calculatedValue - width); + } + reset() { + this._resetElementAttributes(this._element, 'overflow'); + this._resetElementAttributes(this._element, PROPERTY_PADDING); + this._resetElementAttributes(SELECTOR_FIXED_CONTENT, PROPERTY_PADDING); + this._resetElementAttributes(SELECTOR_STICKY_CONTENT, PROPERTY_MARGIN); + } + isOverflowing() { + return this.getWidth() > 0; + } + + // Private + _disableOverFlow() { + this._saveInitialAttribute(this._element, 'overflow'); + this._element.style.overflow = 'hidden'; + } + _setElementAttributes(selector, styleProperty, callback) { + const scrollbarWidth = this.getWidth(); + const manipulationCallBack = element => { + if (element !== this._element && window.innerWidth > element.clientWidth + scrollbarWidth) { + return; + } + this._saveInitialAttribute(element, styleProperty); + const calculatedValue = window.getComputedStyle(element).getPropertyValue(styleProperty); + element.style.setProperty(styleProperty, `${callback(Number.parseFloat(calculatedValue))}px`); + }; + this._applyManipulationCallback(selector, manipulationCallBack); + } + _saveInitialAttribute(element, styleProperty) { + const actualValue = element.style.getPropertyValue(styleProperty); + if (actualValue) { + Manipulator.setDataAttribute(element, styleProperty, actualValue); + } + } + _resetElementAttributes(selector, styleProperty) { + const manipulationCallBack = element => { + const value = Manipulator.getDataAttribute(element, styleProperty); + // We only want to remove the property if the value is `null`; the value can also be zero + if (value === null) { + element.style.removeProperty(styleProperty); + return; + } + Manipulator.removeDataAttribute(element, styleProperty); + element.style.setProperty(styleProperty, value); + }; + this._applyManipulationCallback(selector, manipulationCallBack); + } + _applyManipulationCallback(selector, callBack) { + if (isElement$1(selector)) { + callBack(selector); + return; + } + for (const sel of SelectorEngine.find(selector, this._element)) { + callBack(sel); + } + } + } + + /** + * -------------------------------------------------------------------------- + * Bootstrap modal.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + + /** + * Constants + */ + + const NAME$7 = 'modal'; + const DATA_KEY$4 = 'bs.modal'; + const EVENT_KEY$4 = `.${DATA_KEY$4}`; + const DATA_API_KEY$2 = '.data-api'; + const ESCAPE_KEY$1 = 'Escape'; + const EVENT_HIDE$4 = `hide${EVENT_KEY$4}`; + const EVENT_HIDE_PREVENTED$1 = `hidePrevented${EVENT_KEY$4}`; + const EVENT_HIDDEN$4 = `hidden${EVENT_KEY$4}`; + const EVENT_SHOW$4 = `show${EVENT_KEY$4}`; + const EVENT_SHOWN$4 = `shown${EVENT_KEY$4}`; + const EVENT_RESIZE$1 = `resize${EVENT_KEY$4}`; + const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY$4}`; + const EVENT_MOUSEDOWN_DISMISS = `mousedown.dismiss${EVENT_KEY$4}`; + const EVENT_KEYDOWN_DISMISS$1 = `keydown.dismiss${EVENT_KEY$4}`; + const EVENT_CLICK_DATA_API$2 = `click${EVENT_KEY$4}${DATA_API_KEY$2}`; + const CLASS_NAME_OPEN = 'modal-open'; + const CLASS_NAME_FADE$3 = 'fade'; + const CLASS_NAME_SHOW$4 = 'show'; + const CLASS_NAME_STATIC = 'modal-static'; + const OPEN_SELECTOR$1 = '.modal.show'; + const SELECTOR_DIALOG = '.modal-dialog'; + const SELECTOR_MODAL_BODY = '.modal-body'; + const SELECTOR_DATA_TOGGLE$2 = '[data-bs-toggle="modal"]'; + const Default$6 = { + backdrop: true, + focus: true, + keyboard: true + }; + const DefaultType$6 = { + backdrop: '(boolean|string)', + focus: 'boolean', + keyboard: 'boolean' + }; + + /** + * Class definition + */ + + class Modal extends BaseComponent { + constructor(element, config) { + super(element, config); + this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element); + this._backdrop = this._initializeBackDrop(); + this._focustrap = this._initializeFocusTrap(); + this._isShown = false; + this._isTransitioning = false; + this._scrollBar = new ScrollBarHelper(); + this._addEventListeners(); + } + + // Getters + static get Default() { + return Default$6; + } + static get DefaultType() { + return DefaultType$6; + } + static get NAME() { + return NAME$7; + } + + // Public + toggle(relatedTarget) { + return this._isShown ? this.hide() : this.show(relatedTarget); + } + show(relatedTarget) { + if (this._isShown || this._isTransitioning) { + return; + } + const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$4, { + relatedTarget + }); + if (showEvent.defaultPrevented) { + return; + } + this._isShown = true; + this._isTransitioning = true; + this._scrollBar.hide(); + document.body.classList.add(CLASS_NAME_OPEN); + this._adjustDialog(); + this._backdrop.show(() => this._showElement(relatedTarget)); + } + hide() { + if (!this._isShown || this._isTransitioning) { + return; + } + const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$4); + if (hideEvent.defaultPrevented) { + return; + } + this._isShown = false; + this._isTransitioning = true; + this._focustrap.deactivate(); + this._element.classList.remove(CLASS_NAME_SHOW$4); + this._queueCallback(() => this._hideModal(), this._element, this._isAnimated()); + } + dispose() { + EventHandler.off(window, EVENT_KEY$4); + EventHandler.off(this._dialog, EVENT_KEY$4); + this._backdrop.dispose(); + this._focustrap.deactivate(); + super.dispose(); + } + handleUpdate() { + this._adjustDialog(); + } + + // Private + _initializeBackDrop() { + return new Backdrop({ + isVisible: Boolean(this._config.backdrop), + // 'static' option will be translated to true, and booleans will keep their value, + isAnimated: this._isAnimated() + }); + } + _initializeFocusTrap() { + return new FocusTrap({ + trapElement: this._element + }); + } + _showElement(relatedTarget) { + // try to append dynamic modal + if (!document.body.contains(this._element)) { + document.body.append(this._element); + } + this._element.style.display = 'block'; + this._element.removeAttribute('aria-hidden'); + this._element.setAttribute('aria-modal', true); + this._element.setAttribute('role', 'dialog'); + this._element.scrollTop = 0; + const modalBody = SelectorEngine.findOne(SELECTOR_MODAL_BODY, this._dialog); + if (modalBody) { + modalBody.scrollTop = 0; + } + reflow(this._element); + this._element.classList.add(CLASS_NAME_SHOW$4); + const transitionComplete = () => { + if (this._config.focus) { + this._focustrap.activate(); + } + this._isTransitioning = false; + EventHandler.trigger(this._element, EVENT_SHOWN$4, { + relatedTarget + }); + }; + this._queueCallback(transitionComplete, this._dialog, this._isAnimated()); + } + _addEventListeners() { + EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS$1, event => { + if (event.key !== ESCAPE_KEY$1) { + return; + } + if (this._config.keyboard) { + this.hide(); + return; + } + this._triggerBackdropTransition(); + }); + EventHandler.on(window, EVENT_RESIZE$1, () => { + if (this._isShown && !this._isTransitioning) { + this._adjustDialog(); + } + }); + EventHandler.on(this._element, EVENT_MOUSEDOWN_DISMISS, event => { + // a bad trick to segregate clicks that may start inside dialog but end outside, and avoid listen to scrollbar clicks + EventHandler.one(this._element, EVENT_CLICK_DISMISS, event2 => { + if (this._element !== event.target || this._element !== event2.target) { + return; + } + if (this._config.backdrop === 'static') { + this._triggerBackdropTransition(); + return; + } + if (this._config.backdrop) { + this.hide(); + } + }); + }); + } + _hideModal() { + this._element.style.display = 'none'; + this._element.setAttribute('aria-hidden', true); + this._element.removeAttribute('aria-modal'); + this._element.removeAttribute('role'); + this._isTransitioning = false; + this._backdrop.hide(() => { + document.body.classList.remove(CLASS_NAME_OPEN); + this._resetAdjustments(); + this._scrollBar.reset(); + EventHandler.trigger(this._element, EVENT_HIDDEN$4); + }); + } + _isAnimated() { + return this._element.classList.contains(CLASS_NAME_FADE$3); + } + _triggerBackdropTransition() { + const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED$1); + if (hideEvent.defaultPrevented) { + return; + } + const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; + const initialOverflowY = this._element.style.overflowY; + // return if the following background transition hasn't yet completed + if (initialOverflowY === 'hidden' || this._element.classList.contains(CLASS_NAME_STATIC)) { + return; + } + if (!isModalOverflowing) { + this._element.style.overflowY = 'hidden'; + } + this._element.classList.add(CLASS_NAME_STATIC); + this._queueCallback(() => { + this._element.classList.remove(CLASS_NAME_STATIC); + this._queueCallback(() => { + this._element.style.overflowY = initialOverflowY; + }, this._dialog); + }, this._dialog); + this._element.focus(); + } + + /** + * The following methods are used to handle overflowing modals + */ + + _adjustDialog() { + const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; + const scrollbarWidth = this._scrollBar.getWidth(); + const isBodyOverflowing = scrollbarWidth > 0; + if (isBodyOverflowing && !isModalOverflowing) { + const property = isRTL() ? 'paddingLeft' : 'paddingRight'; + this._element.style[property] = `${scrollbarWidth}px`; + } + if (!isBodyOverflowing && isModalOverflowing) { + const property = isRTL() ? 'paddingRight' : 'paddingLeft'; + this._element.style[property] = `${scrollbarWidth}px`; + } + } + _resetAdjustments() { + this._element.style.paddingLeft = ''; + this._element.style.paddingRight = ''; + } + + // Static + static jQueryInterface(config, relatedTarget) { + return this.each(function () { + const data = Modal.getOrCreateInstance(this, config); + if (typeof config !== 'string') { + return; + } + if (typeof data[config] === 'undefined') { + throw new TypeError(`No method named "${config}"`); + } + data[config](relatedTarget); + }); + } + } + + /** + * Data API implementation + */ + + EventHandler.on(document, EVENT_CLICK_DATA_API$2, SELECTOR_DATA_TOGGLE$2, function (event) { + const target = SelectorEngine.getElementFromSelector(this); + if (['A', 'AREA'].includes(this.tagName)) { + event.preventDefault(); + } + EventHandler.one(target, EVENT_SHOW$4, showEvent => { + if (showEvent.defaultPrevented) { + // only register focus restorer if modal will actually get shown + return; + } + EventHandler.one(target, EVENT_HIDDEN$4, () => { + if (isVisible(this)) { + this.focus(); + } + }); + }); + + // avoid conflict when clicking modal toggler while another one is open + const alreadyOpen = SelectorEngine.findOne(OPEN_SELECTOR$1); + if (alreadyOpen) { + Modal.getInstance(alreadyOpen).hide(); + } + const data = Modal.getOrCreateInstance(target); + data.toggle(this); + }); + enableDismissTrigger(Modal); + + /** + * jQuery + */ + + defineJQueryPlugin(Modal); + + /** + * -------------------------------------------------------------------------- + * Bootstrap offcanvas.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + + /** + * Constants + */ + + const NAME$6 = 'offcanvas'; + const DATA_KEY$3 = 'bs.offcanvas'; + const EVENT_KEY$3 = `.${DATA_KEY$3}`; + const DATA_API_KEY$1 = '.data-api'; + const EVENT_LOAD_DATA_API$2 = `load${EVENT_KEY$3}${DATA_API_KEY$1}`; + const ESCAPE_KEY = 'Escape'; + const CLASS_NAME_SHOW$3 = 'show'; + const CLASS_NAME_SHOWING$1 = 'showing'; + const CLASS_NAME_HIDING = 'hiding'; + const CLASS_NAME_BACKDROP = 'offcanvas-backdrop'; + const OPEN_SELECTOR = '.offcanvas.show'; + const EVENT_SHOW$3 = `show${EVENT_KEY$3}`; + const EVENT_SHOWN$3 = `shown${EVENT_KEY$3}`; + const EVENT_HIDE$3 = `hide${EVENT_KEY$3}`; + const EVENT_HIDE_PREVENTED = `hidePrevented${EVENT_KEY$3}`; + const EVENT_HIDDEN$3 = `hidden${EVENT_KEY$3}`; + const EVENT_RESIZE = `resize${EVENT_KEY$3}`; + const EVENT_CLICK_DATA_API$1 = `click${EVENT_KEY$3}${DATA_API_KEY$1}`; + const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY$3}`; + const SELECTOR_DATA_TOGGLE$1 = '[data-bs-toggle="offcanvas"]'; + const Default$5 = { + backdrop: true, + keyboard: true, + scroll: false + }; + const DefaultType$5 = { + backdrop: '(boolean|string)', + keyboard: 'boolean', + scroll: 'boolean' + }; + + /** + * Class definition + */ + + class Offcanvas extends BaseComponent { + constructor(element, config) { + super(element, config); + this._isShown = false; + this._backdrop = this._initializeBackDrop(); + this._focustrap = this._initializeFocusTrap(); + this._addEventListeners(); + } + + // Getters + static get Default() { + return Default$5; + } + static get DefaultType() { + return DefaultType$5; + } + static get NAME() { + return NAME$6; + } + + // Public + toggle(relatedTarget) { + return this._isShown ? this.hide() : this.show(relatedTarget); + } + show(relatedTarget) { + if (this._isShown) { + return; + } + const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$3, { + relatedTarget + }); + if (showEvent.defaultPrevented) { + return; + } + this._isShown = true; + this._backdrop.show(); + if (!this._config.scroll) { + new ScrollBarHelper().hide(); + } + this._element.setAttribute('aria-modal', true); + this._element.setAttribute('role', 'dialog'); + this._element.classList.add(CLASS_NAME_SHOWING$1); + const completeCallBack = () => { + if (!this._config.scroll || this._config.backdrop) { + this._focustrap.activate(); + } + this._element.classList.add(CLASS_NAME_SHOW$3); + this._element.classList.remove(CLASS_NAME_SHOWING$1); + EventHandler.trigger(this._element, EVENT_SHOWN$3, { + relatedTarget + }); + }; + this._queueCallback(completeCallBack, this._element, true); + } + hide() { + if (!this._isShown) { + return; + } + const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$3); + if (hideEvent.defaultPrevented) { + return; + } + this._focustrap.deactivate(); + this._element.blur(); + this._isShown = false; + this._element.classList.add(CLASS_NAME_HIDING); + this._backdrop.hide(); + const completeCallback = () => { + this._element.classList.remove(CLASS_NAME_SHOW$3, CLASS_NAME_HIDING); + this._element.removeAttribute('aria-modal'); + this._element.removeAttribute('role'); + if (!this._config.scroll) { + new ScrollBarHelper().reset(); + } + EventHandler.trigger(this._element, EVENT_HIDDEN$3); + }; + this._queueCallback(completeCallback, this._element, true); + } + dispose() { + this._backdrop.dispose(); + this._focustrap.deactivate(); + super.dispose(); + } + + // Private + _initializeBackDrop() { + const clickCallback = () => { + if (this._config.backdrop === 'static') { + EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED); + return; + } + this.hide(); + }; + + // 'static' option will be translated to true, and booleans will keep their value + const isVisible = Boolean(this._config.backdrop); + return new Backdrop({ + className: CLASS_NAME_BACKDROP, + isVisible, + isAnimated: true, + rootElement: this._element.parentNode, + clickCallback: isVisible ? clickCallback : null + }); + } + _initializeFocusTrap() { + return new FocusTrap({ + trapElement: this._element + }); + } + _addEventListeners() { + EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, event => { + if (event.key !== ESCAPE_KEY) { + return; + } + if (this._config.keyboard) { + this.hide(); + return; + } + EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED); + }); + } + + // Static + static jQueryInterface(config) { + return this.each(function () { + const data = Offcanvas.getOrCreateInstance(this, config); + if (typeof config !== 'string') { + return; + } + if (data[config] === undefined || config.startsWith('_') || config === 'constructor') { + throw new TypeError(`No method named "${config}"`); + } + data[config](this); + }); + } + } + + /** + * Data API implementation + */ + + EventHandler.on(document, EVENT_CLICK_DATA_API$1, SELECTOR_DATA_TOGGLE$1, function (event) { + const target = SelectorEngine.getElementFromSelector(this); + if (['A', 'AREA'].includes(this.tagName)) { + event.preventDefault(); + } + if (isDisabled(this)) { + return; + } + EventHandler.one(target, EVENT_HIDDEN$3, () => { + // focus on trigger when it is closed + if (isVisible(this)) { + this.focus(); + } + }); + + // avoid conflict when clicking a toggler of an offcanvas, while another is open + const alreadyOpen = SelectorEngine.findOne(OPEN_SELECTOR); + if (alreadyOpen && alreadyOpen !== target) { + Offcanvas.getInstance(alreadyOpen).hide(); + } + const data = Offcanvas.getOrCreateInstance(target); + data.toggle(this); + }); + EventHandler.on(window, EVENT_LOAD_DATA_API$2, () => { + for (const selector of SelectorEngine.find(OPEN_SELECTOR)) { + Offcanvas.getOrCreateInstance(selector).show(); + } + }); + EventHandler.on(window, EVENT_RESIZE, () => { + for (const element of SelectorEngine.find('[aria-modal][class*=show][class*=offcanvas-]')) { + if (getComputedStyle(element).position !== 'fixed') { + Offcanvas.getOrCreateInstance(element).hide(); + } + } + }); + enableDismissTrigger(Offcanvas); + + /** + * jQuery + */ + + defineJQueryPlugin(Offcanvas); + + /** + * -------------------------------------------------------------------------- + * Bootstrap util/sanitizer.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + // js-docs-start allow-list + const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i; + const DefaultAllowlist = { + // Global attributes allowed on any supplied element below. + '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN], + a: ['target', 'href', 'title', 'rel'], + area: [], + b: [], + br: [], + col: [], + code: [], + div: [], + em: [], + hr: [], + h1: [], + h2: [], + h3: [], + h4: [], + h5: [], + h6: [], + i: [], + img: ['src', 'srcset', 'alt', 'title', 'width', 'height'], + li: [], + ol: [], + p: [], + pre: [], + s: [], + small: [], + span: [], + sub: [], + sup: [], + strong: [], + u: [], + ul: [] + }; + // js-docs-end allow-list + + const uriAttributes = new Set(['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href']); + + /** + * A pattern that recognizes URLs that are safe wrt. XSS in URL navigation + * contexts. + * + * Shout-out to Angular https://github.com/angular/angular/blob/15.2.8/packages/core/src/sanitization/url_sanitizer.ts#L38 + */ + // eslint-disable-next-line unicorn/better-regex + const SAFE_URL_PATTERN = /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i; + const allowedAttribute = (attribute, allowedAttributeList) => { + const attributeName = attribute.nodeName.toLowerCase(); + if (allowedAttributeList.includes(attributeName)) { + if (uriAttributes.has(attributeName)) { + return Boolean(SAFE_URL_PATTERN.test(attribute.nodeValue)); + } + return true; + } + + // Check if a regular expression validates the attribute. + return allowedAttributeList.filter(attributeRegex => attributeRegex instanceof RegExp).some(regex => regex.test(attributeName)); + }; + function sanitizeHtml(unsafeHtml, allowList, sanitizeFunction) { + if (!unsafeHtml.length) { + return unsafeHtml; + } + if (sanitizeFunction && typeof sanitizeFunction === 'function') { + return sanitizeFunction(unsafeHtml); + } + const domParser = new window.DOMParser(); + const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html'); + const elements = [].concat(...createdDocument.body.querySelectorAll('*')); + for (const element of elements) { + const elementName = element.nodeName.toLowerCase(); + if (!Object.keys(allowList).includes(elementName)) { + element.remove(); + continue; + } + const attributeList = [].concat(...element.attributes); + const allowedAttributes = [].concat(allowList['*'] || [], allowList[elementName] || []); + for (const attribute of attributeList) { + if (!allowedAttribute(attribute, allowedAttributes)) { + element.removeAttribute(attribute.nodeName); + } + } + } + return createdDocument.body.innerHTML; + } + + /** + * -------------------------------------------------------------------------- + * Bootstrap util/template-factory.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + + /** + * Constants + */ + + const NAME$5 = 'TemplateFactory'; + const Default$4 = { + allowList: DefaultAllowlist, + content: {}, + // { selector : text , selector2 : text2 , } + extraClass: '', + html: false, + sanitize: true, + sanitizeFn: null, + template: '
' + }; + const DefaultType$4 = { + allowList: 'object', + content: 'object', + extraClass: '(string|function)', + html: 'boolean', + sanitize: 'boolean', + sanitizeFn: '(null|function)', + template: 'string' + }; + const DefaultContentType = { + entry: '(string|element|function|null)', + selector: '(string|element)' + }; + + /** + * Class definition + */ + + class TemplateFactory extends Config { + constructor(config) { + super(); + this._config = this._getConfig(config); + } + + // Getters + static get Default() { + return Default$4; + } + static get DefaultType() { + return DefaultType$4; + } + static get NAME() { + return NAME$5; + } + + // Public + getContent() { + return Object.values(this._config.content).map(config => this._resolvePossibleFunction(config)).filter(Boolean); + } + hasContent() { + return this.getContent().length > 0; + } + changeContent(content) { + this._checkContent(content); + this._config.content = { + ...this._config.content, + ...content + }; + return this; + } + toHtml() { + const templateWrapper = document.createElement('div'); + templateWrapper.innerHTML = this._maybeSanitize(this._config.template); + for (const [selector, text] of Object.entries(this._config.content)) { + this._setContent(templateWrapper, text, selector); + } + const template = templateWrapper.children[0]; + const extraClass = this._resolvePossibleFunction(this._config.extraClass); + if (extraClass) { + template.classList.add(...extraClass.split(' ')); + } + return template; + } + + // Private + _typeCheckConfig(config) { + super._typeCheckConfig(config); + this._checkContent(config.content); + } + _checkContent(arg) { + for (const [selector, content] of Object.entries(arg)) { + super._typeCheckConfig({ + selector, + entry: content + }, DefaultContentType); + } + } + _setContent(template, content, selector) { + const templateElement = SelectorEngine.findOne(selector, template); + if (!templateElement) { + return; + } + content = this._resolvePossibleFunction(content); + if (!content) { + templateElement.remove(); + return; + } + if (isElement$1(content)) { + this._putElementInTemplate(getElement(content), templateElement); + return; + } + if (this._config.html) { + templateElement.innerHTML = this._maybeSanitize(content); + return; + } + templateElement.textContent = content; + } + _maybeSanitize(arg) { + return this._config.sanitize ? sanitizeHtml(arg, this._config.allowList, this._config.sanitizeFn) : arg; + } + _resolvePossibleFunction(arg) { + return execute(arg, [this]); + } + _putElementInTemplate(element, templateElement) { + if (this._config.html) { + templateElement.innerHTML = ''; + templateElement.append(element); + return; + } + templateElement.textContent = element.textContent; + } + } + + /** + * -------------------------------------------------------------------------- + * Bootstrap tooltip.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + + /** + * Constants + */ + + const NAME$4 = 'tooltip'; + const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']); + const CLASS_NAME_FADE$2 = 'fade'; + const CLASS_NAME_MODAL = 'modal'; + const CLASS_NAME_SHOW$2 = 'show'; + const SELECTOR_TOOLTIP_INNER = '.tooltip-inner'; + const SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`; + const EVENT_MODAL_HIDE = 'hide.bs.modal'; + const TRIGGER_HOVER = 'hover'; + const TRIGGER_FOCUS = 'focus'; + const TRIGGER_CLICK = 'click'; + const TRIGGER_MANUAL = 'manual'; + const EVENT_HIDE$2 = 'hide'; + const EVENT_HIDDEN$2 = 'hidden'; + const EVENT_SHOW$2 = 'show'; + const EVENT_SHOWN$2 = 'shown'; + const EVENT_INSERTED = 'inserted'; + const EVENT_CLICK$1 = 'click'; + const EVENT_FOCUSIN$1 = 'focusin'; + const EVENT_FOCUSOUT$1 = 'focusout'; + const EVENT_MOUSEENTER = 'mouseenter'; + const EVENT_MOUSELEAVE = 'mouseleave'; + const AttachmentMap = { + AUTO: 'auto', + TOP: 'top', + RIGHT: isRTL() ? 'left' : 'right', + BOTTOM: 'bottom', + LEFT: isRTL() ? 'right' : 'left' + }; + const Default$3 = { + allowList: DefaultAllowlist, + animation: true, + boundary: 'clippingParents', + container: false, + customClass: '', + delay: 0, + fallbackPlacements: ['top', 'right', 'bottom', 'left'], + html: false, + offset: [0, 6], + placement: 'top', + popperConfig: null, + sanitize: true, + sanitizeFn: null, + selector: false, + template: '', + title: '', + trigger: 'hover focus' + }; + const DefaultType$3 = { + allowList: 'object', + animation: 'boolean', + boundary: '(string|element)', + container: '(string|element|boolean)', + customClass: '(string|function)', + delay: '(number|object)', + fallbackPlacements: 'array', + html: 'boolean', + offset: '(array|string|function)', + placement: '(string|function)', + popperConfig: '(null|object|function)', + sanitize: 'boolean', + sanitizeFn: '(null|function)', + selector: '(string|boolean)', + template: 'string', + title: '(string|element|function)', + trigger: 'string' + }; + + /** + * Class definition + */ + + class Tooltip extends BaseComponent { + constructor(element, config) { + if (typeof Popper === 'undefined') { + throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org)'); + } + super(element, config); + + // Private + this._isEnabled = true; + this._timeout = 0; + this._isHovered = null; + this._activeTrigger = {}; + this._popper = null; + this._templateFactory = null; + this._newContent = null; + + // Protected + this.tip = null; + this._setListeners(); + if (!this._config.selector) { + this._fixTitle(); + } + } + + // Getters + static get Default() { + return Default$3; + } + static get DefaultType() { + return DefaultType$3; + } + static get NAME() { + return NAME$4; + } + + // Public + enable() { + this._isEnabled = true; + } + disable() { + this._isEnabled = false; + } + toggleEnabled() { + this._isEnabled = !this._isEnabled; + } + toggle() { + if (!this._isEnabled) { + return; + } + this._activeTrigger.click = !this._activeTrigger.click; + if (this._isShown()) { + this._leave(); + return; + } + this._enter(); + } + dispose() { + clearTimeout(this._timeout); + EventHandler.off(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler); + if (this._element.getAttribute('data-bs-original-title')) { + this._element.setAttribute('title', this._element.getAttribute('data-bs-original-title')); + } + this._disposePopper(); + super.dispose(); + } + show() { + if (this._element.style.display === 'none') { + throw new Error('Please use show on visible elements'); + } + if (!(this._isWithContent() && this._isEnabled)) { + return; + } + const showEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOW$2)); + const shadowRoot = findShadowRoot(this._element); + const isInTheDom = (shadowRoot || this._element.ownerDocument.documentElement).contains(this._element); + if (showEvent.defaultPrevented || !isInTheDom) { + return; + } + + // TODO: v6 remove this or make it optional + this._disposePopper(); + const tip = this._getTipElement(); + this._element.setAttribute('aria-describedby', tip.getAttribute('id')); + const { + container + } = this._config; + if (!this._element.ownerDocument.documentElement.contains(this.tip)) { + container.append(tip); + EventHandler.trigger(this._element, this.constructor.eventName(EVENT_INSERTED)); + } + this._popper = this._createPopper(tip); + tip.classList.add(CLASS_NAME_SHOW$2); + + // If this is a touch-enabled device we add extra + // empty mouseover listeners to the body's immediate children; + // only needed because of broken event delegation on iOS + // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html + if ('ontouchstart' in document.documentElement) { + for (const element of [].concat(...document.body.children)) { + EventHandler.on(element, 'mouseover', noop); + } + } + const complete = () => { + EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOWN$2)); + if (this._isHovered === false) { + this._leave(); + } + this._isHovered = false; + }; + this._queueCallback(complete, this.tip, this._isAnimated()); + } + hide() { + if (!this._isShown()) { + return; + } + const hideEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDE$2)); + if (hideEvent.defaultPrevented) { + return; + } + const tip = this._getTipElement(); + tip.classList.remove(CLASS_NAME_SHOW$2); + + // If this is a touch-enabled device we remove the extra + // empty mouseover listeners we added for iOS support + if ('ontouchstart' in document.documentElement) { + for (const element of [].concat(...document.body.children)) { + EventHandler.off(element, 'mouseover', noop); + } + } + this._activeTrigger[TRIGGER_CLICK] = false; + this._activeTrigger[TRIGGER_FOCUS] = false; + this._activeTrigger[TRIGGER_HOVER] = false; + this._isHovered = null; // it is a trick to support manual triggering + + const complete = () => { + if (this._isWithActiveTrigger()) { + return; + } + if (!this._isHovered) { + this._disposePopper(); + } + this._element.removeAttribute('aria-describedby'); + EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDDEN$2)); + }; + this._queueCallback(complete, this.tip, this._isAnimated()); + } + update() { + if (this._popper) { + this._popper.update(); + } + } + + // Protected + _isWithContent() { + return Boolean(this._getTitle()); + } + _getTipElement() { + if (!this.tip) { + this.tip = this._createTipElement(this._newContent || this._getContentForTemplate()); + } + return this.tip; + } + _createTipElement(content) { + const tip = this._getTemplateFactory(content).toHtml(); + + // TODO: remove this check in v6 + if (!tip) { + return null; + } + tip.classList.remove(CLASS_NAME_FADE$2, CLASS_NAME_SHOW$2); + // TODO: v6 the following can be achieved with CSS only + tip.classList.add(`bs-${this.constructor.NAME}-auto`); + const tipId = getUID(this.constructor.NAME).toString(); + tip.setAttribute('id', tipId); + if (this._isAnimated()) { + tip.classList.add(CLASS_NAME_FADE$2); + } + return tip; + } + setContent(content) { + this._newContent = content; + if (this._isShown()) { + this._disposePopper(); + this.show(); + } + } + _getTemplateFactory(content) { + if (this._templateFactory) { + this._templateFactory.changeContent(content); + } else { + this._templateFactory = new TemplateFactory({ + ...this._config, + // the `content` var has to be after `this._config` + // to override config.content in case of popover + content, + extraClass: this._resolvePossibleFunction(this._config.customClass) + }); + } + return this._templateFactory; + } + _getContentForTemplate() { + return { + [SELECTOR_TOOLTIP_INNER]: this._getTitle() + }; + } + _getTitle() { + return this._resolvePossibleFunction(this._config.title) || this._element.getAttribute('data-bs-original-title'); + } + + // Private + _initializeOnDelegatedTarget(event) { + return this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig()); + } + _isAnimated() { + return this._config.animation || this.tip && this.tip.classList.contains(CLASS_NAME_FADE$2); + } + _isShown() { + return this.tip && this.tip.classList.contains(CLASS_NAME_SHOW$2); + } + _createPopper(tip) { + const placement = execute(this._config.placement, [this, tip, this._element]); + const attachment = AttachmentMap[placement.toUpperCase()]; + return createPopper(this._element, tip, this._getPopperConfig(attachment)); + } + _getOffset() { + const { + offset + } = this._config; + if (typeof offset === 'string') { + return offset.split(',').map(value => Number.parseInt(value, 10)); + } + if (typeof offset === 'function') { + return popperData => offset(popperData, this._element); + } + return offset; + } + _resolvePossibleFunction(arg) { + return execute(arg, [this._element]); + } + _getPopperConfig(attachment) { + const defaultBsPopperConfig = { + placement: attachment, + modifiers: [{ + name: 'flip', + options: { + fallbackPlacements: this._config.fallbackPlacements + } + }, { + name: 'offset', + options: { + offset: this._getOffset() + } + }, { + name: 'preventOverflow', + options: { + boundary: this._config.boundary + } + }, { + name: 'arrow', + options: { + element: `.${this.constructor.NAME}-arrow` + } + }, { + name: 'preSetPlacement', + enabled: true, + phase: 'beforeMain', + fn: data => { + // Pre-set Popper's placement attribute in order to read the arrow sizes properly. + // Otherwise, Popper mixes up the width and height dimensions since the initial arrow style is for top placement + this._getTipElement().setAttribute('data-popper-placement', data.state.placement); + } + }] + }; + return { + ...defaultBsPopperConfig, + ...execute(this._config.popperConfig, [defaultBsPopperConfig]) + }; + } + _setListeners() { + const triggers = this._config.trigger.split(' '); + for (const trigger of triggers) { + if (trigger === 'click') { + EventHandler.on(this._element, this.constructor.eventName(EVENT_CLICK$1), this._config.selector, event => { + const context = this._initializeOnDelegatedTarget(event); + context.toggle(); + }); + } else if (trigger !== TRIGGER_MANUAL) { + const eventIn = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSEENTER) : this.constructor.eventName(EVENT_FOCUSIN$1); + const eventOut = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSELEAVE) : this.constructor.eventName(EVENT_FOCUSOUT$1); + EventHandler.on(this._element, eventIn, this._config.selector, event => { + const context = this._initializeOnDelegatedTarget(event); + context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true; + context._enter(); + }); + EventHandler.on(this._element, eventOut, this._config.selector, event => { + const context = this._initializeOnDelegatedTarget(event); + context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] = context._element.contains(event.relatedTarget); + context._leave(); + }); + } + } + this._hideModalHandler = () => { + if (this._element) { + this.hide(); + } + }; + EventHandler.on(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler); + } + _fixTitle() { + const title = this._element.getAttribute('title'); + if (!title) { + return; + } + if (!this._element.getAttribute('aria-label') && !this._element.textContent.trim()) { + this._element.setAttribute('aria-label', title); + } + this._element.setAttribute('data-bs-original-title', title); // DO NOT USE IT. Is only for backwards compatibility + this._element.removeAttribute('title'); + } + _enter() { + if (this._isShown() || this._isHovered) { + this._isHovered = true; + return; + } + this._isHovered = true; + this._setTimeout(() => { + if (this._isHovered) { + this.show(); + } + }, this._config.delay.show); + } + _leave() { + if (this._isWithActiveTrigger()) { + return; + } + this._isHovered = false; + this._setTimeout(() => { + if (!this._isHovered) { + this.hide(); + } + }, this._config.delay.hide); + } + _setTimeout(handler, timeout) { + clearTimeout(this._timeout); + this._timeout = setTimeout(handler, timeout); + } + _isWithActiveTrigger() { + return Object.values(this._activeTrigger).includes(true); + } + _getConfig(config) { + const dataAttributes = Manipulator.getDataAttributes(this._element); + for (const dataAttribute of Object.keys(dataAttributes)) { + if (DISALLOWED_ATTRIBUTES.has(dataAttribute)) { + delete dataAttributes[dataAttribute]; + } + } + config = { + ...dataAttributes, + ...(typeof config === 'object' && config ? config : {}) + }; + config = this._mergeConfigObj(config); + config = this._configAfterMerge(config); + this._typeCheckConfig(config); + return config; + } + _configAfterMerge(config) { + config.container = config.container === false ? document.body : getElement(config.container); + if (typeof config.delay === 'number') { + config.delay = { + show: config.delay, + hide: config.delay + }; + } + if (typeof config.title === 'number') { + config.title = config.title.toString(); + } + if (typeof config.content === 'number') { + config.content = config.content.toString(); + } + return config; + } + _getDelegateConfig() { + const config = {}; + for (const [key, value] of Object.entries(this._config)) { + if (this.constructor.Default[key] !== value) { + config[key] = value; + } + } + config.selector = false; + config.trigger = 'manual'; + + // In the future can be replaced with: + // const keysWithDifferentValues = Object.entries(this._config).filter(entry => this.constructor.Default[entry[0]] !== this._config[entry[0]]) + // `Object.fromEntries(keysWithDifferentValues)` + return config; + } + _disposePopper() { + if (this._popper) { + this._popper.destroy(); + this._popper = null; + } + if (this.tip) { + this.tip.remove(); + this.tip = null; + } + } + + // Static + static jQueryInterface(config) { + return this.each(function () { + const data = Tooltip.getOrCreateInstance(this, config); + if (typeof config !== 'string') { + return; + } + if (typeof data[config] === 'undefined') { + throw new TypeError(`No method named "${config}"`); + } + data[config](); + }); + } + } + + /** + * jQuery + */ + + defineJQueryPlugin(Tooltip); + + /** + * -------------------------------------------------------------------------- + * Bootstrap popover.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + + /** + * Constants + */ + + const NAME$3 = 'popover'; + const SELECTOR_TITLE = '.popover-header'; + const SELECTOR_CONTENT = '.popover-body'; + const Default$2 = { + ...Tooltip.Default, + content: '', + offset: [0, 8], + placement: 'right', + template: '', + trigger: 'click' + }; + const DefaultType$2 = { + ...Tooltip.DefaultType, + content: '(null|string|element|function)' + }; + + /** + * Class definition + */ + + class Popover extends Tooltip { + // Getters + static get Default() { + return Default$2; + } + static get DefaultType() { + return DefaultType$2; + } + static get NAME() { + return NAME$3; + } + + // Overrides + _isWithContent() { + return this._getTitle() || this._getContent(); + } + + // Private + _getContentForTemplate() { + return { + [SELECTOR_TITLE]: this._getTitle(), + [SELECTOR_CONTENT]: this._getContent() + }; + } + _getContent() { + return this._resolvePossibleFunction(this._config.content); + } + + // Static + static jQueryInterface(config) { + return this.each(function () { + const data = Popover.getOrCreateInstance(this, config); + if (typeof config !== 'string') { + return; + } + if (typeof data[config] === 'undefined') { + throw new TypeError(`No method named "${config}"`); + } + data[config](); + }); + } + } + + /** + * jQuery + */ + + defineJQueryPlugin(Popover); + + /** + * -------------------------------------------------------------------------- + * Bootstrap scrollspy.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + + /** + * Constants + */ + + const NAME$2 = 'scrollspy'; + const DATA_KEY$2 = 'bs.scrollspy'; + const EVENT_KEY$2 = `.${DATA_KEY$2}`; + const DATA_API_KEY = '.data-api'; + const EVENT_ACTIVATE = `activate${EVENT_KEY$2}`; + const EVENT_CLICK = `click${EVENT_KEY$2}`; + const EVENT_LOAD_DATA_API$1 = `load${EVENT_KEY$2}${DATA_API_KEY}`; + const CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item'; + const CLASS_NAME_ACTIVE$1 = 'active'; + const SELECTOR_DATA_SPY = '[data-bs-spy="scroll"]'; + const SELECTOR_TARGET_LINKS = '[href]'; + const SELECTOR_NAV_LIST_GROUP = '.nav, .list-group'; + const SELECTOR_NAV_LINKS = '.nav-link'; + const SELECTOR_NAV_ITEMS = '.nav-item'; + const SELECTOR_LIST_ITEMS = '.list-group-item'; + const SELECTOR_LINK_ITEMS = `${SELECTOR_NAV_LINKS}, ${SELECTOR_NAV_ITEMS} > ${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}`; + const SELECTOR_DROPDOWN = '.dropdown'; + const SELECTOR_DROPDOWN_TOGGLE$1 = '.dropdown-toggle'; + const Default$1 = { + offset: null, + // TODO: v6 @deprecated, keep it for backwards compatibility reasons + rootMargin: '0px 0px -25%', + smoothScroll: false, + target: null, + threshold: [0.1, 0.5, 1] + }; + const DefaultType$1 = { + offset: '(number|null)', + // TODO v6 @deprecated, keep it for backwards compatibility reasons + rootMargin: 'string', + smoothScroll: 'boolean', + target: 'element', + threshold: 'array' + }; + + /** + * Class definition + */ + + class ScrollSpy extends BaseComponent { + constructor(element, config) { + super(element, config); + + // this._element is the observablesContainer and config.target the menu links wrapper + this._targetLinks = new Map(); + this._observableSections = new Map(); + this._rootElement = getComputedStyle(this._element).overflowY === 'visible' ? null : this._element; + this._activeTarget = null; + this._observer = null; + this._previousScrollData = { + visibleEntryTop: 0, + parentScrollTop: 0 + }; + this.refresh(); // initialize + } + + // Getters + static get Default() { + return Default$1; + } + static get DefaultType() { + return DefaultType$1; + } + static get NAME() { + return NAME$2; + } + + // Public + refresh() { + this._initializeTargetsAndObservables(); + this._maybeEnableSmoothScroll(); + if (this._observer) { + this._observer.disconnect(); + } else { + this._observer = this._getNewObserver(); + } + for (const section of this._observableSections.values()) { + this._observer.observe(section); + } + } + dispose() { + this._observer.disconnect(); + super.dispose(); + } + + // Private + _configAfterMerge(config) { + // TODO: on v6 target should be given explicitly & remove the {target: 'ss-target'} case + config.target = getElement(config.target) || document.body; + + // TODO: v6 Only for backwards compatibility reasons. Use rootMargin only + config.rootMargin = config.offset ? `${config.offset}px 0px -30%` : config.rootMargin; + if (typeof config.threshold === 'string') { + config.threshold = config.threshold.split(',').map(value => Number.parseFloat(value)); + } + return config; + } + _maybeEnableSmoothScroll() { + if (!this._config.smoothScroll) { + return; + } + + // unregister any previous listeners + EventHandler.off(this._config.target, EVENT_CLICK); + EventHandler.on(this._config.target, EVENT_CLICK, SELECTOR_TARGET_LINKS, event => { + const observableSection = this._observableSections.get(event.target.hash); + if (observableSection) { + event.preventDefault(); + const root = this._rootElement || window; + const height = observableSection.offsetTop - this._element.offsetTop; + if (root.scrollTo) { + root.scrollTo({ + top: height, + behavior: 'smooth' + }); + return; + } + + // Chrome 60 doesn't support `scrollTo` + root.scrollTop = height; + } + }); + } + _getNewObserver() { + const options = { + root: this._rootElement, + threshold: this._config.threshold, + rootMargin: this._config.rootMargin + }; + return new IntersectionObserver(entries => this._observerCallback(entries), options); + } + + // The logic of selection + _observerCallback(entries) { + const targetElement = entry => this._targetLinks.get(`#${entry.target.id}`); + const activate = entry => { + this._previousScrollData.visibleEntryTop = entry.target.offsetTop; + this._process(targetElement(entry)); + }; + const parentScrollTop = (this._rootElement || document.documentElement).scrollTop; + const userScrollsDown = parentScrollTop >= this._previousScrollData.parentScrollTop; + this._previousScrollData.parentScrollTop = parentScrollTop; + for (const entry of entries) { + if (!entry.isIntersecting) { + this._activeTarget = null; + this._clearActiveClass(targetElement(entry)); + continue; + } + const entryIsLowerThanPrevious = entry.target.offsetTop >= this._previousScrollData.visibleEntryTop; + // if we are scrolling down, pick the bigger offsetTop + if (userScrollsDown && entryIsLowerThanPrevious) { + activate(entry); + // if parent isn't scrolled, let's keep the first visible item, breaking the iteration + if (!parentScrollTop) { + return; + } + continue; + } + + // if we are scrolling up, pick the smallest offsetTop + if (!userScrollsDown && !entryIsLowerThanPrevious) { + activate(entry); + } + } + } + _initializeTargetsAndObservables() { + this._targetLinks = new Map(); + this._observableSections = new Map(); + const targetLinks = SelectorEngine.find(SELECTOR_TARGET_LINKS, this._config.target); + for (const anchor of targetLinks) { + // ensure that the anchor has an id and is not disabled + if (!anchor.hash || isDisabled(anchor)) { + continue; + } + const observableSection = SelectorEngine.findOne(decodeURI(anchor.hash), this._element); + + // ensure that the observableSection exists & is visible + if (isVisible(observableSection)) { + this._targetLinks.set(decodeURI(anchor.hash), anchor); + this._observableSections.set(anchor.hash, observableSection); + } + } + } + _process(target) { + if (this._activeTarget === target) { + return; + } + this._clearActiveClass(this._config.target); + this._activeTarget = target; + target.classList.add(CLASS_NAME_ACTIVE$1); + this._activateParents(target); + EventHandler.trigger(this._element, EVENT_ACTIVATE, { + relatedTarget: target + }); + } + _activateParents(target) { + // Activate dropdown parents + if (target.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) { + SelectorEngine.findOne(SELECTOR_DROPDOWN_TOGGLE$1, target.closest(SELECTOR_DROPDOWN)).classList.add(CLASS_NAME_ACTIVE$1); + return; + } + for (const listGroup of SelectorEngine.parents(target, SELECTOR_NAV_LIST_GROUP)) { + // Set triggered links parents as active + // With both