diff options
Diffstat (limited to 'public/admin/controller/marketplace/modification.php')
-rw-r--r-- | public/admin/controller/marketplace/modification.php | 777 |
1 files changed, 777 insertions, 0 deletions
diff --git a/public/admin/controller/marketplace/modification.php b/public/admin/controller/marketplace/modification.php new file mode 100644 index 0000000..f094fc1 --- /dev/null +++ b/public/admin/controller/marketplace/modification.php @@ -0,0 +1,777 @@ +<?php +/** + * Modifcation XML Documentation can be found here: + * + * https://github.com/opencart/opencart/wiki/Modification-System + */ +class ControllerMarketplaceModification extends Controller { + private $error = array(); + + public function index() { + $this->load->language('marketplace/modification'); + + $this->document->setTitle($this->language->get('heading_title')); + + $this->load->model('setting/modification'); + + $this->getList(); + } + + public function delete() { + $this->load->language('marketplace/modification'); + + $this->document->setTitle($this->language->get('heading_title')); + + $this->load->model('setting/modification'); + + if (isset($this->request->post['selected']) && $this->validate()) { + foreach ($this->request->post['selected'] as $modification_id) { + $this->model_setting_modification->deleteModification($modification_id); + } + + $this->session->data['success'] = $this->language->get('text_success'); + + $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']; + } + + $this->response->redirect($this->url->link('marketplace/modification', 'user_token=' . $this->session->data['user_token'] . $url, true)); + } + + $this->getList(); + } + + public function refresh($data = array()) { + $this->load->language('marketplace/modification'); + + $this->document->setTitle($this->language->get('heading_title')); + + $this->load->model('setting/modification'); + + if ($this->validate()) { + // Just before files are deleted, if config settings say maintenance mode is off then turn it on + $maintenance = $this->config->get('config_maintenance'); + + $this->load->model('setting/setting'); + + $this->model_setting_setting->editSettingValue('config', 'config_maintenance', true); + + //Log + $log = array(); + + // Clear all modification files + $files = array(); + + // Make path into an array + $path = array(DIR_MODIFICATION . '*'); + + // 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 + $files[] = $file; + } + } + + // Reverse sort the file array + rsort($files); + + // Clear all modification files + foreach ($files as $file) { + if ($file != DIR_MODIFICATION . 'index.html') { + // If file just delete + if (is_file($file)) { + unlink($file); + + // If directory use the remove directory function + } elseif (is_dir($file)) { + rmdir($file); + } + } + } + + // Begin + $xml = array(); + + // Load the default modification XML + $xml[] = file_get_contents(DIR_SYSTEM . 'modification.xml'); + + // This is purly for developers so they can run mods directly and have them run without upload after each change. + $files = glob(DIR_SYSTEM . '*.ocmod.xml'); + + if ($files) { + foreach ($files as $file) { + $xml[] = file_get_contents($file); + } + } + + // Get the default modification file + $results = $this->model_setting_modification->getModifications(); + + foreach ($results as $result) { + if ($result['status']) { + $xml[] = $result['xml']; + } + } + + $modification = array(); + + foreach ($xml as $xml) { + if (empty($xml)){ + continue; + } + + $dom = new DOMDocument('1.0', 'UTF-8'); + $dom->preserveWhiteSpace = false; + $dom->loadXml($xml); + + // Log + $log[] = 'MOD: ' . $dom->getElementsByTagName('name')->item(0)->textContent; + + // Wipe the past modification store in the backup array + $recovery = array(); + + // Set the a recovery of the modification code in case we need to use it if an abort attribute is used. + if (isset($modification)) { + $recovery = $modification; + } + + $files = $dom->getElementsByTagName('modification')->item(0)->getElementsByTagName('file'); + + foreach ($files as $file) { + $operations = $file->getElementsByTagName('operation'); + + $files = explode('|', $file->getAttribute('path')); + + foreach ($files as $file) { + $path = ''; + + // Get the full path of the files that are going to be used for modification + if ((substr($file, 0, 7) == 'catalog')) { + $path = DIR_CATALOG . substr($file, 8); + } + + if ((substr($file, 0, 5) == 'admin')) { + $path = DIR_APPLICATION . substr($file, 6); + } + + if ((substr($file, 0, 6) == 'system')) { + $path = DIR_SYSTEM . substr($file, 7); + } + + if ($path) { + $files = glob($path, GLOB_BRACE); + + if ($files) { + foreach ($files as $file) { + // Get the key to be used for the modification cache filename. + if (substr($file, 0, strlen(DIR_CATALOG)) == DIR_CATALOG) { + $key = 'catalog/' . substr($file, strlen(DIR_CATALOG)); + } + + if (substr($file, 0, strlen(DIR_APPLICATION)) == DIR_APPLICATION) { + $key = 'admin/' . substr($file, strlen(DIR_APPLICATION)); + } + + if (substr($file, 0, strlen(DIR_SYSTEM)) == DIR_SYSTEM) { + $key = 'system/' . substr($file, strlen(DIR_SYSTEM)); + } + + // If file contents is not already in the modification array we need to load it. + if (!isset($modification[$key])) { + $content = file_get_contents($file); + + $modification[$key] = preg_replace('~\r?\n~', "\n", $content); + $original[$key] = preg_replace('~\r?\n~', "\n", $content); + + // Log + $log[] = PHP_EOL . 'FILE: ' . $key; + } + + foreach ($operations as $operation) { + $error = $operation->getAttribute('error'); + + // Ignoreif + $ignoreif = $operation->getElementsByTagName('ignoreif')->item(0); + + if ($ignoreif) { + if ($ignoreif->getAttribute('regex') != 'true') { + if (strpos($modification[$key], $ignoreif->textContent) !== false) { + continue; + } + } else { + if (preg_match($ignoreif->textContent, $modification[$key])) { + continue; + } + } + } + + $status = false; + + // Search and replace + if ($operation->getElementsByTagName('search')->item(0)->getAttribute('regex') != 'true') { + // Search + $search = $operation->getElementsByTagName('search')->item(0)->textContent; + $trim = $operation->getElementsByTagName('search')->item(0)->getAttribute('trim'); + $index = $operation->getElementsByTagName('search')->item(0)->getAttribute('index'); + + // Trim line if no trim attribute is set or is set to true. + if (!$trim || $trim == 'true') { + $search = trim($search); + } + + // Add + $add = $operation->getElementsByTagName('add')->item(0)->textContent; + $trim = $operation->getElementsByTagName('add')->item(0)->getAttribute('trim'); + $position = $operation->getElementsByTagName('add')->item(0)->getAttribute('position'); + $offset = $operation->getElementsByTagName('add')->item(0)->getAttribute('offset'); + + if ($offset == '') { + $offset = 0; + } + + // Trim line if is set to true. + if ($trim == 'true') { + $add = trim($add); + } + + // Log + $log[] = 'CODE: ' . $search; + + // Check if using indexes + if ($index !== '') { + $indexes = explode(',', $index); + } else { + $indexes = array(); + } + + // Get all the matches + $i = 0; + + $lines = explode("\n", $modification[$key]); + + for ($line_id = 0; $line_id < count($lines); $line_id++) { + $line = $lines[$line_id]; + + // Status + $match = false; + + // Check to see if the line matches the search code. + if (stripos($line, $search) !== false) { + // If indexes are not used then just set the found status to true. + if (!$indexes) { + $match = true; + } elseif (in_array($i, $indexes)) { + $match = true; + } + + $i++; + } + + // Now for replacing or adding to the matched elements + if ($match) { + switch ($position) { + default: + case 'replace': + $new_lines = explode("\n", $add); + + if ($offset < 0) { + array_splice($lines, $line_id + $offset, abs($offset) + 1, array(str_replace($search, $add, $line))); + + $line_id -= $offset; + } else { + array_splice($lines, $line_id, $offset + 1, array(str_replace($search, $add, $line))); + } + break; + case 'before': + $new_lines = explode("\n", $add); + + array_splice($lines, $line_id - $offset, 0, $new_lines); + + $line_id += count($new_lines); + break; + case 'after': + $new_lines = explode("\n", $add); + + array_splice($lines, ($line_id + 1) + $offset, 0, $new_lines); + + $line_id += count($new_lines); + break; + } + + // Log + $log[] = 'LINE: ' . $line_id; + + $status = true; + } + } + + $modification[$key] = implode("\n", $lines); + } else { + $search = trim($operation->getElementsByTagName('search')->item(0)->textContent); + $limit = $operation->getElementsByTagName('search')->item(0)->getAttribute('limit'); + $replace = trim($operation->getElementsByTagName('add')->item(0)->textContent); + + // Limit + if (!$limit) { + $limit = -1; + } + + // Log + $match = array(); + + preg_match_all($search, $modification[$key], $match, PREG_OFFSET_CAPTURE); + + // Remove part of the the result if a limit is set. + if ($limit > 0) { + $match[0] = array_slice($match[0], 0, $limit); + } + + if ($match[0]) { + $log[] = 'REGEX: ' . $search; + + for ($i = 0; $i < count($match[0]); $i++) { + $log[] = 'LINE: ' . (substr_count(substr($modification[$key], 0, $match[0][$i][1]), "\n") + 1); + } + + $status = true; + } + + // Make the modification + $modification[$key] = preg_replace($search, $replace, $modification[$key], $limit); + } + + if (!$status) { + // Abort applying this modification completely. + if ($error == 'abort') { + $modification = $recovery; + // Log + $log[] = 'NOT FOUND - ABORTING!'; + break 5; + } + // Skip current operation or break + elseif ($error == 'skip') { + // Log + $log[] = 'NOT FOUND - OPERATION SKIPPED!'; + continue; + } + // Break current operations + else { + // Log + $log[] = 'NOT FOUND - OPERATIONS ABORTED!'; + break; + } + } + } + } + } + } + } + } + + // Log + $log[] = '----------------------------------------------------------------'; + } + + // Log + $ocmod = new Log('ocmod.log'); + $ocmod->write(implode("\n", $log)); + + // Write all modification files + foreach ($modification as $key => $value) { + // Only create a file if there are changes + if ($original[$key] != $value) { + $path = ''; + + $directories = explode('/', dirname($key)); + + foreach ($directories as $directory) { + $path = $path . '/' . $directory; + + if (!is_dir(DIR_MODIFICATION . $path)) { + @mkdir(DIR_MODIFICATION . $path, 0777); + } + } + + $handle = fopen(DIR_MODIFICATION . $key, 'w'); + + fwrite($handle, $value); + + fclose($handle); + } + } + + // Maintance mode back to original settings + $this->model_setting_setting->editSettingValue('config', 'config_maintenance', $maintenance); + + // Do not return success message if refresh() was called with $data + $this->session->data['success'] = $this->language->get('text_success'); + + $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']; + } + + $this->response->redirect($this->url->link(!empty($data['redirect']) ? $data['redirect'] : 'marketplace/modification', 'user_token=' . $this->session->data['user_token'] . $url, true)); + } + + $this->getList(); + } + + public function clear() { + $this->load->language('marketplace/modification'); + + $this->document->setTitle($this->language->get('heading_title')); + + $this->load->model('setting/modification'); + + if ($this->validate()) { + $files = array(); + + // Make path into an array + $path = array(DIR_MODIFICATION . '*'); + + // 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 + $files[] = $file; + } + } + + // Reverse sort the file array + rsort($files); + + // Clear all modification files + foreach ($files as $file) { + if ($file != DIR_MODIFICATION . 'index.html') { + // If file just delete + if (is_file($file)) { + unlink($file); + + // If directory use the remove directory function + } elseif (is_dir($file)) { + rmdir($file); + } + } + } + + $this->session->data['success'] = $this->language->get('text_success'); + + $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']; + } + + $this->response->redirect($this->url->link('marketplace/modification', 'user_token=' . $this->session->data['user_token'] . $url, true)); + } + + $this->getList(); + } + + public function enable() { + $this->load->language('marketplace/modification'); + + $this->document->setTitle($this->language->get('heading_title')); + + $this->load->model('setting/modification'); + + if (isset($this->request->get['modification_id']) && $this->validate()) { + $this->model_setting_modification->enableModification($this->request->get['modification_id']); + + $this->session->data['success'] = $this->language->get('text_success'); + + $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']; + } + + $this->response->redirect($this->url->link('marketplace/modification', 'user_token=' . $this->session->data['user_token'] . $url, true)); + } + + $this->getList(); + } + + public function disable() { + $this->load->language('marketplace/modification'); + + $this->document->setTitle($this->language->get('heading_title')); + + $this->load->model('setting/modification'); + + if (isset($this->request->get['modification_id']) && $this->validate()) { + $this->model_setting_modification->disableModification($this->request->get['modification_id']); + + $this->session->data['success'] = $this->language->get('text_success'); + + $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']; + } + + $this->response->redirect($this->url->link('marketplace/modification', 'user_token=' . $this->session->data['user_token'] . $url, true)); + } + + $this->getList(); + } + + public function clearlog() { + $this->load->language('marketplace/modification'); + + $this->document->setTitle($this->language->get('heading_title')); + + $this->load->model('setting/modification'); + + if ($this->validate()) { + $handle = fopen(DIR_LOGS . 'ocmod.log', 'w+'); + + fclose($handle); + + $this->session->data['success'] = $this->language->get('text_success'); + + $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']; + } + + $this->response->redirect($this->url->link('marketplace/modification', 'user_token=' . $this->session->data['user_token'] . $url, true)); + } + + $this->getList(); + } + + protected function getList() { + if (isset($this->request->get['sort'])) { + $sort = $this->request->get['sort']; + } else { + $sort = 'name'; + } + + if (isset($this->request->get['order'])) { + $order = $this->request->get['order']; + } else { + $order = 'ASC'; + } + + if (isset($this->request->get['page'])) { + $page = $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'] = array(); + + $data['breadcrumbs'][] = array( + 'text' => $this->language->get('text_home'), + 'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token'], true) + ); + + $data['breadcrumbs'][] = array( + 'text' => $this->language->get('heading_title'), + 'href' => $this->url->link('marketplace/modification', 'user_token=' . $this->session->data['user_token'], true) + ); + + $data['refresh'] = $this->url->link('marketplace/modification/refresh', 'user_token=' . $this->session->data['user_token'] . $url, true); + $data['clear'] = $this->url->link('marketplace/modification/clear', 'user_token=' . $this->session->data['user_token'] . $url, true); + $data['delete'] = $this->url->link('marketplace/modification/delete', 'user_token=' . $this->session->data['user_token'] . $url, true); + + $data['modifications'] = array(); + + $filter_data = array( + 'sort' => $sort, + 'order' => $order, + 'start' => ($page - 1) * $this->config->get('config_limit_admin'), + 'limit' => $this->config->get('config_limit_admin') + ); + + $modification_total = $this->model_setting_modification->getTotalModifications(); + + $results = $this->model_setting_modification->getModifications($filter_data); + + foreach ($results as $result) { + $data['modifications'][] = array( + 'modification_id' => $result['modification_id'], + 'name' => $result['name'], + 'author' => $result['author'], + 'version' => $result['version'], + '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'])), + 'link' => $result['link'], + 'enable' => $this->url->link('marketplace/modification/enable', 'user_token=' . $this->session->data['user_token'] . '&modification_id=' . $result['modification_id'], true), + 'disable' => $this->url->link('marketplace/modification/disable', 'user_token=' . $this->session->data['user_token'] . '&modification_id=' . $result['modification_id'], true), + 'enabled' => $result['status'] + ); + } + + $data['user_token'] = $this->session->data['user_token']; + + if (isset($this->error['warning'])) { + $data['error_warning'] = $this->error['warning']; + } else { + $data['error_warning'] = ''; + } + + if (isset($this->session->data['success'])) { + $data['success'] = $this->session->data['success']; + + unset($this->session->data['success']); + } else { + $data['success'] = ''; + } + + if (isset($this->request->post['selected'])) { + $data['selected'] = (array)$this->request->post['selected']; + } else { + $data['selected'] = array(); + } + + $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('marketplace/modification', 'user_token=' . $this->session->data['user_token'] . '&sort=name' . $url, true); + $data['sort_author'] = $this->url->link('marketplace/modification', 'user_token=' . $this->session->data['user_token'] . '&sort=author' . $url, true); + $data['sort_version'] = $this->url->link('marketplace/modification', 'user_token=' . $this->session->data['user_token'] . '&sort=version' . $url, true); + $data['sort_status'] = $this->url->link('marketplace/modification', 'user_token=' . $this->session->data['user_token'] . '&sort=status' . $url, true); + $data['sort_date_added'] = $this->url->link('marketplace/modification', 'user_token=' . $this->session->data['user_token'] . '&sort=date_added' . $url, true); + + $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']; + } + + $pagination = new Pagination(); + $pagination->total = $modification_total; + $pagination->page = $page; + $pagination->limit = $this->config->get('config_limit_admin'); + $pagination->url = $this->url->link('marketplace/modification', 'user_token=' . $this->session->data['user_token'] . $url . '&page={page}', true); + + $data['pagination'] = $pagination->render(); + + $data['results'] = sprintf($this->language->get('text_pagination'), ($modification_total) ? (($page - 1) * $this->config->get('config_limit_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_limit_admin')) > ($modification_total - $this->config->get('config_limit_admin'))) ? $modification_total : ((($page - 1) * $this->config->get('config_limit_admin')) + $this->config->get('config_limit_admin')), $modification_total, ceil($modification_total / $this->config->get('config_limit_admin'))); + + $data['sort'] = $sort; + $data['order'] = $order; + + // Log + $file = DIR_LOGS . 'ocmod.log'; + + if (file_exists($file)) { + $data['log'] = htmlentities(file_get_contents($file, FILE_USE_INCLUDE_PATH, null)); + } else { + $data['log'] = ''; + } + + $data['clear_log'] = $this->url->link('marketplace/modification/clearlog', 'user_token=' . $this->session->data['user_token'], true); + + $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/modification', $data)); + } + + protected function validate() { + if (!$this->user->hasPermission('modify', 'marketplace/modification')) { + $this->error['warning'] = $this->language->get('error_permission'); + } + + return !$this->error; + } +} |