Current File : /var/www/vinorea/modules/ipexportimport/controllers/front/export.php |
<?php
/**
*
* NOTICE OF LICENSE
*
* @author SmartPresta <tehran.alishov@gmail.com>
* @copyright 2024 SmartPresta
* @license Commercial License
*/
if (!defined('_PS_VERSION_')) {
exit;
}
require_once dirname(__FILE__) . '/../../classes/EIAHelper.php';
require_once dirname(__FILE__) . '/../../classes/EIAExportCronHistory.php';
class IpExportImportExportModuleFrontController extends ModuleFrontController
{
private $now;
private $exportDir;
private $url;
private $fileType;
private $docName;
public function init()
{
if (Configuration::getGlobalValue('IPEA_SCHDL_ENABLE') && (Configuration::getGlobalValue('IPEA_SCHDL_USE_EMAIL') || Configuration::getGlobalValue('IPEA_SCHDL_USE_FTP'))) {
if (Tools::getValue('token') === md5(Configuration::getGlobalValue('IPEIA_SECURE_KEY'))) {
error_reporting(E_ERROR | E_PARSE);
ini_set('max_execution_time', 0);
ini_set('memory_limit', '-1');
$this->export();
die;
} else {
http_response_code(403);
die($this->module->l('Token is incorrect.'));
}
} else {
http_response_code(401);
die($this->module->l('No schedule is enabled in the module.'));
}
}
public function export()
{
$this->exportDir = dirname(__FILE__) . '/../../export';
// $this->cleanDir($this->exportDir);
$dt = new DateTime();
$this->now = $dt->format('YmdHis');
$this->url = $this->context->link->getModuleLink('ipexportimport', 'exportByGroups', array('token' => md5(Configuration::getGlobalValue('IPEIA_SECURE_KEY'))));
$speeds = [50, 100, 200, 500, 1000, 2000, 5000, 10000];
$allEntities = EIAHelper::allEntities($this->module);
$files = [];
if (Configuration::getGlobalValue('IPEA_SCHDL_USE_EMAIL') == '1') {
$emails_limit = '';
if (Tools::isSubmit('email_ids')) {
$emails_limit = ' AND id_ipexport_email IN (' . pSQL(Tools::getValue('email_ids')) . ') ';
}
$sql = 'SELECT
i.id_ipexport id,
address,
timestamp,
entities,
IFNULL(configuration,
(
SELECT configuration
FROM ' . _DB_PREFIX_ . 'ipexport
WHERE `name` = "catalog_default")) configuration,
datatables
FROM ' . _DB_PREFIX_ . 'ipexport_email ie
LEFT JOIN ' . _DB_PREFIX_ . 'ipexport i ON ie.template = i.`name`
WHERE ie.active = 1 ' . $emails_limit . '
';
$result = Db::getInstance()->executeS($sql);
foreach ($result as $res) {
$config = json_decode($res['configuration'], true);
$attachments = [];
$files[$res['id']] = [];
foreach (explode(',', $res['entities']) as $val) {
$conf = $config[$val];
parse_str($conf['inputs'], $conf['inputs']);
if (isset($files[$res['id']][$val]) && file_exists($files[$res['id']][$val])) {
$file = $files[$res['id']][$val];
} else {
$id = mt_rand() . uniqid();
$data = $this->exportNow(null, 0, $speeds[$conf['inputs']['speed']], -1, $val, $id, $res['id']);
$files[$res['id']][$val] = $file = $this->exportDir . '/' . $data['fileId'] . '.' . $data['type'];
}
$this->fileType = $conf['inputs']['as'];
$this->docName = $conf['inputs']['doc_name'] ?: $allEntities[$val]['plural'];
$file_attachment = array();
$file_attachment['content'] = Tools::file_get_contents($file);
$file_attachment['name'] = ($res['timestamp'] ? $this->now . '-' : '') . $this->docName;
if ($this->fileType === 'xlsx') {
$file_attachment['mime'] = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
$file_attachment['name'] .= '.xlsx';
} elseif ($this->fileType === 'csv') {
$file_attachment['mime'] = 'text/csv';
$file_attachment['name'] .= '.csv';
} elseif ($this->fileType === 'xml') {
$file_attachment['mime'] = 'application/xml';
$file_attachment['name'] .= '.xml';
} elseif ($this->fileType === 'json') {
$file_attachment['mime'] = 'application/json';
$file_attachment['name'] .= '.json';
}
$attachments[$val] = $file_attachment;
}
$response = $this->sendPSEmail($res['address'], $this->module->l('Your exports'), $attachments);
$this->saveCronHistory($response, 'Email', array_keys($attachments));
}
}
if (Configuration::getGlobalValue('IPEA_SCHDL_USE_FTP') == '1') {
$ftps_limit = '';
if (Tools::isSubmit('ftp_ids')) {
$ftps_limit = ' AND id_ipexport_ftp IN (' . pSQL(Tools::getValue('ftp_ids')) . ') ';
}
$sql = 'SELECT
i.id_ipexport id,
ie.`template`,
type,
url,
port,
username,
password,
timestamp,
entities,
IFNULL(configuration,
(
SELECT configuration
FROM ' . _DB_PREFIX_ . 'ipexport
WHERE `name` = "catalog_default")) configuration,
datatables
FROM ' . _DB_PREFIX_ . 'ipexport_ftp ie
LEFT JOIN ' . _DB_PREFIX_ . 'ipexport i ON ie.template = i.`name`
WHERE ie.active = 1 ' . $ftps_limit;
$result = Db::getInstance()->executeS($sql);
foreach ($result as $res) {
$config = json_decode($res['configuration'], true);
foreach (explode(',', $res['entities']) as $val) {
$val = explode(':', $val);
if ($val[1] == '1') {
$conf = $config[$val[0]];
parse_str($conf['inputs'], $conf['inputs']);
if (isset($files[$res['id']][$val[0]]) && file_exists($files[$res['id']][$val[0]])) {
$file = $files[$res['id']][$val[0]];
} else {
$id = mt_rand() . uniqid();
$data = $this->exportNow(null, 0, $speeds[$conf['inputs']['speed']], -1, $val[0], $id, $res['id']);
$files[$res['id']][$val[0]] = $file = $this->exportDir . '/' . $data['fileId'] . '.' . $data['type'];
}
$this->fileType = $conf['inputs']['as'];
$this->docName = $conf['inputs']['doc_name'] ?: $allEntities[$val[0]]['plural'];
$response = $this->uploadToFTP(
$file,
$res['type'],
$res['url'],
$res['port'],
$res['username'],
$res['password'],
$val[2],
$res['timestamp']
);
$this->saveCronHistory($response, 'FTP', $val[0]);
}
}
}
}
// Remove all contents of "export" folder in the end
$this->cleanDir($this->exportDir);
}
public function saveCronHistory($response, $type, $entities)
{
$cronHistory = new EIAExportCronHistory();
$cronHistory->type = $type;
$cronHistory->entities = $entities;
$cronHistory->success = (int) $response['success'];
$cronHistory->message = $response['message'];
$cronHistory->date_add = date('Y-m-d H:i:s');
$cronHistory->add();
}
public function sendPSEmail($to, $subject, $attachments)
{
$dir_mail = false;
$mail_iso = $this->context->language->iso_code;
if (!file_exists(dirname(__FILE__) . '/../../mails/' . $mail_iso . '/export.txt') ||
!file_exists(dirname(__FILE__) . '/../../mails/' . $mail_iso . '/export.html')) {
$this->copyDir(dirname(__FILE__) . '/../../mails/en', dirname(__FILE__) . '/../mails/' . $mail_iso);
}
$dir_mail = dirname(__FILE__) . '/../../mails/';
$configuration = Configuration::getMultiple(array(
'PS_SHOP_EMAIL',
'PS_SHOP_NAME',
));
$template_vars = array('{shop_name}' => $configuration['PS_SHOP_NAME']);
if (Mail::Send(
$this->context->language->id,
'export',
$subject,
$template_vars,
$to,
null,
$configuration['PS_SHOP_EMAIL'],
$configuration['PS_SHOP_NAME'],
$attachments,
null,
$dir_mail,
null,
$this->context->shop->id
)) {
$response = $this->module->l("Email successfully sent with attachment.");
echo $response . " <br>\n ";
return [
'success' => true,
'message' => $response,
];
} else {
$response = $this->module->l("Email could not sent.");
echo $response . " <br>\n ";
return [
'success' => false,
'message' => $response,
];
}
}
public function uploadToFTP($file, $type, $url, $port, $username, $password, $remote_folder, $file_add_ts)
{
if (!$remote_folder) {
return false;
// $remote_folder = 'public_ftp';
}
$password = html_entity_decode($password);
$ext = '.' . $this->fileType;
$file_path = $file_add_ts ? $remote_folder . '/' . $this->now . '-' . $this->docName . $ext : $remote_folder . '/' . $this->docName . $ext;
if ($type === 'sftp') {
set_include_path(dirname(__FILE__) . '/../../vendor/phpseclib');
include_once('Net/SFTP.php');
if (!$port) {
$port = 22;
}
$sftp = new Net_SFTP($url, $port);
if ($sftp->login($username, $password)) {
if ($sftp->put($file_path, $file, NET_SFTP_LOCAL_FILE)) {
$response = sprintf($this->module->l('File was successfully transferred to "%s" using SFTP.'), $file_path);
echo $response . " <br>\n ";
return [
'success' => true,
'message' => $response,
];
} else {
$response = $this->module->l('File was unable to be transferred using SFTP.');
echo $response . " <br>\n ";
return [
'success' => false,
'message' => $response,
];
}
} else {
$response = $this->module->l('Cannot log in using SFTP.');
echo $response . " <br>\n ";
return [
'success' => false,
'message' => $response,
];
}
} else {
if (!$port) {
$port = 21;
}
// open an FTP/FTPS connection
if ($type === 'ftps') {
$connId = ftp_ssl_connect($url, (int) $port);
} else {
$connId = ftp_connect($url, (int) $port);
}
if ($connId) {
// login to FTP server
if (!@ftp_login($connId, $username, $password)) {
$response = $this->module->l('Could not log in using FTP. Make sure login and/or password is correct.') ;
echo $response . " <br>\n ";
return [
'success' => false,
'message' => $response,
];
}
ftp_pasv($connId, true);
if (ftp_put($connId, $file_path, $file, FTP_BINARY)) {
ftp_close($connId);
$response = sprintf($this->module->l('File was successfully transferred to "%s" using FTP.'), $file_path);
echo $response . " <br>\n ";
return [
'success' => true,
'message' => $response,
];
} else {
ftp_pasv($connId, false);
if (ftp_put($connId, $file_path, $file, FTP_BINARY)) {
ftp_close($connId);
$response = sprintf($this->module->l('File was successfully transferred to "%s" using FTP (active mode).'), $file_path);
echo $response . " <br>\n ";
return [
'success' => true,
'message' => $response,
];
}
ftp_close($connId);
$response = $this->module->l('File was unable to be transferred using FTP.');
echo $response . " <br>\n ";
return [
'success' => false,
'message' => $response,
];
}
} else {
$response = $this->module->l('Could not connect using FTP.');
echo $response . " <br>\n ";
return [
'success' => false,
'message' => $response,
];
}
}
}
private function copyDir($src, $dst)
{
// open the source directory
$dir = opendir($src);
// Make the destination directory if not exist
@mkdir($dst);
// Loop through the files in source directory
while ($file = readdir($dir)) {
if (( $file != '.' ) && ( $file != '..' )) {
if (is_dir($src . '/' . $file)) {
// Recursively calling custom copy function
// for sub directory
$this->copyDir($src . '/' . $file, $dst . '/' . $file);
} else {
copy($src . '/' . $file, $dst . '/' . $file);
}
}
}
closedir($dir);
}
private function cleanDir($str)
{
if (is_file($str)) {
//Attempt to delete it.
return unlink($str);
} elseif (is_dir($str)) {
//Get a list of the files in this directory.
$scan = glob(rtrim($str, '/') . '/*');
//Loop through the list of files.
foreach ($scan as $path) {
//Call our recursive function.
$this->cleanDir($path);
}
//Remove the directory itself.
if ($str !== $this->exportDir) {
return @rmdir($str);
} else {
return 1;
}
}
}
public function exportNow($ch, $offset, $limit, $total, $entity, $fileId, $templateId)
{
if ($ch === null) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
}
$query = http_build_query([
'action' => 'export',
'offset' => $offset,
'limit' => $limit,
'entity' => $entity,
'fileId' => $fileId,
'templateId' => $templateId,
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
// curl_setopt($ch, CURLOPT_HTTPHEADER, array("Cookie: XDEBUG_SESSION=netbeans-xdebug"));
$server_output = curl_exec($ch);
if (curl_errno($ch)) {
echo curl_error($ch) . "<br> \n";
}
$server_output = json_decode($server_output, true);
if ($server_output['totalCount']) {
$total = $server_output['totalCount'];
}
if (isset($server_output['isFinished']) && !$server_output['isFinished']) {
$newOffset = $offset + $limit;
return $this->exportNow($ch, $newOffset, $limit, $total, $entity, $fileId, $templateId);
} else {
curl_close($ch);
return $server_output;
}
}
}