226 lines
8.1 KiB
Python
226 lines
8.1 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
fix_imported_k2_metas.py
|
|
|
|
Asigna metas, categorías y Polylang a los posts importados por import_new_k2_items.py.
|
|
Los posts WP ya existen (IDs 43914-44082); este script solo añade los metadatos.
|
|
|
|
Mapping: wp_id = k2_id + 26040
|
|
"""
|
|
|
|
import json
|
|
import subprocess
|
|
import sys
|
|
import re
|
|
|
|
# ── Config ─────────────────────────────────────────────────────────────────────
|
|
JOOMLA_SSH_HOST = "134.0.10.170"
|
|
JOOMLA_SSH_USER = "feadulta"
|
|
JOOMLA_SSH_PASS = "6Rm2qOF@eundwpda"
|
|
JOOMLA_DB_HOST = "127.0.0.1"
|
|
JOOMLA_DB_USER = "fejoomla3"
|
|
JOOMLA_DB_PASS = "5FF-}5^[>7^pK4W9"
|
|
JOOMLA_DB_NAME = "fejoomla3"
|
|
|
|
WP_DOCKER = "wordpress-mysql"
|
|
WP_DB_USER = "wordpress_user"
|
|
WP_DB_PASS = "wordpress_pass"
|
|
WP_DB_NAME = "wordpress_db"
|
|
|
|
LAST_K2_ID = 17873
|
|
WP_ID_OFFSET = 26040 # wp_id = k2_id + WP_ID_OFFSET
|
|
|
|
CAT_FEADULTA = 71
|
|
CAT_ARTICULOS = 1650
|
|
CAT_EVANGELIO = 1647
|
|
CAT_EUCARISTIA = 1648
|
|
LANG_MAP = {1: 'es', 2: 'en', 3: 'fr', 4: 'it', 5: 'pt'}
|
|
DOMINGO_RE = r'DOMINGO|SEMANA SANTA|SEMANA DE PASCUA|PENTECOST|NAVIDAD|EPIFAN'
|
|
|
|
DRY_RUN = '--dry-run' in sys.argv
|
|
|
|
# ── Helpers ────────────────────────────────────────────────────────────────────
|
|
|
|
def wp_execute(sql: str):
|
|
if DRY_RUN:
|
|
print(f" [DRY] {sql[:100]}")
|
|
return
|
|
cmd = ['docker', 'exec', WP_DOCKER,
|
|
'mysql', '-u', WP_DB_USER, f'-p{WP_DB_PASS}', WP_DB_NAME,
|
|
'--default-character-set=utf8mb4', '-e', sql]
|
|
result = subprocess.run(cmd, capture_output=True, text=True)
|
|
if result.returncode != 0:
|
|
err = result.stderr.replace('mysql: [Warning] Using a password on the command line interface can be insecure.\n', '')
|
|
if err.strip():
|
|
print(f" [ERR] {err.strip()[:200]}", file=sys.stderr)
|
|
|
|
|
|
def wp_mysql(query: str) -> list[dict]:
|
|
cmd = ['docker', 'exec', WP_DOCKER,
|
|
'mysql', '-u', WP_DB_USER, f'-p{WP_DB_PASS}', WP_DB_NAME,
|
|
'--default-character-set=utf8mb4', '-B', '-e', query]
|
|
result = subprocess.run(cmd, capture_output=True, text=True, encoding='utf-8')
|
|
if result.returncode != 0:
|
|
return []
|
|
lines = result.stdout.strip().split('\n')
|
|
if len(lines) < 2:
|
|
return []
|
|
headers = lines[0].split('\t')
|
|
return [dict(zip(headers, line.split('\t'))) for line in lines[1:] if line]
|
|
|
|
|
|
def esc(s: str) -> str:
|
|
return s.replace('\\', '\\\\').replace("'", "\\'")
|
|
|
|
|
|
def unhex(val: str) -> str:
|
|
if not val or val == 'NULL':
|
|
return ''
|
|
try:
|
|
return bytes.fromhex(val).decode('utf-8', errors='replace')
|
|
except Exception:
|
|
return val
|
|
|
|
|
|
def parse_extra_fields(ef_json: str) -> dict:
|
|
result = {'lang_val': None, 'has_libro': False}
|
|
if not ef_json:
|
|
return result
|
|
try:
|
|
fields = json.loads(ef_json)
|
|
except json.JSONDecodeError:
|
|
return result
|
|
for f in fields:
|
|
fid = str(f.get('id', ''))
|
|
val = f.get('value')
|
|
if fid == '16' and val is not None:
|
|
try:
|
|
result['lang_val'] = int(val)
|
|
except (ValueError, TypeError):
|
|
pass
|
|
elif fid == '9':
|
|
result['has_libro'] = True
|
|
return result
|
|
|
|
|
|
def determine_categories(ef: dict, title: str) -> list[int]:
|
|
lang = ef.get('lang_val')
|
|
es = (lang == 1 or lang is None)
|
|
cats = [CAT_FEADULTA]
|
|
if es and ef.get('has_libro'):
|
|
cats.append(CAT_EVANGELIO)
|
|
elif es and re.search(DOMINGO_RE, title, re.IGNORECASE):
|
|
cats.append(CAT_EUCARISTIA)
|
|
else:
|
|
cats.append(CAT_ARTICULOS)
|
|
return cats
|
|
|
|
|
|
# ── Main ───────────────────────────────────────────────────────────────────────
|
|
|
|
def main():
|
|
print(f"=== Fix metas/cats K2 items > {LAST_K2_ID} {'[DRY RUN]' if DRY_RUN else '[LIVE]'} ===\n")
|
|
|
|
# Cargar term_taxonomy_ids
|
|
term_ids = [CAT_FEADULTA, CAT_ARTICULOS, CAT_EVANGELIO, CAT_EUCARISTIA]
|
|
tt_ids = {}
|
|
rows = wp_mysql(f"SELECT term_id, term_taxonomy_id FROM wp_term_taxonomy WHERE term_id IN ({','.join(map(str,term_ids))}) AND taxonomy='category'")
|
|
for r in rows:
|
|
tt_ids[int(r['term_id'])] = int(r['term_taxonomy_id'])
|
|
print(f"TT IDs categorías: {tt_ids}")
|
|
|
|
pl_ids = {}
|
|
rows = wp_mysql("SELECT t.slug, tt.term_taxonomy_id FROM wp_terms t JOIN wp_term_taxonomy tt ON tt.term_id=t.term_id WHERE tt.taxonomy='language' AND t.slug IN ('es','en','fr','it','pt')")
|
|
for r in rows:
|
|
pl_ids[r['slug']] = int(r['term_taxonomy_id'])
|
|
print(f"Polylang TT IDs: {pl_ids}")
|
|
|
|
# Verificar que los WP posts existen
|
|
rows = wp_mysql(f"SELECT COUNT(*) n FROM wp_posts WHERE ID BETWEEN {LAST_K2_ID+WP_ID_OFFSET+1} AND (SELECT MAX(ID) FROM wp_posts)")
|
|
print(f"Posts WP a procesar (aprox): {rows[0]['n'] if rows else '?'}")
|
|
|
|
# Obtener K2 items desde Joomla
|
|
print("\nObteniendo K2 items de Joomla prod...")
|
|
query = (
|
|
f"SELECT id, HEX(title) title, HEX(extra_fields) extra_fields "
|
|
f"FROM ew4r_k2_items WHERE published=1 AND id > {LAST_K2_ID} ORDER BY id;"
|
|
)
|
|
mysql_cmd = (
|
|
f"mysql -h {JOOMLA_DB_HOST} -u {JOOMLA_DB_USER} "
|
|
f"-p'{JOOMLA_DB_PASS}' {JOOMLA_DB_NAME} "
|
|
f"--default-character-set=utf8mb4 -B"
|
|
)
|
|
cmd = ['sshpass', '-p', JOOMLA_SSH_PASS, 'ssh', f'{JOOMLA_SSH_USER}@{JOOMLA_SSH_HOST}', mysql_cmd]
|
|
result = subprocess.run(cmd, input=query, capture_output=True, text=True, encoding='utf-8')
|
|
if result.returncode != 0:
|
|
print(f"ERROR: {result.stderr[:300]}")
|
|
sys.exit(1)
|
|
|
|
lines = result.stdout.strip().split('\n')
|
|
headers = lines[0].split('\t')
|
|
items = [dict(zip(headers, line.split('\t'))) for line in lines[1:] if line]
|
|
print(f"Items obtenidos: {len(items)}")
|
|
|
|
stats = {'ok': 0, 'skip': 0}
|
|
|
|
for item in items:
|
|
k2_id = int(item['id'])
|
|
wp_id = k2_id + WP_ID_OFFSET
|
|
title = unhex(item.get('title', ''))
|
|
ef_raw = unhex(item.get('extra_fields', ''))
|
|
ef = parse_extra_fields(ef_raw)
|
|
lang = LANG_MAP.get(ef.get('lang_val'), 'es')
|
|
cats = determine_categories(ef, title)
|
|
|
|
# Verificar que el WP post existe
|
|
existing = wp_mysql(f"SELECT ID FROM wp_posts WHERE ID={wp_id} LIMIT 1")
|
|
if not existing:
|
|
print(f" [SKIP] WP post ID={wp_id} no encontrado (k2={k2_id})")
|
|
stats['skip'] += 1
|
|
continue
|
|
|
|
print(f" [{k2_id}→{wp_id}] {title[:45]} | lang={lang} | cats={cats}")
|
|
|
|
# Metas
|
|
for meta_key, meta_val in [('_fgj2wp_old_k2_id', str(k2_id)), ('Idioma', str(ef.get('lang_val') or 1))]:
|
|
wp_execute(
|
|
f"INSERT IGNORE INTO wp_postmeta (post_id, meta_key, meta_value) "
|
|
f"VALUES ({wp_id}, '{esc(meta_key)}', '{esc(meta_val)}')"
|
|
)
|
|
|
|
# Categorías
|
|
for term_id in cats:
|
|
tt_id = tt_ids.get(term_id)
|
|
if tt_id:
|
|
wp_execute(
|
|
f"INSERT IGNORE INTO wp_term_relationships (object_id, term_taxonomy_id) "
|
|
f"VALUES ({wp_id}, {tt_id})"
|
|
)
|
|
|
|
# Polylang
|
|
pl_tt = pl_ids.get(lang)
|
|
if pl_tt:
|
|
wp_execute(
|
|
f"INSERT IGNORE INTO wp_term_relationships (object_id, term_taxonomy_id) "
|
|
f"VALUES ({wp_id}, {pl_tt})"
|
|
)
|
|
|
|
stats['ok'] += 1
|
|
|
|
# Actualizar counts
|
|
if not DRY_RUN and stats['ok'] > 0:
|
|
print("\nActualizando counts de categorías y Polylang...")
|
|
all_tt = list(tt_ids.values()) + list(pl_ids.values())
|
|
tt_str = ','.join(str(x) for x in all_tt)
|
|
wp_execute(
|
|
f"UPDATE wp_term_taxonomy tt SET count = ("
|
|
f"SELECT COUNT(*) FROM wp_term_relationships tr WHERE tr.term_taxonomy_id=tt.term_taxonomy_id"
|
|
f") WHERE tt.term_taxonomy_id IN ({tt_str})"
|
|
)
|
|
|
|
print(f"\n=== Resultado: {stats['ok']} ok, {stats['skip']} skip ===")
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|