118 lines
4.2 KiB
Python
118 lines
4.2 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""Переносит картинки из архива Bitrix в media/ нового проекта и генерит seed_media.sql."""
|
|
import sqlread, io, os, zipfile
|
|
|
|
P = 'db.sql'
|
|
ZIP = r'C:\Users\naym4\Downloads\public_html.zip'
|
|
MEDIA_DIR = r'D:\dana\media'
|
|
OUT = io.open('seed_media.sql', 'w', encoding='utf-8')
|
|
|
|
MIME = {'.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.png': 'image/png',
|
|
'.gif': 'image/gif', '.svg': 'image/svg+xml', '.webp': 'image/webp',
|
|
'.pdf': 'application/pdf'}
|
|
|
|
def esc(s):
|
|
return "'" + str(s or '').replace("\\", "\\\\").replace("'", "''") + "'"
|
|
|
|
# --- b_file: id -> (subdir, name, ctype, size, w, h, original) ---
|
|
files = {}
|
|
for r in sqlread.rows(P, 'b_file'):
|
|
files[r['ID']] = r
|
|
|
|
# --- свойство ICON (344) услуг: element_id -> file_id ---
|
|
icon_of = {}
|
|
for r in sqlread.rows(P, 'b_iblock_element_property'):
|
|
if r.get('IBLOCK_PROPERTY_ID') == '344' and r.get('VALUE'):
|
|
icon_of[r['IBLOCK_ELEMENT_ID']] = r['VALUE']
|
|
|
|
# какие элементы каких инфоблоков и какое поле-картинка использовать
|
|
# (iblock, поле-приоритет, целевая таблица, целевая колонка)
|
|
PLAN = [
|
|
('29', ['PREVIEW_PICTURE', 'DETAIL_PICTURE'], 'doctors', 'photo_id'),
|
|
('30', ['PREVIEW_PICTURE', 'DETAIL_PICTURE'], 'services', 'image_id'),
|
|
('50', ['PREVIEW_PICTURE', 'DETAIL_PICTURE'], 'checkups', 'image_id'),
|
|
]
|
|
|
|
zf = zipfile.ZipFile(ZIP)
|
|
zip_names = set(zf.namelist())
|
|
extracted = {} # file_id -> web path
|
|
skipped = 0
|
|
|
|
def ensure(file_id):
|
|
"""Извлечь файл из архива, вернуть web-путь или None."""
|
|
if file_id in extracted:
|
|
return extracted[file_id]
|
|
f = files.get(file_id)
|
|
if not f:
|
|
return None
|
|
subdir = (f.get('SUBDIR') or '').strip()
|
|
name = (f.get('FILE_NAME') or '').strip()
|
|
if not subdir or not name:
|
|
return None
|
|
arc = 'public_html/upload/%s/%s' % (subdir, name)
|
|
if arc not in zip_names:
|
|
return None
|
|
dest_dir = os.path.join(MEDIA_DIR, subdir.replace('/', os.sep))
|
|
os.makedirs(dest_dir, exist_ok=True)
|
|
with zf.open(arc) as src, open(os.path.join(dest_dir, name), 'wb') as dst:
|
|
dst.write(src.read())
|
|
web = '/media/%s/%s' % (subdir, name)
|
|
extracted[file_id] = web
|
|
return web
|
|
|
|
OUT.write('-- Картинки из архива Bitrix. Пути ссылаются на файлы в D:\\dana\\media\n')
|
|
OUT.write('BEGIN;\n\n')
|
|
|
|
def emit_media(file_id, web, alt):
|
|
f = files[file_id]
|
|
ext = os.path.splitext(web)[1].lower()
|
|
mime = MIME.get(ext, f.get('CONTENT_TYPE') or 'application/octet-stream')
|
|
if mime == 'application/octet-stream' and ext in MIME:
|
|
mime = MIME[ext]
|
|
w = f.get('WIDTH') or '0'
|
|
h = f.get('HEIGHT') or '0'
|
|
size = f.get('FILE_SIZE') or '0'
|
|
OUT.write(
|
|
"INSERT INTO media (path, mime, size, width, height, alt) VALUES (%s,%s,%s,%s,%s,%s) "
|
|
"ON CONFLICT (path) DO NOTHING;\n" % (
|
|
esc(web), esc(mime), size, w if w != '' else '0', h if h != '' else '0', esc(alt)))
|
|
|
|
count = {}
|
|
for ibid, fields, table, col in PLAN:
|
|
c = 0
|
|
for r in sqlread.rows(P, 'b_iblock_element'):
|
|
if r['IBLOCK_ID'] != ibid or r.get('ACTIVE') != 'Y':
|
|
continue
|
|
fid = None
|
|
for fld in fields:
|
|
if r.get(fld) and r[fld] in files:
|
|
fid = r[fld]
|
|
break
|
|
if not fid:
|
|
continue
|
|
web = ensure(fid)
|
|
if not web:
|
|
continue
|
|
alt = (r.get('NAME') or '').strip()
|
|
emit_media(fid, web, alt)
|
|
OUT.write(
|
|
"UPDATE %s SET %s = (SELECT id FROM media WHERE path=%s) WHERE legacy_id=%s;\n" % (
|
|
table, col, esc(web), r['ID']))
|
|
c += 1
|
|
count[table] = c
|
|
|
|
# --- SVG-иконки услуг ---
|
|
icons = 0
|
|
for eid, fid in icon_of.items():
|
|
web = ensure(fid)
|
|
if not web:
|
|
continue
|
|
emit_media(fid, web, '')
|
|
OUT.write("UPDATE services SET icon = %s WHERE legacy_id=%s;\n" % (esc(web), eid))
|
|
icons += 1
|
|
|
|
OUT.write('\nCOMMIT;\n')
|
|
OUT.close()
|
|
print('extracted files:', len(extracted))
|
|
print('links:', count, 'icons:', icons)
|