<?php

		function FixUTF8($args) {
			$output = $args['input'];
			
			$output = convertNamedHTMLEntitiesToNumeric(['input'=>$output]);
			
			preg_match_all('/(&#[0-9]+;)/', $output, $matches, PREG_OFFSET_CAPTURE);
			$full_matches = $matches[0];
			
			$found = [];
			$search = [];
			$replace = [];
			
			for($i = 0; $i < count($full_matches); $i++) {
				$match = $full_matches[$i];
				$word = $match[0];
				if(!$found[$word]) {
					$found[$word] = TRUE;
					$search[] = $word;
					$replacement = str_replace(['&#', ';'], ['HTML Entity #', ''], $word);
					$replace[] = $replacement;
				}
			}

			$new_output = str_replace($search, $replace, $output);
			
			return $new_output;
		}
		
		function convertNamedHTMLEntitiesToNumeric($args) {
			$input = $args['input'];
			return preg_replace_callback("/(&[a-zA-Z][a-zA-Z0-9]*;)/",function($m){
				$c = html_entity_decode($m[0],ENT_HTML5,"UTF-8");
				# return htmlentities($c,ENT_XML1,"UTF-8"); -- see update below
				
				$convmap = array(0x80, 0xffff, 0, 0xffff);
				return mb_encode_numericentity($c, $convmap, 'UTF-8');
			}, $input);
		}

print(FixUTF8(['input'=>"Oggi &egrave; un bel&nbsp;giorno"]));