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.55
User: u72294154 (9179942) | Group: ftpusers (600)
Safe Mode: OFF
Disable Function:
NONE

name : importador.class.php
<?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 inmueblesRun($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->vaciaInmuebles();
		$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 = 'Inmuebles';
		$element = 'Inmueble';

		$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_inmueble;
				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) count($inmueble->fotos->foto);
							if ($numFotos > 0) {
								$this->procesaFotos($inmueble, $numFotos, $id_insertado);
							}
						}
					}
				}
			}
		}
		$this->traza("<p class='resumen'>Inmuebles insertados: $total</p>");



		// AGRUPACION DE VIVIENDAS
		// 1 Cargo el tipo Casas. | Casas -> Pareado -> Planta baja -> Casa de piedra -> Casa de Pueblo -> Casa con terreno

		$sqlTipoCasa = 'SELECT id FROM tipos_inmueble WHERE nombre = "Casas o chalets" LIMIT 1';

		$sqlUpdateTipoCasa = 'UPDATE tipos_inmueble set nombre = "Casas", seo = "casas" WHERE nombre = "Casas o chalets"';

		if($this->db->query($sqlUpdateTipoCasa)) {
			$this->traza("<p>Actualizada la agrupación de CASAS");
		}


		$resTipoCasa = $this->db->query($sqlTipoCasa);

		while ($rowTipoCasa = $this->db->fetch($resTipoCasa)) {

			$id = $rowTipoCasa['id'];
	
		}

		$sqlSetCasa = "UPDATE inmuebles 
		SET nombre_tipo_inmueble = 'Casas',
		id_tipo_inmueble = ". $id . "
		WHERE inmuebles.nombre_tipo_inmueble = 'Casas o chalets' 
		OR inmuebles.nombre_tipo_inmueble = 'Casonas'
		OR inmuebles.nombre_tipo_inmueble = 'Casas rústicas'";

		if ($this->db->query($sqlSetCasa)) {
			$this->traza("<p>Se ha agrupado las Casas");
		} else {
			$this->traza("<p>Se ha producido un error al agrupar las Casas");
		}

		$sqlDeleteTipoCasaOtros = "DELETE FROM tipos_inmueble 
		WHERE nombre = 'Casonas' 
		OR nombre = 'Casas rústicas'";

		if ($this->db->query($sqlDeleteTipoCasaOtros)) {
			$this->traza("<p>Se han borrado los otros tipos de inmuebles");
		} else {
			$this->traza("<p>Se ha producido un error al borrar los otros tipos de inmuebles relacionados");
		}
	}

	/**
	 * 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->num_referencia)) ? $inmueble->id : $inmueble->num_referencia;
		/*
		ESTO ESTABA ANTES
		if (empty(trim($inmueble->provincia))) {
		*/
		//Provincia
		if (empty(trim('Cantabria'))) {
			$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
		// Quitamos el error si no viene Población para que lo inserte. JAGUI Altamira 21
		/*if (empty(trim($inmueble->poblacion))) {
			$this->traza("<p class='error'>Datos erróneos en el XML. Inmueble: {$identificacion}. Dato: Población.</p>");
			return false;
		}*/
		$poblacion = $this->capitaliza((string) $inmueble->poblacion);
		// Quitamos el error si no viene Localidad para que lo inserte. JAGUI Altamira 21
		/*if (empty($this->pobsBD[$poblacion]) || $this->pobsBD[$poblacion]['id_provincia'] != $id_provincia) {
			$this->traza("<p class='error'>Hay que actualizar la tabla de localidades. 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 localidades

		//Tipo de Inmueble
		// Quitamos el error si no viene Localidad para que lo inserte. JAGUI Altamira 21
		/*
		if (empty(trim($inmueble->tipo_inmueble))) {
			$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_inmueble);
		// Quitamos el error si no viene nombre tipo inmueble para que lo inserte. JAGUI Altamira 21
		/*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->metros_construidos, 2);
		$m2utiles = $this->getInt($inmueble->metros_utiles, 2);
		$m2sup = $this->getInt($inmueble->metros_parcela, 2);
		$superficie = max($m2utiles, $m2cons);
		$habitaciones = $this->getInt($inmueble->dormitorios) + $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");

		$coordenadas = explode(",", $inmueble->coordenadas);
		$inmueble->latitud = $coordenadas[0];
		$inmueble->longitud = $coordenadas[1];

		//Datos a insertar en BD
		$data = array(
			'id' => (string) $inmueble->id_inmueble,
			'id_cliente' => 0,
			'codigo_agencia' => (int) $inmueble->codigo_agencia,
			'id_gestor' => (strpos($inmueble->Gestor->email_gestor, 'altamira21') !== false) ? (int) $inmueble->Gestor->id_gestor : 459845,
			'nombre_gestor' => (strpos($inmueble->Gestor->email_gestor, 'altamira21') !== false) ? $inmueble->Gestor->nombre_gestor : 'Pilar Altamira 21', 
			'apellido_gestor' => (strpos($inmueble->Gestor->email_gestor, 'altamira21') !== false) ? $inmueble->Gestor->apellido_gestor : 'coordinadora', 
			'email_gestor' => (strpos($inmueble->Gestor->email_gestor, 'altamira21') !== false) ? $inmueble->Gestor->email_gestor : 'coordinadora@altamira21.com', 
			'telefono_gestor' => (strpos($inmueble->Gestor->email_gestor, 'altamira21') !== false) ? $inmueble->Gestor->telefono_gestor : '942051900',
			'foto_gestor' => (strpos($inmueble->Gestor->email_gestor, 'altamira21') !== false) ? $inmueble->Gestor->foto_gestor : '459845.jpg',
			'foto_gestor_url' => (strpos($inmueble->Gestor->email_gestor, 'altamira21') !== false) ? $inmueble->Gestor->url_foto_gestor : 'https://app.iagestion.com/Imagenes/Perfiles/459845.jpg',
			'mls' => 'https://pasarelas.iagestion.com',
			'referencia_unica' => (string) $inmueble->id_inmueble,
			'referencia' =>  (string) $inmueble->num_referencia,
			//'id_promocion' => 0,
			'id_pais' => 1,
			'id_provincia' => $procesado['id_provincia'],
			'id_area' => $procesado['id_area'],
			'id_localidad' => $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' => (string) $inmueble->direccion,
			'direccion_numero' => (int) $inmueble->numero,
			'direccion_piso' => (string) $inmueble->planta,
			'direccion_letra' => '',
			'direccion_escalera' => '',
			'cp' => (string) $inmueble->cod_postal,
			'id_gestion' =>  ($inmueble->tipo_operacion == 'Venta' ? 1 : 2),
			'precio' => ((int) $inmueble->precio > 0 ? $this->getInt($inmueble->precio, 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->banios,
			'aseos' => (string) $inmueble->aseos,
			'salones' => (string) $inmueble->salones,
			'promocion' => (string) $inmueble->keypromo,
			'superficie' => $superficie,
			'superficie_util' => $m2utiles,
			'superficie_construida' => $m2cons,
			'superficie_terreno' => $m2sup,
			'latitud' => $inmueble->latitud,
			'longitud' => $inmueble->longitud,
			//'map_point' => "Point($latitud , $longitud)",
			'geolocalizacion' => $inmueble->latitud.','.$inmueble->longitud,
			'nuevo' => ((!empty($inmueble->conservacion) && (int) $inmueble->conservacion[1] > 60) ? 1 : 0),
			'garaje' => (string) $inmueble->garajes,
			'calefaccion' => ((string) $inmueble->calefaccion != '' ? 1 : 0),
			'aire_acondicionado' => (string) $inmueble->aire_con,
			'piscina' => ((string) $inmueble->piscina == 1 ? 1 : 0),
			'jardin' => ((int) $inmueble->jardin > 0 ? (string) $inmueble->jardin : 0),
			'trastero' => (string) $inmueble->trasteros,
			'ascensor' => (string) $inmueble->ascensores,
			'terraza' => (string) $inmueble->terrazas,
			'titulo_corto' => (string) $inmueble->titular_publico,
			'descripcion' => (string) $inmueble->observaciones_publicas->observaciones,
			'observaciones' => (string) $inmueble->observaciones_publicas->observaciones,
			'activa' => 1,
			'banco' => (int) $inmueble->entidadbancaria,
			'eficiencia_energetica' => $certificado,
			'reservado' => 0,
			'destacado' => (int) $inmueble->destacado,
			'visitas' => 0,
			'tour_virtual' => $inmueble->tours->tour->url_tour,
			'vistas_mar' => $inmueble->vistas_mar,
			'nfotos' => (int) $inmueble->numfotos,
			'cod_ofer' => (string) $inmueble->cod_ofer,
			'estadoficha' => (int) $inmueble->estadoficha,
			'estado_inmueble' => (string) $inmueble->estado_inmueble,
			//'keyacci' => (int) $inmueble->keyacci,
			//'numsucursal' => ((int) $inmueble->numsucursal > 0 ? (string) $inmueble->numsucursal : null),
			'seo' => $this->getUrlInmueble(
				$procesado['nombre_tipo_inmueble'], 
				$procesado['nombre_zona'], 
				$procesado['nombre_poblacion'], 
				$procesado['nombre_provincia'], 
				$habitaciones, 
				(string) $inmueble->num_referencia
			),
          'seo_accesible' => '/' . $inmueble->id_inmueble . '/' .$inmueble->num_referencia,
			'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->num_referencia}. | <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 = "fotos->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>");
			}
		} */

		$i = 1;
		foreach ($inmueble->fotos->foto as $url) {
		//	print_r($foto);
			//die;
			$principal = ($i == 1) ? 1 : 0;
 $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)) {
			/* ESTABA ANTES JAGUI */
	        //$temp[] = $nombre_zona;
			/* ESTABA ANTES JAGUI */
		}
		$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')) {
			die;
			$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 auxiliaresRun($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->importInmuebles();
		$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 localidades 
		$this->pobAreaBD = $this->loadAreas();
		
		//2.2.- Para cargar y actualizar las localidades
			$this->pobsBD = $this->importPoblaciones();
		
		
		//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 localidades 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->db->query('DELETE FROM provincias');

		$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 = 'Inmuebles';
		$element = 'Inmueble';
		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 localidades con el mismo nombre, tal como está hecho, fallaría
	 */
	private function loadPoblaciones() {
		$pobsBD = array();
		$resPobs = $this->db->query('SELECT * FROM localidades');
		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 localidades (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 localidades 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 localidades 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 localidades 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 localidades con el mismo nombre, tal como está hecho, fallaría
	 */
	public function importPoblaciones() {
		$pobsBD = array();
		$pobsNuevas = array();
		$actualizarPobs = false;
		$this->db->query('DELETE FROM localidades');

		$this->xml->open($this->xmlFile);
		$this->traza('<h2>Actualizando localidades...........</h2>');
		
		// Cargo las localidades que ya tengo y compruebo si se han de actualizar
		$resPobs = $this->db->query('SELECT * FROM localidades');
		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 localidades que no tenga cargadas
		// También compruebo que los id_area coinciden con lo que tengo cargado
		$rootElement = 'Inmuebles';
		$element = 'Inmueble';
		while ($this->xml->read()) {
			if ($this->xml->localName == $element && $this->xml->nodeType == XMLReader::ELEMENT) {
				$inmueble = simplexml_load_string($this->xml->readOuterXml(), 'SimpleXMLElement', LIBXML_NOCDATA);
				/* ESTABA ANTES. JAGUIL */
				//$nombrePob = $this->capitaliza((string) $inmueble->poblacion);
				/* ESTABA ANTES. JAGUIL */
				//print((string) $inmueble->poblacion);
				//print("<br>");
				$nombrePob = (string) $inmueble->poblacion;
				$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 localidades a la BD
		$total = 0;
		if (!empty($pobsNuevas)) {
			$i = 0;
			foreach ($pobsNuevas as $pob) {
				$sql = "INSERT INTO localidades (id, id_provincia,id_area,nombre) VALUES ({$i}, {$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>");
				}
				$i++;
			}
		}
		$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 localidades 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 = 'Inmuebles';
		$element = 'Inmueble';
		while ($this->xml->read()) {
			if ($this->xml->localName == $element && $this->xml->nodeType == XMLReader::ELEMENT) {
				$inmueble = simplexml_load_string($this->xml->readOuterXml(), 'SimpleXMLElement', LIBXML_NOCDATA);
				/* ESTABA ANTES JAGUI */
				//$nombre = $this->capitaliza((string) $inmueble->zona);
				/* ESTABA ANTES JAGUI */
				$nombre = (string) $inmueble->zona;
				$poblacion = $this->capitaliza((string) $inmueble->poblacion);
				$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) {
				/* JAGUI */
				if(!empty($zona['id_poblacion'])) {
					$zona['id_poblacion'] = $zona['id_poblacion'];
				}else {
					$zona['id_poblacion'] = rand();
				}
				/* JAGUI */
				
				$sql = "INSERT INTO zonas (localidad_id,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 = 'Inmuebles';
		$element = 'Inmueble';
		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_inmueble)/*&& !empty($inmueble->key_tipo) */) {
				/* ESTABA ANTES JAGUI */
					//$nombreTipoInmueble = $this->capitaliza((string) $inmueble->tipo_inmueble);
				/* ESTABA ANTES JAGUI */
				$nombreTipoInmueble = (string) $inmueble->tipo_inmueble;
				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)) {
		$i = 0;
		foreach ($tipos_inmueble as $t) {
			$sql = "INSERT INTO tipos_inmueble (id, tipo_id, nombre, seo) VALUES ({$i}, {$t['tipo_id']}, '{$t['nombre']}', '{$t['seo']}')";
			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>");
			}
			$i++;
		}
	}
	$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