Uname: Linux info 3.0 #1337 SMP Tue Jan 01 00:00:00 CEST 2000 all GNU/Linux
Software: Apache
PHP version: 5.6.40 [ PHP INFO ] PHP os: Linux
Server Ip: 217.160.0.194
Your Ip: 216.73.216.115
User: u72294154 (9179942) | Group: ftpusers (600)
Safe Mode: OFF
Disable Function:
NONE

name : importador.class.php_OLD_JAGUILAR
<?php
/**
 * A partir de los XML de importación, carga los datos
 * Desarrollado a partir de las versiones anteriores, corrigiendo algunos errores, mejorando el número de consultas,
 * incluyendo el uso de una librería de conexión a la BD,...
 * 
 * @author  Víctor Velasco <v.velasco@interactivaclic.com>
 * @version 1.0,   2017-11-03
 */
class Importador {
	private $db; //Instancia de la clase Database
	private $xml;
	private $xmlFile;
	private $provsBD = array();
	private $pobsBD = array();
	private $pobAreaBD = array();
	private $tipologiasBD = array();
	private $tiposInmBD = array();
	private $zonasBD = array();
	private $trazar = true;
	private $time = 0;
	private $idAgencia = 0;
	private $gestiones = array(
		'Vender' => 1,
		'Alquilar' => 2,
		'Traspasar' => 3,
		'Vender o Alquilar' => 4,
		'Vender o Traspasar' => 5, //Añadido 8/11/2017 - Víctor Velasco
		'Temporada Alquiler' => 6, //Añadido 8/11/2017 - Víctor Velasco
		'Traspasar o Alquilar' => 7 //Añadido 8/11/2017 - Víctor Velasco
	);
	//$archivos_xml = array(XML_FILE_ASOCIACION);

	function __construct(Database $db) {
		$this->db = $db;
		$this->db->query("SET NAMES 'utf8'");
	}

	/**
	 * Carga las tablas de Inmuebles:
	 * Inmuebles, Inmuebles-Documentos e Inmuebles-Galerías
	 */
	public function inmuebles($idAgencia, $xmlFile, $trazar = true) {
		$this->tiempo();
		$this->trazar = $trazar;
		$this->idAgencia = $idAgencia;
		$this->xmlFile = $xmlFile;
		$this->xml = new XMLReader();
		$this->traza("<h1>Importación de inmuebles desde: $this->xmlFile</h1>");
		$this->importInmuebles();
		$this->tiempo(true);
	}

	private function importInmuebles() {
		//Cargo los datos auxiliares a través del gestor de Inmuebles
		$this->setDatosAuxiliares();

		$this->xml->open($this->xmlFile);
		$this->traza('<h2>Importando inmuebles...........</h2>');

		$this->vaciaInmuebles();

		/* Recorremos el xml en busca de todos los inmuebles */
		$rootElement = 'propiedades';
		$element = 'propiedad';

		$inmuebles = array();
		$total = 0;
		while ($this->xml->read()) {
			if ($this->xml->localName === $element && $this->xml->nodeType == XMLReader::ELEMENT) {
				$inmueble = simplexml_load_string($this->xml->readOuterXml(), 'SimpleXMLElement', LIBXML_NOCDATA);
				$inmueble_id = (string) $inmueble->id;
				if (empty($inmuebles[$inmueble_id])) {
					//Compruebo datos auxiliares
					$procesados = $this->compruebaInmueble($inmueble);
					if (!empty($procesados)) {
						//Proceso el inmueble y lo intento insertar
						$id_insertado = $this->procesaInmueble($inmueble, $procesados);
						if ($id_insertado !== false) {
							$inmuebles[$inmueble_id] = $id_insertado;
							$total++;
							// Galería del inmueble
							$numFotos = (int) $inmueble->numfotos;
							if ($numFotos > 0) {
								$this->procesaFotos($inmueble, $numFotos, $id_insertado);
							}
						}
					}
				}
			}
		}
		$this->traza("<p class='resumen'>Inmuebles insertados: $total</p>");
	}

	/**
	 * Carga los datos auxiliares para la validación y la carga.
	 */
	private function setDatosAuxiliares() {
		$this->provsBD = $this->loadProvincias();
		$this->pobsBD = $this->loadPoblaciones();
		$this->tiposInmBD = $this->loadTiposInmueble();
		$this->zonasBD = $this->loadZonas();
	}

	/**
	 * Comprueba que los datos relativos al inmueble que han de estar en las tablas auxiliares, están y son coherentes.
	 * Devuelve un array con lo procesado, para no repetir los cálculos.
	 * O false si no se cumplen las condiciones del inmueble.
	 */
	private function compruebaInmueble($inmueble) {
		$identificacion = empty(trim($inmueble->ref)) ? $inmueble->id : $inmueble->ref;
		//Provincia
		if (empty(trim($inmueble->provincia))) {
			$this->traza("<p class='error'>Datos erróneos en el XML. Inmueble: {$identificacion}. Dato: Provincia.</p>");
			return false;
		}
		$provincia = $this->capitaliza((string) $inmueble->provincia);
		if (empty($this->provsBD[$provincia])) {
			$this->traza("<p class='error'>Hay que actualizar la tabla de provincias. Inmueble: {$identificacion}. Provincia: {$provincia}.</p>");
			return false;
		}
		$id_provincia = $this->provsBD[$provincia];
		
		//Población
		if (empty(trim($inmueble->ciudad))) {
			$this->traza("<p class='error'>Datos erróneos en el XML. Inmueble: {$identificacion}. Dato: Población.</p>");
			return false;
		}
		$poblacion = $this->capitaliza((string) $inmueble->ciudad);
		if (empty($this->pobsBD[$poblacion]) || $this->pobsBD[$poblacion]['id_provincia'] != $id_provincia) {
			$this->traza("<p class='error'>Hay que actualizar la tabla de poblaciones. Inmueble: {$identificacion}. Población: {$poblacion}.</p>");
			return false;
		}
		$id_poblacion = $this->pobsBD[$poblacion]['id'];
		$id_area = $this->pobsBD[$poblacion]['id_area']; //Asumo que está bien la zona tal cual sale de las poblaciones

		//Tipo de Inmueble
		if (empty(trim($inmueble->tipo_ofer))) {
			$this->traza("<p class='error'>Datos erróneos en el XML. Inmueble: {$identificacion}. Dato: Tipo de Inmueble (tipo_ofer).</p>");
			return false;
		}
		$nombre_tipo_inmueble = $this->capitaliza((string) $inmueble->tipo_ofer);
		if (empty($this->tiposInmBD[$nombre_tipo_inmueble])) {
			$this->traza("<p class='error'>Hay que actualizar la tabla de Tipos de inmueble. Inmueble: {$identificacion}. Tipo de inmueble: {$nombre_tipo_inmueble}.</p>");
			return false;
		}
		$id_tipo_inmueble = $this->tiposInmBD[$nombre_tipo_inmueble]['id'];
		
		//Zona: Esta puede llegar vacía y no es error
		if (empty(trim($inmueble->zona))) {
			$this->traza("<p class='aviso'>Aviso: Falta <b>ZONA</b> en el XML. Inmueble: {$identificacion}.<br><em>*El inmueble se insertará sin zona</em></p>");
			$id_zona = 0;
			$nombre_zona = '';
		} else {
			$nombre_zona = $this->capitaliza($inmueble->zona);
			if (empty($this->zonasBD[$nombre_zona])) {
				$this->traza("<p class='error'>Hay que actualizar la tabla de Zonas. Inmueble: {$identificacion}. Zona: {$nombre_zona}.</p>");
				return false;
			}
			$id_zona = $this->zonasBD[$nombre_zona];
		}

		//Devuelvo los datos procesados, para no repetirlo
		$procesado = array(
			'nombre_provincia' => $provincia,
			'id_provincia' => $id_provincia,
			'nombre_poblacion' => $poblacion,
			'id_poblacion' => $id_poblacion,
			'id_area' => $id_area,
			'id_tipo_inmueble' => $id_tipo_inmueble,
			'nombre_tipo_inmueble' => $nombre_tipo_inmueble,
			'id_zona' => $id_zona,
			'nombre_zona' => $nombre_zona
		);
		return $procesado;
	}

	/**
	 * Para un inmueble, asocia los datos y los carga en la BD
	 */
	private function procesaInmueble($inmueble, $procesado) {
		//Datos intermedios
		$gestion = (string) $inmueble->accion;
		$id_gestion = empty($this->gestiones[$gestion]) ? 0 : $this->gestiones[$gestion];
		$tipo_mensualidad = ($id_gestion == 2 || $id_gestion == 4 || $id_gestion == 6 || $id_gestion == 7) ? 'MES' : '';
		$latitud = $this->formatCoord($inmueble->latitud);
		$longitud = $this->formatCoord($inmueble->altitud);
		$m2cons = $this->getInt($inmueble->m_cons, 2);
        $m2utiles = $this->getInt($inmueble->m_uties, 2);
        $m2sup = $this->getInt($inmueble->m_parcela, 2);
		$superficie = max($m2utiles, $m2cons);
		$habitaciones = $this->getInt($inmueble->habitaciones) + $this->getInt($inmueble->habdobles);
        if ($superficie == 0) {
        	$superficie = $m2sup;
        }
        $certificado = '';
        $certificadoRecibido = $this->getInt($inmueble->energiarecibido);
        if ($certificadoRecibido == 1) {
            $certificado = (string) $inmueble->energialetra;
        } else {
            $certificados = array(
                0 => 'PENDIENTE',
                2 => 'TRAMITES',
                3 => 'EXENTO'
            );
            $certificado = empty($certificados[$certificadoRecibido]) ? 0 : $certificados[$certificadoRecibido];
        }
        $ahora = date("Y-m-d H:i:s");

		//Datos a insertar en BD
		$data = array(
			'id' => (string) $inmueble->id,
			'id_cliente' => 0,
			'mi_agencia' => ((int) $inmueble->numagencia == $this->idAgencia) ? 1 : 0,
			'urbaniza' => 0,
			'mls' => 'inmovilla',
			'referencia_unica' => (string) $inmueble->id,
			'referencia' =>  (string) $inmueble->ref,
			'id_promocion' => 0,
			'id_pais' => 1,
			'id_provincia' => $procesado['id_provincia'],
			'id_area' => $procesado['id_area'],
			'id_poblacion' => $procesado['id_poblacion'],
			'id_zona' => $procesado['id_zona'],
			'nombre_tipo_inmueble' => $procesado['nombre_tipo_inmueble'],
			'id_tipo_inmueble' => $procesado['id_tipo_inmueble'],
			'id_tipo_via' => 0,
			'direccion_calle' => '',
			'direccion_numero' => '',
			'direccion_piso' => '',
			'direccion_letra' => '',
			'direccion_escalera' => '',
			'cp' => (string) $inmueble->cp,
			'id_gestion' => $id_gestion,
			'precio_venta' => ((int) $inmueble->precioinmo > 0 ? $this->getInt($inmueble->precioinmo, 2) : 0),
			'precio_alquiler' => ((int) $inmueble->precioalq > 0 ? $this->getInt($inmueble->precioalq, 2) : 0),
			'precio_anterior' => ((int) $inmueble->outlet > 0 ? $this->getInt($inmueble->outlet, 2) : 0),
			'tipo_mensualidad' => $tipo_mensualidad,
			'habitaciones' => $habitaciones,
			'banos' => (string) $inmueble->banyos,
			'aseos' => (string) $inmueble->aseos,
			'superficie' => $superficie,
			'superficie_util' => $m2utiles,
			'superficie_construida' => $m2cons,
			'superficie_terreno' => $m2sup,
			'latitud' => $latitud,
			'longitud' => $longitud,
			'map_point' => "Point($latitud , $longitud)",
			'nuevo' => ((!empty($inmueble->conservacion) && (int) $inmueble->conservacion[1] > 60) ? 1 : 0),
			'garaje' => (string) $inmueble->plaza_gara,
			'calefaccion' => (string) $inmueble->calefaccion,
			'aire_acondicionado' => (string) $inmueble->aire_con,
			'piscina' => (intval((string) $inmueble->piscina_prop) == 0 ? (intval((string) $inmueble->piscina_com) == 0 ? 0 : 1) : 1),
			'jardin' => ((int) $inmueble->jardin > 0 ? (string) $inmueble->jardin : 0),
			'trastero' => (string) $inmueble->trastero,
			'ascensor' => (string) $inmueble->ascensor,
			'terraza' => (string) $inmueble->terraza,
			'descripcion' => (string) $inmueble->descrip1,
			'anyo_construccion' => 0,
			'observaciones' => '',
			'activa' => 1,
			'banco' => (int) $inmueble->entidadbancaria,
			'eficiencia_energetica' => $certificado,
			'reservado' => 0,
			'destacado' => (int) $inmueble->destacado,
			'visitas' => 0,
			'nfotos' => (int) $inmueble->numfotos,
			'cod_ofer' => (string) $inmueble->cod_ofer,
			'estadoficha' => (int) $inmueble->estadoficha,
			'keyacci' => (int) $inmueble->keyacci,
			'numsucursal' => ((int) $inmueble->numsucursal > 0 ? (string) $inmueble->numsucursal : null),
			'url' => $this->getUrlInmueble(
				$procesado['nombre_tipo_inmueble'], 
				$procesado['nombre_zona'], 
				$procesado['nombre_poblacion'], 
				$procesado['nombre_provincia'], 
				$habitaciones, 
				(string) $inmueble->ref
			),
			'created' => $ahora,
			'modified' => $ahora
		);

		//Preparo los datos para inserción
		$campos = array();
		$valores = array();
        foreach ($data as $indice => $valor) {
        	$campos[] = $indice;
        	$valores[] = ($indice == 'map_point') ? $valor : $this->db->quote($valor);
        }
        $c = implode(',', $campos);
        $v = implode(',', $valores);
        $sql = "INSERT INTO inmuebles ($c) VALUES ($v)";
        if ($this->db->query($sql)) {
        	return $this->db->insert_id();
        } else {
        	$error = $this->db->error();
        	$this->traza("<p class='error'>Error insertando inmueble {$inmueble->ref}. | <code>{$sql}</code> | Error: {$error}</p>");
        	return false;
        }
	}

	/**
	 * Recorre el listado de fotos y lo inserta en la tabla de inmuebles_galeria
	 */
	private function procesaFotos($inmueble, $numFotos, $id_insertado) {
		for ($i = 1; $i <= $numFotos; $i++) {
			$principal = ($i == 1) ? 1 : 0;
			$nodoFoto = "foto{$i}";
			$url = (string) $inmueble->$nodoFoto;
			$sql = "INSERT INTO inmuebles_galeria (id_inmueble,tipo,imagen,descripcion,url,principal,orden) VALUES ('$id_insertado','imagen','','','$url','$principal','$i')";
			if (!$this->db->query($sql)) {
				$this->traza("<p class='error'>Error insertando imagen {$i} del inmueble con id {$id_insertado}.</p>");
			}
		}
	}

	/**
	 * Formatea coordenadas (latitud, longitud)
	 */
	private function formatCoord($x) {
		return preg_replace('/([^0-9\.\-]+)/', '', str_replace(':', '', trim((string) $x)));
	}


	/**
	 * Genera la URL del inmueble concatenando los datos recibidos
	 */
	function getUrlInmueble($nombre_tipo_inmueble, $nombre_zona, $nombre_poblacion, $nombre_provincia, $habitaciones, $referencia) {
	    $url = '';
	    $temp = array();
        $temp[] = $nombre_tipo_inmueble;
	    if (!empty($nombre_zona)) {
	        $temp[] = $nombre_zona;
	    }
        $temp[] = $nombre_poblacion;
        $temp[] = $nombre_provincia;

	    if (!empty($habitaciones) || $habitaciones != 0) {
	        $temp[] = $habitaciones . '-habitacion' . (($habitaciones > 1) ? 'es' : '');
	    }
	    $url .= implode('-', $temp);

	    if (!empty($referencia)) {
	        $url .= '_' . format_url($referencia);
	    }

	    return '/' . $this->getSlug($url);
	}

	/**
	 * Vacio: Inmuebles, Inmuebles-Documentos e Inmuebles-Galerías
	 */
	private function vaciaInmuebles() {
		if (!$this->db->query('DELETE FROM inmuebles')) {
			$this->traza('<p class="error">No se ha podido vaciar la tabla de inmuebles</p>');
		}
		if (!$this->db->query('DELETE FROM inmuebles_documentos')) {
			$this->traza('<p class="error">No se ha podido vaciar la tabla de inmuebles_documentos</p>');
		}
		if (!$this->db->query('DELETE FROM inmuebles_galeria')) {
			$this->traza('<p class="error">No se ha podido vaciar la tabla de inmuebles_galeria</p>');
		}
	}

	/**
	 * Prepara la carga de las tablas auxiliares:
	 * Provincias, Poblaciones, Zonas y Tipos de Inmueble
	 */
	public function auxiliares($xmlFile, $trazar = true) {
		$this->tiempo();
		$this->trazar = $trazar;
		$this->xmlFile = $xmlFile;
		$this->xml = new XMLReader();
		$this->traza("<h1>Importación de tablas auxiliares desde: $this->xmlFile</h1>");
		$this->importAuxiliares();
		$this->tiempo(true);
	}

	/**
	 * Los 4 procesos de importación:
	 * carga las tablas de Provincias, Poblaciones, Zonas y Tipos de Inmueble
	 */
	private function importAuxiliares() {
		//1.- Cargo y actualizo las provincias
		$this->provsBD = $this->importProvincias();

		//2.1.- Cargo las áreas de las poblaciones 
		$this->pobAreaBD = $this->loadAreas();
		
		//2.2.- Para cargar y actualizar las poblaciones, necesito asegurarme de que tengo áreas
		if (!empty($this->pobAreaBD)) {
			$this->pobsBD = $this->importPoblaciones();
		} else {
			$this->traza('<p>No se pueden importar las poblaciones porque no se han cargado sus áreas');
		}
		
		//3.- Borro y creo las zonas
		$this->importZonas();

		//4.1.- Cargo las tipologías para los tipos de inmueble 
		$this->tipologiasBD = $this->loadTipologias();
		//4.2.- Cargo los tipos de Inmueble
		$this->importTiposDeInmueble();

	}

	/**
	 * Introduce en la Base de Datos, las poblaciones que no están introducidas ya.
	 * Fuerza el valor del país a 1.
	 * A día de hoy (3/11/2017), el id_pais no se usa para nada.
	 * Devuelve un array con las provincias en mayúsculas como índice y el id como valor:
	 * 		$provsBD = array(
	 * 			'CANTABRIA' => 1,
	 * 			'BURGOS' => 2,
	 * 			...
	 * 		)
	 * 	Este array incluye los datos que existían originalmente, más los cargados en esta ejecución.
	 */
	public function importProvincias() {
		$this->xml->open($this->xmlFile);
		$this->traza('<h2>Actualizando  provincias...........</h2>');

		//Cargo las provincias que ya tengo
		$provsBD = $this->loadProvincias();

		//En este array meteré las provincias que falten en la tabla "provincias"
		$provincias = array();
		/* Recorremos el xml en busca de todas las provincias */
		$rootElement = 'propiedades';
		$element = 'propiedad';
		while ($this->xml->read()) {
			if ($this->xml->localName == $element && $this->xml->nodeType == XMLReader::ELEMENT) {
				$inmueble = simplexml_load_string($this->xml->readOuterXml(), 'SimpleXMLElement', LIBXML_NOCDATA);
				$nombre = $this->capitaliza((string) $inmueble->provincia);
				if (empty($provsBD[$nombre]) && empty($provincias[$nombre])) {
					$provincias[$nombre] = $nombre;
				}
			}
		}

		$total = 0;
		//Recorro el array de $provincias (las que faltan en la BD) y:
		//	- Las inserto en BD
		//	- Las añado al rray 
		if (!empty($provincias)) {
			foreach ($provincias as $provincia) {
				$sql = "INSERT INTO provincias (nombre,id_pais) VALUES ('{$provincia}', 1)";
				if ($this->db->query($sql)) {
					$this->traza("<p>Se ha insertado: <em>{$provincia}</em></p>");
					$total++;
					//Lo añado al array
					$provsBD[$provincia] = $this->db->insert_id();
				} else {
					$this->traza("<p>Se ha producido un error al insertar: <em>{$provincia}</em> | <code>{$sql}</code></p>");
				}
			}
		}

		$this->traza("<p class='resumen'>Provincias insertadas: $total</p>");
		return $provsBD;
	}

	/**
	 * Carga las provincias de la BD
	 */
	private function loadProvincias() {
		$provsBD = array();
		$resProvs = $this->db->query('SELECT id, nombre FROM provincias');
		if ($resProvs) {
			while ($rowProvs = $this->db->fetch($resProvs)) {
				$provsBD[$this->capitaliza($rowProvs['nombre'])] = $rowProvs['id'];
			}
		}
		return $provsBD;
	}

	/**
	 * Carga las provincias de la BD
	 * OJO: Si en el futuro hubiera diferentes poblaciones con el mismo nombre, tal como está hecho, fallaría
	 */
	private function loadPoblaciones() {
		$pobsBD = array();
		$resPobs = $this->db->query('SELECT * FROM poblaciones');
		if ($resPobs) {
			while ($rowPobs = $this->db->fetch($resPobs)) {
				$pobsBD[$this->capitaliza($rowPobs['nombre'])] = array(
					'id' => $rowPobs['id'],
					'id_provincia' => $rowPobs['id_provincia'],
					'id_area' => $rowPobs['id_area'],
					'nombre' => $rowPobs['nombre'],
				);
			}
		}
		return $pobsBD;
	}

	/**
	 * Carga los tipos de inmueble de la BD
	 */
	private function loadTiposInmueble() {
		$tiposInmBD = array();
		$resTipos = $this->db->query('SELECT id, tipo_id, nombre FROM tipos_inmueble');
		if ($resTipos) {
			while ($rowTipos = $this->db->fetch($resTipos)) {
				$tiposInmBD[$this->capitaliza($rowTipos['nombre'])] = array(
					'id' => $rowTipos['id'],
					'tipo_id' => $rowTipos['tipo_id'] //La tipología
				);
			}
		}
		return $tiposInmBD;
	}

	/**
	 * Carga las zonas de la BD
	 */
	private function loadZonas() {
		$zonasBD = array();
		$resZonas = $this->db->query('SELECT id, nombre FROM zonas');
		if ($resZonas) {
			while ($rowZonas = $this->db->fetch($resZonas)) {
				$zonasBD[$this->capitaliza($rowZonas['nombre'])] = $rowZonas['id'];
			}
		}
		return $zonasBD;
	}


	/**
	 * En la tabla "areas" están relacionadas las distintas áreas con los 
	 * id's de las poblaciones (valor "ciudad" en el XML) de Inmovilla.
	 * Por ejemplo: La zona "Santander", está relacionada con 15099 (Santander), 952599 (Boo de Piélagos), etc.
	 *
	 * Aquí preparo un array que asocia el id de Inmovilla de una población, con el id de área de nuestra BD.
	 * Ejemplo:
	 * 		idPobArea = array(
	 * 			'15099' => 3,
	 * 			'952599' => 3,
	 * 			...
	 * 		)
	 *
	 * Este array relacional es el que se devuelve.
	 * Se utilizará para cargar las poblaciones informando del área a la que pertenece cada una.
	 */
	private function loadAreas() {
		$idPobArea = array();

		//Cargo las áreas
		$sqlAreas = 'SELECT id, nombre, localidades FROM areas';
		$resAreas = $this->db->query($sqlAreas);
		while ($rowAreas = $this->db->fetch($resAreas)) {
			//$provsBD[$this->capitaliza($rowAreas['nombre'])] = $rowAreas['id'];
			if (!empty($rowAreas['localidades'])) {
				$idsPoblaciones = unserialize($rowAreas['localidades']);
				$idArea = $rowAreas['id'];
				foreach ($idsPoblaciones as $idPob) {
					$idPobArea[$idPob] = $idArea;
				}
			}
		}

		return $idPobArea;
	}

	/**
	 * Carga las poblaciones que existen en la BD.
	 * Lee el XML e inserta o actualiza los datos de la BD: comprueba la capitalización de los nombres y el id_area
	 * Devuelve un array con las poblaciones con el formato:
	 * 		$pobsBD = array(
	 * 			'Santander' => array(
	 * 				'id' => 3,
	 * 				'id_provincia' => 1,
	 * 				'id_area' => 3,
	 * 				'nombre' => 'Santander',
	 * 				'provincia' => Cantabria
	 * 			),
	 * 			...
	 * 		)
	 * 		
	 * OJO: Si en el futuro hubiera diferentes poblaciones con el mismo nombre, tal como está hecho, fallaría
	 */
	public function importPoblaciones() {
		$pobsBD = array();
		$pobsNuevas = array();
		$actualizarPobs = false;

		$this->xml->open($this->xmlFile);
		$this->traza('<h2>Actualizando poblaciones...........</h2>');
		
		// Cargo las poblaciones que ya tengo y compruebo si se han de actualizar
		$resPobs = $this->db->query('SELECT * FROM poblaciones');
		if ($resPobs) {
			while ($rowPobs = $this->db->fetch($resPobs)) {
				$nombreCap = $this->capitaliza($rowPobs['nombre']);
				$actualizar = false;
				$id = $rowPobs['id'];
				$nombre = trim($rowPobs['nombre']);
				if ($nombre != $this->capitaliza($nombre)) {
					//Si el nombre no está bien capitalizado, debo actualizar este campo
					$actualizar = true;
					$actualizarPobs = true;
					$nombre = $this->capitaliza($nombre);
				}
				
				$pobsBD[$nombreCap] = array(
					'id' => $id,
					'id_provincia' => $rowPobs['id_provincia'],
					'id_area' => $rowPobs['id_area'],
					'nombre' => $nombre,
					'actualizar' => $actualizar
				);
			}
		}

		// Recorremos el xml en busca de todas las poblaciones que no tenga cargadas
		// También compruebo que los id_area coinciden con lo que tengo cargado
		$rootElement = 'propiedades';
		$element = 'propiedad';
		while ($this->xml->read()) {
			if ($this->xml->localName == $element && $this->xml->nodeType == XMLReader::ELEMENT) {
				$inmueble = simplexml_load_string($this->xml->readOuterXml(), 'SimpleXMLElement', LIBXML_NOCDATA);
				$nombrePob = $this->capitaliza((string) $inmueble->ciudad);
				$idPobApi = (int) $inmueble->key_loca;

				//Si no la tengo ya cargada o en la lista de nuevas, la añado
				if (empty($pobsBD[$nombrePob]) && empty($pobsNuevas[$nombrePob])) {
					$nombreProv = $this->capitaliza((string) $inmueble->provincia);
					$idArea = empty($this->pobAreaBD[$idPobApi]) ? 0 : $this->pobAreaBD[$idPobApi];
					$pobsNuevas[$nombrePob] = array(
						'id' => null,
						'id_provincia' => $this->provsBD[$nombreProv],
						'id_area' => $idArea,
						'nombre' => $nombrePob,
						'actualizar' => false
					);
					$pobsBD[$nombrePob] = array(
						'id' => 0,//Lo definiré tras la inserción
						'id_provincia' => $this->provsBD[$nombreProv],
						'id_area' => $idArea,
						'nombre' => $nombrePob,
						'actualizar' => false
					); 
				} elseif ( 
					(empty($this->pobAreaBD[$idPobApi]) && $pobsBD[$nombrePob]['id_area'] != 0) ||
					(!empty($this->pobAreaBD[$idPobApi]) && $pobsBD[$nombrePob]['id_area'] != $this->pobAreaBD[$idPobApi])
						 ) {
						//Si el id_area no es el que corresponde, debo actualizar este campo en la BD
						$actualizarPobs = true;
						$id_area = empty($this->pobAreaBD[$id]) ? 0 : $this->pobAreaBD[$id];
						$pobsBD[$nombrePob]['id_area'] = empty($this->pobAreaBD[$idPobApi]) ? 0 : $this->pobAreaBD[$idPobApi];
						$pobsBD[$nombrePob]['actualizar'] = true;
				}
			}
		}

		//Inserciones: Nuevas poblaciones a la BD
		$total = 0;
		if (!empty($pobsNuevas)) {
			foreach ($pobsNuevas as $pob) {
				$sql = "INSERT INTO poblaciones (id_provincia,id_area,nombre) VALUES ({$pob['id_provincia']},{$pob['id_area']},'{$pob['nombre']}')";
				if ($this->db->query($sql)) {
					$this->traza("<p>Se ha insertado: <em>{$pob['nombre']}</em></p>");
					$total++;
					$pobsBD[$pob['nombre']]['id'] = $this->db->insert_id();
				} else {
					$this->traza("<p>Se ha producido un error al insertar: <em>{$pob['nombre']}</em>. | <code>{$sql}</code></p>");
				}
			}
		}
		$this->traza("<p class='resumen'>Poblaciones insertadas: $total</p>");

		//Actualizaciones: Hay datos obsoletos que hay que actualizar (por capitalización del nombre o por la asociación con área)
		$total = 0;
		if ($actualizarPobs) {
			foreach ($pobsBD as $pob) {
				if ($pob['actualizar']) {
					$sql = "UPDATE poblaciones SET id_area = {$pob['id_area']}, nombre = '{$pob['nombre']}' WHERE id = {$pob['id']}";
					if ($this->db->query($sql)) {
						$this->traza("<p>Se ha actualizado: <em>{$pob['nombre']}</em></p>");
						$total++;
						$pob['actualizar'] = false;
					} else {
						$this->traza("<p>Se ha producido un error al actualizar: <em>{$pob['nombre']}</em>. | <code>{$sql}</code></p>");
					}
				}
			}
		}
		$this->traza("<p class='resumen'>Poblaciones actualizadas: $total</p>");

		return $pobsBD;
	}

	/**
	 * Vacía las zonas y las recrea
	 */
	public function importZonas() {
		$zonas = array();

		$this->xml->open($this->xmlFile);
		$this->traza('<h2>Actualizando zonas...........</h2>');

		//Vacío las zonas
		if (!$this->db->query('DELETE FROM zonas')) {
			$this->traza('<p class="error">No se ha podido vaciar la tabla de zonas</p>');
		}


		// Busco las zonas en el XML
		$rootElement = 'propiedades';
		$element = 'propiedad';
		while ($this->xml->read()) {
			if ($this->xml->localName == $element && $this->xml->nodeType == XMLReader::ELEMENT) {
				$inmueble = simplexml_load_string($this->xml->readOuterXml(), 'SimpleXMLElement', LIBXML_NOCDATA);
				$nombre = $this->capitaliza((string) $inmueble->zona);
				$poblacion = $this->capitaliza((string) $inmueble->ciudad);
				$id_poblacion = $this->pobsBD[$poblacion]['id'];
				if (!empty($nombre) && (empty($zonas[$nombre]) || (!empty($zonas[$nombre]) && $zonas[$nombre]['id_poblacion'] != $id_poblacion))) {
					//Si no existe la zona en esa población, la añado a la lista
					$zonas[$nombre] = array(
						'nombre' => $nombre,
						'id_poblacion' => $this->pobsBD[$poblacion]['id']
					);
				}
			}
		}

		$total = 0;
		if (!empty($zonas)) {
			$total = 0;
			foreach ($zonas as $zona) {
				$sql = "INSERT INTO zonas (id_poblacion,nombre) VALUES ({$zona['id_poblacion']},'{$zona['nombre']}')";
				if ($this->db->query($sql)) {
					$this->traza("<p>Se ha insertado: <em>{$zona['nombre']}</em></p>");
					$total++;
				} else {
					$this->traza("<p class='error'>Se ha producido un error al insertar: <em>{$zona['nombre']}</em>. | <code>{$sql}</code></p>");
				}
			}
		}
		$this->traza("<p class='resumen'>Zonas insertadas: $total</p>");

		return $zonas; 
	}

	/**
	 * La tabla "tipologias" agrupo en una categoría superior, los tipos de inmueble.
	 * Para mantener esta relación, cada tipología contiene un array serializado con los 
	 * id's de los tipos (valor "key_tipo" en el XML) de Inmovilla.
	 * Por ejemplo: los tipos de inmueble "Casa", "Casa de Campo", "Casa de Pueblo",... pertenecen a la tipología "Casa".
	 * 
	 * Aquí preparo un array que asocia el id de Inmovilla de un tipo de inmueble, con el id de la Tipología de nuestra BD.
	 * Ejemplo:
	 * 		idTipoInmueble = array(
	 * 			'199' => 8,
	 * 			'499' => 8,
	 * 			...
	 * 		)
	 *
	 * Este array relacional es el que se devuelve.
	 * Se utilizará para cargar los tipos de inmueble informando de la tipología a la que pertenece cada uno.
	 */
	private function loadTipologias() {
		//tipo_ofer
		$idTipoInmueble = array();

		//Cargo las áreas
		$sqlTipologias = 'SELECT id, nombre, tipos FROM tipologias';
		$resTipologias = $this->db->query($sqlTipologias);
		while ($rowTipologias = $this->db->fetch($resTipologias)) {
			if (!empty($rowTipologias['tipos'])) {
				$idsTiposInm = unserialize($rowTipologias['tipos']);
				$idTipologia = (int) $rowTipologias['id'];
				foreach ($idsTiposInm as $tipoInmueble) {
					$idTipoInmueble[$tipoInmueble] = $idTipologia;
				}
			}
		}

		return $idTipoInmueble;
	}

	/**
	 * Vacía los tipos de Inmueble y los recrea
	 */
	public function importTiposDeInmueble() {
		$tipos_inmueble = array();

		$this->xml->open($this->xmlFile);
		$this->traza('<h2>Actualizando tipos_inmueble...........</h2>');

		//Vacío los tipos de inmueble
		if (!$this->db->query('DELETE FROM tipos_inmueble')) {
			$this->traza('<p class="error">No se ha podido vaciar la tabla de tipos de inmueble</p>');
		}

		/* Recorremos el xml en busca de todos los tipos_inmueble */
		$rootElement = 'propiedades';
		$element = 'propiedad';
		while ($this->xml->read()) {
			if ($this->xml->localName == $element && $this->xml->nodeType == XMLReader::ELEMENT) {
				$inmueble = simplexml_load_string($this->xml->readOuterXml(), 'SimpleXMLElement', LIBXML_NOCDATA);
				if (!empty($inmueble->tipo_ofer) && !empty($inmueble->key_tipo)) {
					$nombreTipoInmueble = $this->capitaliza((string) $inmueble->tipo_ofer);
					if (empty($tipos_inmueble[$nombreTipoInmueble])) {
						$slug = $this->getSlug($nombreTipoInmueble);
						$inmovilla_id = (int) $inmueble->key_tipo;
						$tipologia_id = empty($this->tipologiasBD[$inmovilla_id]) ? 0 : $this->tipologiasBD[$inmovilla_id];
						$tipos_inmueble[$nombreTipoInmueble] = array(
							'tipo_id' => $tipologia_id,
							'nombre' => $nombreTipoInmueble,
							'seo' => $slug,
							'inmovilla_id' => $inmovilla_id,
						);
					}
				} else {
					$this->traza("<p class='error'>Error XML en {$inmueble}</p>");
				}
			}
		}

		$total = 0;
		if (!empty($tipos_inmueble)) {
			foreach ($tipos_inmueble as $t) {
				$sql = "INSERT INTO tipos_inmueble (tipo_id, nombre, seo, inmovilla_id) VALUES ({$t['tipo_id']}, '{$t['nombre']}', '{$t['seo']}', {$t['inmovilla_id']})";
				if ($this->db->query($sql)) {
					$this->traza("<p>Se ha insertado: <em>{$t['nombre']}</em></p>");
					$total++;
				} else {
					$this->traza("<p class='error'>Se ha producido un error al insertar: <em>{$t['nombre']}</em>. | <code>{$sql}</code></p>");
				}
			}
		}
		$this->traza("<p class='resumen'>Tipos de inmueble insertados: $total</p>");
	}


	private function getSlug($texto, $spacer = '-') {
		$slug = trim($texto);
	    $slug = str_replace(array("á","à","ä","Á","À","Ä","ª"),"a",$slug);
	    $slug = str_replace(array("é","è","ë","É","È","Ë"),"e",$slug);
	    $slug = str_replace(array("í","ì","ï","Í","Ì","Ï"),"i",$slug);
	    $slug = str_replace(array("ó","ò","ö","Ó","Ò","Ö","º"),"o",$slug);
	    $slug = str_replace(array("ú","ù","ü","Ú","Ù","Ü"),"u",$slug);
	    $slug = str_replace(array("ñ","Ñ"),"n",$slug);
	    $slug = str_replace(array('"',"'","´","`"),'',$slug);
	    $slug = str_replace(array(",",".",";","¡","!","¿","?","(",")","/","\\"),$spacer,$slug);
	    $slug = str_replace(array("ç","Ç"),"c",$slug);
		$slug = preg_replace("/[ \t\n\r]+/", $spacer, $slug);
		$slug = preg_replace("/^[¡¿-]+/", "", $slug);
		$slug = preg_replace("/[?!-]+$/", "", $slug);
		$slug = str_replace(" ", $spacer, $slug);
		$slug = str_replace(array("[","]"), "", $slug);
		$slug = preg_replace("/[ -]+/", $spacer, $slug);
		$slug = strtolower($slug);
		return $slug; 
	}

	/**
	 * Cada primera letra en mayúsculas.
	 * Uso esta función en conjunción con encode porque ucwords() no da el resultado deseado.
	 */
	private function capitaliza($valor) {
		return mb_convert_case($this->limpiaErrores(trim($valor)), MB_CASE_TITLE);
	}

	/**
	 * Elimino o sustituyo caracteres que veo que recurrentemente llegan erroneos
	 */
	private function limpiaErrores($valor) {
		$valor = str_replace(
				array('ä', 'â', 'Â', 'Ä'),
				array('a', 'a', 'A', 'A'),
				$valor
		);
		$valor = str_replace(
				array('ë', 'ê','Ê', 'Ë'),
				array('e', 'e','E', 'E'),
				$valor
		);
		$valor = str_replace(
				array('î', 'Î'),
				array('i', 'I'),
				$valor
		);
		$valor = str_replace(
				array('ã', 'ö', 'ô', 'Ã', 'Ö', 'Ô'),
				array('ó', 'o', 'o', 'Ó', 'O', 'O'),
				$valor
		);
		$valor = str_replace(
				array('ü', 'û', 'Û', 'Ü'),
				array('u', 'u', 'U', 'U'),
				$valor
		);
		$valor = str_replace('*', '', $valor);

		return $valor;
	}

	/**
	 * Extraigo el valor entero de un nodo.
	 * Compruebo que esté dentro del rango de enteros de MySQL.
	 * Si se sale, devuelvo 0 porque considero que es un dato erroneo.
	 * Si no tiene decimales: 
	 * 		Valor máximo para un entero de 10m posiciones con signo en MySQL: -2147483648 / +2147483647
	 * Si tiene decimales, 10 posiciones rellenas de "9" a las que quito las posiciones decimales
	 * 		Ejemplo con 2 decimales: 99999999.99
	 */
	private function getInt($valor, $decimalesCampo = 0) {
		$v = intval(trim((string) $valor));
		if ($decimalesCampo == 0) {
			if ($v > 2147483647 || $v < -2147483648) {
				return 0;
			}
		} else {
			$max = 9999999999 / pow(10, $decimalesCampo);
			if ($v >= $max || $v <= -($max-1)) {
				return 0;
			}
		}
		return $v;
	}

	/**
	 * Si está establecido que hay trazas, imprimo el mensaje que recibo en el documento.
	 */
	public function traza($html) {
		if ($this->trazar) {
			echo $html;
		}
	}

	/**
	 * Mide el tiempo de un proceso.
	 * Al llamarlo con false, marca el inicio.
	 * Al llamarlo con true, marca el fin y lo imprime.
	 */
	private function tiempo($fin = false) {
		if (!$fin) {
			//Inicio
			$this->time = microtime(true);
		} else {
			//Fin
			$time_end = microtime(true);
			$duration = $time_end - $this->time;
			$mm = (int) ($duration / 60);
			$ss = (int) $duration - $mm * 60;
			$this->traza("<p class='tiempo'>Duración del proceso: {$mm} minutos, {$ss} segundos.</p>");
		}
	}
}

?>
© 2026 GrazzMean