Server IP : 85.214.239.14 / Your IP : 3.145.72.55 Web Server : Apache/2.4.62 (Debian) System : Linux h2886529.stratoserver.net 4.9.0 #1 SMP Tue Jan 9 19:45:01 MSK 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.18 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, MySQL : OFF | cURL : OFF | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /var/www/wordpress/wp-content/plugins/fictional-maps-handler/php/classes/ |
Upload File : |
<?php /** * @author Michael Herrmann * @copyright 2020 */ include_once('MAP_DB_CONNECTOR.php'); include_once('DETAIL_MAP.php'); class MAP implements JsonSerializable { private $id; public $userid; public $map_name; private $map_width; private $map_height; private $tile_depth; private $min_zoom; private $max_zoom; private $search; private $fullscreen; private $popout; private $scalebar_toggle; private $labels; private $popup_background; private $measuring; private $map_units; private $width_in_units; private $protected; private $password_hash; private $origin; private $description; private $rating; private $detail_maps; /**Current use case: * DO NOT USE THIS! * * USE MAP_DB_CONNECTOR::get_map() */ public function __construct(){ //for later use: //$this->map_db_connector = new MAP_DB_CONNECTOR(); //$this->set_detail_maps($this->map_db_connector->conn); } /** * MAP::was_rated_by() * check if map was already rated by a certain IP address * @param string $ip_address * @return bool */ public function was_rated_by($ip_address){ $rating_array = $this->get_rating(); //get the array of rating objects $was_rated = false; //create the return variable foreach($rating_array as $rating){ //iterate through the array of RATING objects for this map if ($rating->get_rater_ip() == $ip_address){ //check if one has the given IP as rater_ip class variable $was_rated = true; //if yes, set the return value to true } } return $was_rated; } /** * MAP::get_rating_from_ip() * check if map was already rated by a certain IP address * @param string $ip_address * @return int rating */ public function get_rating_from_ip($ip_address){ $rating_array = $this->get_rating(); //get the array of rating objects $ip_rated = null; //create the return variable foreach($rating_array as $rating){ //iterate through the array of RATING objects for this map if ($rating->get_rater_ip() == $ip_address){ //check if one has the given IP as rater_ip class variable $ip_rated = $rating->get_rating(); //if yes, set the return value to the rating corresponding to the ip in the db table fm.map_ratings } } return $ip_rated; } /** * MAP::get_average_rating() * check if map was already rated by a certain IP address * @return float rating */ public function get_average_rating(){ if (!empty($this->rating)){ //check if there even are any ratings $total = 0; foreach($this->rating as $rating){ $total = $total + $rating->get_rating(); //add up all ratings } $average = $total/sizeOf($this->rating); //divide total through number of ratings to get the average return $average; } else { return '0'; } } /** * MAP::get_fancy_average_rating() * uses Lower bound of Wilson score confidence interval for a Bernoulli parameter (0.9604) * * CURRENTLY NOT IN USE - ONLY WORKS WELL WITH MANY MANY VOTES (100+) * * See: * http://www.evanmiller.org/how-not-to-sort-by-average-rating.html * https://gist.github.com/julienbourdeau/77eaca0fd1e4af3fde9fe018fdf13d7d * @return float rating */ public function get_fancy_average_rating(){ $star1 = 0; //first we create empty variables as input for our $star2 = 0; $star3 = 0; $star4 = 0; $star5 = 0; if (!empty($this->rating)){ //check if there even are any ratings foreach($this->rating as $rating){ //iterate through the array of RATING objects for this map switch ($rating->get_rating()){ case 1: $star1++; break; case 2: $star2++; break; case 3: $star3++; break; case 4: $star4++; break; case 5: $star5++; break; } } return $this->fiveStarRating($star1,$star2, $star3, $star4, $star5); //TODO cast range 0-1 to 1-5 } else { return '0'; } } /** * HELPER FUNCTIONS FOR THE FANCY AVERAGE RATING */ private function score($positive, $negative) { return ((($positive + 1.9208) / ($positive + $negative) - 1.96 * sqrt((($positive * $negative) / ($positive + $negative)) + 0.9604) / ($positive + $negative)) / (1 + 3.8416 / ($positive + $negative))); } private function fiveStarRating($one, $two, $three, $four, $five) { $positive = $two * 0.25 + $three * 0.5 + $four * 0.75 + $five; $negative = $one + $two * 0.75 + $three * 0.5 + $four * 0.25; return $this->score($positive, $negative); } /** * MAP::longest_side_value() * returns the longest side value AFTER resizing for tiles * @return int pixelcount */ public function longest_side_value(){ //find out which side is longest first $longest_side; if ($this->map_width >= $this->map_height){ $longest_side = $this->map_width; } else { $longest_side = $this->map_height; } //as everything above 1024 gets resized to the next power of two, return that if ($longest_side > 32768){ return 65.536; } elseif($longest_side > 16384){ return 32768; } elseif($longest_side > 8192){ return 16384; } elseif($longest_side > 4096){ return 8192; } elseif($longest_side > 2048){ return 4096; } elseif($longest_side > 1024){ return 2048; } else { return $longest_side; } } /** * MAP::jsonSerialize() * override the function from JsonSerializable to be able to use json_encode and get the private variables * @return json object vars */ public function jsonSerialize() { return get_object_vars($this); } /** * MAP::prepare_for_download() * builds a zip file including a html file with all necessary styles and site and the accompagnying image files * ZIP is saved to the usermaps/map_name folder * */ public function prepare_for_download(){ #echo "prepare for download<br />"; //first define paths to all the content we need $map_dir = dirname(__FILE__) . "/../../usermaps/".$this->userid."/".$this->map_name; $img_dir = dirname(__FILE__) . "/../../img"; //build the content of the main file $html_string = '<!DOCTYPE html><html><head><title>'.$this->map_name.' - provided by fictionalmaps.com</title><meta charset="utf-8" /><style>'; //start of file, now add the styles $html_string .= file_get_contents(__DIR__.'/../../css/leaflet/leaflet.min.css'); $html_string .= file_get_contents(__DIR__.'/../../css/leaflet/leaflet-search.min.css'); $html_string .= file_get_contents(__DIR__.'/../../css/leaflet/leaflet.fullscreen.min.css'); $html_string .= file_get_contents(__DIR__.'/../../css/leaflet/leaflet.measure.min.css'); $html_string .= file_get_contents(__DIR__.'/../../css/leaflet/leaflet.responsive.popup.min.css'); $html_string .= file_get_contents(__DIR__.'/../../css/fm/dungeonmasterresources.min.css'); $html_string .= 'html, body {height: 100%;margin: 0;} #map {width: 1024px;height: 1024px;}</style></head><body><div id="map"></div>'; //transition to body, added map div and now for the site $html_string .= '<script src="https://kit.fontawesome.com/d3437d5a3a.js" crossorigin="anonymous"></script>'; $html_string .= '<script>'. file_get_contents(__DIR__.'/../../js/lib/jquery-3.5.1.min.js').'</script>'; $html_string .= '<script>'. file_get_contents(__DIR__.'/../../js/leaflet/leaflet.js').'</script>'; $html_string .= '<script>'. file_get_contents(__DIR__.'/../../js/leaflet/leaflet-search.min.js').'</script>'; $html_string .= '<script>'. file_get_contents(__DIR__.'/../../js/leaflet/leaflet.fullscreen.min.js').'</script>'; $html_string .= '<script>'. file_get_contents(__DIR__.'/../../js/leaflet/leaflet.measure.min.js').'</script>'; $html_string .= '<script>'. file_get_contents(__DIR__.'/../../js/leaflet/leaflet.responsive.popup.min.js').'</script>'; $initial_map_string = '<script>'. file_get_contents(__DIR__.'/../../js/fm/fm.audience_map_dl.min.js').'</script>'; //now we load our adapted fm_audience_map to insert the values $placeholder = array("PH_MAPNAME", "PH_WIDTH", "PH_HEIGHT", "PH_TILEDEPTH", "PH_MINZOOM", "PH_MAXZOOM", "PH_SEARCH", "PH_FULLSCREEN", "PH_SCALEBARTOGGLE", "PH_LABELS", "PH_POPUPBACKGROUND", "PH_MEASURING", "PH_MAPUNITS", "PH_WINUNITS", "PH_DETAILMAPS", "PH_MARKERS"); //array with all the placeholders we want to replace if ($this->tile_depth > 2){ //once again, to determine wether it got tiled or not $width = $this->longest_side_value(); //and thus to set width and height accordingly $height = $this->longest_side_value(); } else { $width = $this->map_width; $height = $this->map_height; } $marker_json_string = file_get_contents(__DIR__."/../../usermaps/".$this->userid."/".$this->map_name."/communities.geojson"); //load the geojson with the markers to include right in the file $detail_maps_string = json_encode($this->detail_maps); //create string for detail map json objects $values = array($this->map_name, $width, $height, $this->tile_depth, $this->min_zoom, $this->max_zoom, $this->search, $this->fullscreen, $this->scalebar_toggle, $this->labels, $this->popup_background, $this->measuring, $this->map_units, $this->width_in_units, $detail_maps_string, $marker_json_string); //array with all the values to insert $final_map_string = str_replace($placeholder, $values, $initial_map_string); //replace all the placeholders with values from the array $html_string .= $final_map_string; //add the audience map string now with hardcoded values to the overall string $html_string .= '</body></html>'; //now create a zip and add all the necessary content #echo "create zip archive<br />"; $zip = new ZipArchive(); if($zip->open($map_dir."/".$this->map_name."_offline.zip", ZipArchive::CREATE) === TRUE){ $zip->addFile($img_dir."/error_tile.png","img/error_tile.png"); $zip->addFromString($this->map_name."_offline.html", $html_string); //add the html content we built above as html file to the zip $zip->addFile($map_dir."/".$this->map_name.".png", $this->map_name.".png"); //add the icons foreach(glob($img_dir.'/symbols/*.*') as $filename){ if (substr(basename($filename), 0, 7) === "Map_Pin")$zip->addFile($filename, "img/symbols/".basename($filename)); } #echo $map_dir."/detail-maps"; if(file_exists($map_dir."/detail-maps"))$this->addDir($zip,$map_dir."/detail-maps","detail-maps"); if(file_exists($map_dir."/tiles"))$this->addDir($zip,$map_dir."/tiles","tiles"); // All files are added, so close the zip file. $zip->close(); } //return path to zip archive return $map_dir."/".$this->map_name."_offline.zip"; } /* * ./dir1/. * /.. * /.hidden.file * /image1.png * /zoom1/. * /.. * /image2.png * * $dir = <path to image dir> * */ private function addDir($zipArchive,$dir,$zipdir='.') { if(is_dir($dir)){ #echo "check $dir ...<br />"; if($dh=opendir($dir)){ //Add the directory if(!empty($zipdir))$zipArchive->addEmptyDir($zipdir); //Loop through all the files while(($file=readdir($dh))!==false){ //If it's a folder, run the function again! if(substr($file,0,1)==".")continue; if(!is_file($dir."/".$file)){ //recursive call next dir $this->addDir($zipArchive,$dir."/".$file,$zipdir."/".$file); }else{ // Add the files #echo "add file $dir/$file to $zipdir/$file<br />"; $zipArchive->addFile($dir."/".$file,$zipdir."/".$file); } } } } } /** * ========================================================================= * GETTER & SETTER * * ========================================================================= */ public function get_id(){ return $this->id; } public function get_userid(){ return $this->userid; } public function get_map_name(){ return $this->map_name; } public function get_map_width(){ return $this->map_width; } public function get_map_height(){ return $this->map_height; } public function get_tile_depth(){ return $this->tile_depth; } public function get_min_zoom(){ return $this->min_zoom; } public function get_max_zoom(){ return $this->max_zoom; } public function get_search(){ return $this->search; } public function set_search($search){ $this->search = $search; } public function get_fullscreen(){ return $this->fullscreen; } public function get_popout(){ return $this->popout; } public function get_scalebar_toggle(){ return $this->scalebar_toggle; } public function get_labels(){ return $this->labels; } public function get_popup_background(){ return $this->popup_background; } public function get_measuring(){ return $this->measuring; } public function get_map_units(){ return $this->map_units; } public function get_width_in_units(){ return $this->width_in_units; } public function get_protected(){ return $this->protected; } public function set_protected($protected){ $this->protected = $protected; } public function get_password_hash(){ return $this->password_hash; } /** * MAP::get_origin() * this actually does something ;-) * establishes a db connection and gets the map origin from the fm_map_origins table * @return array associated array with id, origin, origin_url */ public function get_origin(){ $map_db_connector = new MAP_DB_CONNECTOR(); //establish db connection $stmt = $map_db_connector->conn->prepare("SELECT * FROM fm_map_origins WHERE id = :id"); $sql_values = [ //set the array of values to hand over to the prepared sql statement 'id' => $this->origin, //in the origin field of the map table, only the id of the corresponding row of the origins table is stored ]; //we use it here to get all the information about origin site or software $stmt->execute($sql_values); //execute the query return $stmt->fetch(PDO::FETCH_ASSOC); //return the row as array like [origin] => user ; [origin_url] => https://fictionalmaps.com/ } public function get_rating(){ return $this->rating; } public function set_rating($rating){ $this->rating = $rating; } public function get_detail_maps(){ return $this->detail_maps; } /** * MAP::set_detail_maps() * this actually does something ;-) * gets all the detail maps from the fm_detail_maps table and add them to $this->detail_maps * @param object $conn - PDO database connection */ public function set_detail_maps($conn){ //prepare the statement $stmt = $conn->prepare("SELECT * FROM fm_detail_maps WHERE map_id = :map_id"); //execute the statement $sql_values = [ //set the array of values to hand over to the prepared sql statement 'map_id' => $this->id, //get all details maps where the map_id matches the id of this map ]; $stmt->execute($sql_values); $this->detail_maps = $stmt->fetchAll(PDO::FETCH_CLASS, 'DETAIL_MAP'); } /** * MAP::add_description * adds a database entry for the description * @param object $conn - PDO connection * @param string $description */ public function add_description($conn, $description){ $stmt = $conn->prepare("UPDATE fm_maps SET description = :description WHERE id = :map_id"); $sql_values = [ //set the array of values to hand over to the prepared sql statement 'map_id' => $this->id, 'description' => $description, ]; $stmt->execute($sql_values); } public function get_description(){ return $this->description; } /** * MAP::get_tags() * return all tags attributed to this map * statement grabbed here: http://lekkerlogic.com/2016/02/site-tags-using-mysql-many-to-many-tags-schema-database-design/ * @param object $conn - PDO connection */ public function get_tags($conn) { $stmt = $conn->prepare("SELECT t.tag FROM fm_tags t INNER JOIN fm_map_tags mt on t.id = mt.tag_id INNER JOIN fm_maps m on mt.map_id = m.id WHERE m.id = :map_id"); $sql_values = [ //set the array of values to hand over to the prepared sql statement 'map_id' => $this->id, ]; $stmt->execute($sql_values); $tags = $stmt->fetchAll(); return $tags; } }