yf_manage_shop_upload_images admin module| File | plugins/shop/admin_modules/manage_shop/yf_manage_shop_upload_images.class.php |
|---|---|
| Use | admin URL ?object=manage_shop_upload_images |
A site sets them in its config with $PROJECT_CONF['manage_shop_upload_images']['NAME'] = ...;
| Property | Default | Description |
|---|---|---|
$ALLOWED_MIME_TYPES |
['application/zip' => 'zip', 'application/x-rar' => 'rar', 'application/x-tar' => 'tar', 'application/x-gzip' => 'gz'] |
|
$ARCHIVE_FOLDER |
null |
|
$CONFINE_SERVER_PATHbool |
false |
SECURITY: "from server path" takes only a file inside ARCHIVE_FOLDER or SERVER_PATH_DIRS (realpath, so give an absolute path: a relative one resolves against the working directory); default false keeps any readable path, 4.0 flips |
$MAX_IMAGE_SIZE |
8196 |
|
$SAVE_PATH |
null |
|
$SERVER_PATH_DIRSarray |
[] |
More directories CONFINE_SERVER_PATH accepts, e.g. the FTP drop folder of the suppliers |
$SUPPLIER_ID |
null |
public function resize_and_save_image($img, $id, $md5)
public function resize_and_save_image($img, $id, $md5)
{
ini_set('memory_limit', '200M');
$dirs = sprintf('%06s', $id);
$dir2 = substr($dirs, -3, 3);
$dir1 = substr($dirs, -6, 3);
$ext = pathinfo($img, PATHINFO_EXTENSION);
$new_path = $this->SAVE_PATH . $dir1 . '/' . $dir2 . '/';
if ( ! file_exists($new_path)) {
mkdir($new_path, 0777, true);
}
db()->begin();
db()->insert(db('shop_product_images'), [
'product_id' => $id,
'md5' => $md5,
'date_uploaded' => ($_SERVER['REQUEST_TIME'] ?? null),
]);
$i = db()->insert_id();
$real_name = $new_path . 'product_' . $id . '_' . $i . '.jpg';
$thumb_name = $new_path . 'product_' . $id . '_' . $i . module('manage_shop')->THUMB_SUFFIX . '.jpg';
$big_name = $new_path . 'product_' . $id . '_' . $i . module('manage_shop')->FULL_IMG_SUFFIX . '.jpg';
$watermark_name = PROJECT_PATH . SITE_WATERMARK_FILE;
common()->make_thumb($img, $real_name, module('manage_shop')->BIG_X, module('manage_shop')->BIG_Y);
common()->make_thumb($img, $thumb_name, module('manage_shop')->THUMB_X, module('manage_shop')->THUMB_Y);
common()->make_thumb($img, $big_name, module('manage_shop')->BIG_X, module('manage_shop')->BIG_Y, $watermark_name);
$A = db()->query_fetch('SELECT COUNT(*) AS cnt FROM ' . db('shop_product_images') . ' WHERE product_id=' . $id . ' AND is_default=1 AND active=1');
if ($A['cnt'] == 0) {
$A = db()->query_fetch('SELECT id FROM ' . db('shop_product_images') . ' WHERE product_id=' . $id . ' ORDER BY id DESC');
db()->query('UPDATE ' . db('shop_product_images') . ' SET is_default=1 WHERE id=' . $A['id']);
}
db()->query('UPDATE `' . db('shop_products') . "` SET `image`='1' WHERE `id`=" . $id);
db()->commit();
module('manage_shop')->_product_images_add_revision('import', $id, $i);
return $thumb_name;
}
public function search_product_by_filename($folder, $supplier_id = false)
public function search_product_by_filename($folder, $supplier_id = false)
{
$filename = basename($folder);
$ext = pathinfo($filename, PATHINFO_EXTENSION);
$filename = ltrim($filename, ' .-_+=/\|,!@#%~&*()');
if (strpos($filename, '_')) {
$articul = explode('_', $filename);
} elseif (strpos($filename, '.')) {
$articul = explode('.', $filename);
} else {
return 'Wrong filename';
}
if ( ! empty($articul[0])) {
$articul = _es(strip_tags($articul[0]));
$sql = 'SELECT id FROM ' . db('shop_products') . '
WHERE articul IN ("' . $articul . '","' . pathinfo($filename, PATHINFO_FILENAME) . '")
AND supplier_id=' . $supplier_id;
$product = db()->query_fetch($sql);
} else {
return 'Articul_not_found';
}
if (empty($product)) {
return 'Product_not_found';
}
$md5 = md5_file($folder);
$db_item = db()->query_fetch('SELECT id FROM ' . db('shop_product_images') . ' WHERE product_id=' . $product['id'] . " AND md5='" . $md5 . "'");
if ( ! empty($db_item)) {
return 'Dublicate image';
}
module('manage_shop')->_product_check_first_revision('product_images', $product['id']);
$thumb_name = $this->resize_and_save_image($folder, $product['id'], $md5);
return [
'status' => 'Success',
'img' => $thumb_name,
'id' => $product['id'],
];
}
public function upload_images()
public function upload_images()
{
$SUPPLIER_ID = $this->SUPPLIER_ID;
$ADMIN_INFO = db()->query_fetch('SELECT * FROM ' . db('sys_admin') . ' WHERE id=' . (int) (main()->ADMIN_ID));
$SUPPLIER_INFO = db()->query_fetch('SELECT * FROM ' . db('shop_suppliers') . ' WHERE id=' . (int) $SUPPLIER_ID);
$post_server_path = $this->_post_server_path();
if (empty($_FILES) && empty($post_server_path)) {
if ( ! $SUPPLIER_ID) {
$suppliers = db()->get_2d('SELECT id, name FROM ' . db('shop_suppliers'));
$form = form('', ['enctype' => 'multipart/form-data'])
->file('archive')
->select_box('supplier', $suppliers, ['desc' => 'Supplier', 'show_text' => 1])
->text('server_path', 'from server path')
->save('', 'Upload');
} else {
$form = form('', ['enctype' => 'multipart/form-data'])
->file('archive')
->save('', 'Upload');
}
return $form;
}
$SUPPLIER_ID = $this->_upload_supplier_id();
$archive_name = null;
$file_type = null;
$uploaded = null;
$new_name = null;
if ($post_server_path) {
$server_path = $this->_server_path($post_server_path);
if ($server_path !== '' && file_exists($server_path) && is_readable($server_path)) {
$archive_name = $server_path;
$file_type = mime_content_type($archive_name);
$uploaded = true;
}
} else {
$file = ($_FILES['archive'] ?? null);
file_put_contents($this->ARCHIVE_FOLDER . date('d-m-Y') . '.log', "\n[" . $file['name'] . "]\n", FILE_APPEND);
$new_name = md5(rand() . microtime()) . '.' . pathinfo($file['name'], PATHINFO_EXTENSION);
rename($file['name'], $new_name);
$archive_name = $this->ARCHIVE_FOLDER . $new_name;
$file_type = $file['type'];
$uploaded = common()->upload_archive($archive_name);
}
if ( ! $uploaded) {
return js_redirect('./?object=' . ($_GET['object'] ?? null) . '&action=' . ($_GET['action'] ?? null));
}
$EXTRACT_PATH = $this->ARCHIVE_FOLDER . $SUPPLIER_ID . '_id_' . date('H_i_s');
if ( ! file_exists($EXTRACT_PATH)) {
mkdir($EXTRACT_PATH, 0777, true);
}
$full_archive_name = escapeshellarg($archive_name);
$tar = 'tar -xvf ' . $full_archive_name . ' -C ' . escapeshellarg($EXTRACT_PATH);
$gz = 'tar -xzf ' . $full_archive_name . ' -C ' . escapeshellarg($EXTRACT_PATH);
$ext = $this->_archive_ext($file_type);
if ($ext == 'rar') {
common()->rar_extract($archive_name, $EXTRACT_PATH);
}
if ($ext == 'zip') {
common()->zip_extract($archive_name, $EXTRACT_PATH);
}
if ($ext == 'tar' || $ext == 'gz') {
exec($ext == 'gz' ? $gz : $tar);
}
$result_files = _class('dir')->scan_dir($EXTRACT_PATH, true, '-f /\.(jpg|jpeg|png|gif|bmp)$/', '/__MACOSX/');
$items = null;
foreach ($result_files as $k => $v) {
$status = $this->search_product_by_filename($v, $SUPPLIER_ID);
$result = is_array($status) ? $status['status'] : $status;
$filename = str_replace($EXTRACT_PATH, '', $v);
$product_id = is_array($status) ? $status['id'] : '???';
$items[] = [
'number' => $k,
'filename' => $filename,
'status' => $result,
'image' => is_array($status) ? str_replace(PROJECT_PATH, WEB_PATH, $status['img']) : '',
'edit_url' => is_array($status) ? './?object=manage_shop&action=product_edit&id=' . $status['id'] : '',
];
$log_str = $product_id . ' | ' . $result . ' | ' . $filename . ";\n";
file_put_contents($this->ARCHIVE_FOLDER . date('d-m-Y') . '.log', $log_str, FILE_APPEND);
}
$replace = [
'items' => $items,
];
_class('dir')->delete_dir($EXTRACT_PATH, true);
$new_name && unlink($this->ARCHIVE_FOLDER . $new_name);
common()->admin_wall_add(['archive with images uploaded by ' . $SUPPLIER_INFO['name'] . ' ' . $ADMIN_INFO['first_name'] . ' ' . $ADMIN_INFO['last_name']]);
return tpl()->parse('manage_shop/upload_archive', $replace);
}
_ hooks and helpers; not routable as page actionspublic function _archive_ext($mime_type)
Archive type of a MIME type, null when it is not allowed.
public function _archive_ext($mime_type)
{
return is_string($mime_type) ? ($this->ALLOWED_MIME_TYPES[$mime_type] ?? null) : null;
}
public function _init()
public function _init()
{
$this->ARCHIVE_FOLDER = PROJECT_PATH . 'uploads/tmp/';
$this->SAVE_PATH = PROJECT_PATH . 'uploads/shop/products/';
$this->SUPPLIER_ID = (int) db()->get_one('SELECT supplier_id FROM ' . db('shop_admin_to_supplier') . ' WHERE admin_id=' . (int) (main()->ADMIN_ID));
set_time_limit(0);
}
public function _post_server_path()
Posted "from server path" value; the supplier and server path fields are only offered to an admin without an assigned supplier, so an assigned admin's post is ignored.
public function _post_server_path()
{
return $this->SUPPLIER_ID ? '' : ($_POST['server_path'] ?? '');
}
public function _server_path($path)
Archive path typed in "from server path", '' when it is refused.
public function _server_path($path)
{
if ( ! is_string($path)) {
return '';
}
$path = strip_tags(ltrim($path, ' .-_+=|,!@#%~&*();:\'"'));
if ( ! $this->CONFINE_SERVER_PATH) {
return $path;
}
// realpath() throws a ValueError on a NUL byte
$real = $path !== '' && strpos($path, "\0") === false ? realpath($path) : false;
if ($real === false || ! is_file($real)) {
return '';
}
foreach (array_merge([$this->ARCHIVE_FOLDER], (array) $this->SERVER_PATH_DIRS) as $dir) {
$real_dir = is_string($dir) && $dir !== '' && strpos($dir, "\0") === false ? realpath($dir) : false;
if ($real_dir !== false && strpos($real, rtrim($real_dir, '/') . '/') === 0) {
return $real;
}
}
return '';
}
public function _upload_supplier_id()
Supplier of an upload: the one assigned in shop_admin_to_supplier, else the posted one.
public function _upload_supplier_id()
{
if ($this->SUPPLIER_ID) {
return (int) $this->SUPPLIER_ID;
}
return (int) ($_POST['supplier'] ?? 0);
}