salut
Joomla 442
Version de PHP 8.2.10
OVH
une erreur est apparue, puis elle disparait puis revient ...
à la ligne 330 il ya
en mettant le rapport d'erreur au maximum une autre erreur
voici le fichier gpxtrackmap.php (je suppose que c'est ce fichier qui déclenche l'erreur)
à la ligne 52 il y a
vous pouvez m'aider s'il vous plait ?
belle journée
Joomla 442
Version de PHP 8.2.10
OVH
une erreur est apparue, puis elle disparait puis revient ...
: Zend OPcache API is restricted by "restrict_api" configuration directive in /home/site/www/libraries/vendor/joomla/filesystem/src/File.php on line 330
Code:
<?php /** * Part of the Joomla Framework Filesystem Package * * @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE */ namespace Joomla\Filesystem; use Joomla\Filesystem\Exception\FilesystemException; /** * A File handling class * * @since 1.0 */ class File { /** * Strips the last extension off of a file name * * @param string $file The file name * * @return string The file name without the extension * * @since 1.0 */ public static function stripExt($file) { return preg_replace('#\.[^.]*$#', '', $file); } /** * Makes the file name safe to use * * @param string $file The name of the file [not full path] * @param array $stripChars Array of regex (by default will remove any leading periods) * * @return string The sanitised string * * @since 1.0 */ public static function makeSafe($file, array $stripChars = ['#^\.#']) { $regex = array_merge(['#(\.){2,}#', '#[^A-Za-z0-9\.\_\- ]#'], $stripChars); $file = preg_replace($regex, '', $file); // Remove any trailing dots, as those aren't ever valid file names. $file = rtrim($file, '.'); return $file; } /** * Copies a file * * @param string $src The path to the source file * @param string $dest The path to the destination file * @param string $path An optional base path to prefix to the file names * @param boolean $useStreams True to use streams * * @return boolean True on success * * @since 1.0 * @throws FilesystemException * @throws \UnexpectedValueException */ public static function copy($src, $dest, $path = null, $useStreams = false) { // Prepend a base path if it exists if ($path) { $src = Path::clean($path . '/' . $src); $dest = Path::clean($path . '/' . $dest); } // Check src path if (!is_readable($src)) { throw new \UnexpectedValueException( sprintf( "%s: Cannot find or read file: %s", __METHOD__, Path::removeRoot($src) ) ); } if ($useStreams) { $stream = Stream::getStream(); if (!$stream->copy($src, $dest, null, false)) { throw new FilesystemException(sprintf('%1$s(%2$s, %3$s): %4$s', __METHOD__, $src, $dest, $stream->getError())); } self::invalidateFileCache($dest); return true; } if (!@ copy($src, $dest)) { throw new FilesystemException(__METHOD__ . ': Copy failed.'); } self::invalidateFileCache($dest); return true; } /** * Delete a file or array of files * * @param mixed $file The file name or an array of file names * * @return boolean True on success * * @since 1.0 * @throws FilesystemException */ public static function delete($file) { $files = (array) $file; foreach ($files as $file) { $file = Path::clean($file); $filename = basename($file); if (!Path::canChmod($file)) { throw new FilesystemException(__METHOD__ . ': Failed deleting inaccessible file ' . $filename); } // Try making the file writable first. If it's read-only, it can't be deleted // on Windows, even if the parent folder is writable @chmod($file, 0777); // In case of restricted permissions we zap it one way or the other // as long as the owner is either the webserver or the ftp if (!@ unlink($file)) { throw new FilesystemException(__METHOD__ . ': Failed deleting ' . $filename); } self::invalidateFileCache($file); } return true; } /** * Moves a file * * @param string $src The path to the source file * @param string $dest The path to the destination file * @param string $path An optional base path to prefix to the file names * @param boolean $useStreams True to use streams * * @return boolean True on success * * @since 1.0 * @throws FilesystemException */ public static function move($src, $dest, $path = '', $useStreams = false) { if ($path) { $src = Path::clean($path . '/' . $src); $dest = Path::clean($path . '/' . $dest); } // Check src path if (!is_readable($src)) { return 'Cannot find source file.'; } if ($useStreams) { $stream = Stream::getStream(); if (!$stream->move($src, $dest, null, false)) { throw new FilesystemException(__METHOD__ . ': ' . $stream->getError()); } self::invalidateFileCache($dest); return true; } if (!@ rename($src, $dest)) { throw new FilesystemException(__METHOD__ . ': Rename failed.'); } self::invalidateFileCache($dest); return true; } /** * Write contents to a file * * @param string $file The full file path * @param string $buffer The buffer to write * @param boolean $useStreams Use streams * @param boolean $appendToFile Append to the file and not overwrite it. * * @return boolean True on success * * @since 1.0 */ public static function write($file, &$buffer, $useStreams = false, $appendToFile = false) { @set_time_limit(ini_get('max_execution_time')); // If the destination directory doesn't exist we need to create it if (!file_exists(\dirname($file))) { Folder::create(\dirname($file)); } if ($useStreams) { $stream = Stream::getStream(); // Beef up the chunk size to a meg $stream->set('chunksize', (1024 * 1024)); $stream->writeFile($file, $buffer, $appendToFile); self::invalidateFileCache($file); return true; } $file = Path::clean($file); // Set the required flag to only append to the file and not overwrite it if ($appendToFile === true) { $res = \is_int(file_put_contents($file, $buffer, \FILE_APPEND)); } else { $res = \is_int(file_put_contents($file, $buffer)); } self::invalidateFileCache($file); return $res; } /** * Moves an uploaded file to a destination folder * * @param string $src The name of the php (temporary) uploaded file * @param string $dest The path (including filename) to move the uploaded file to * @param boolean $useStreams True to use streams * * @return boolean True on success * * @since 1.0 * @throws FilesystemException */ public static function upload($src, $dest, $useStreams = false) { // Ensure that the path is valid and clean $dest = Path::clean($dest); // Create the destination directory if it does not exist $baseDir = \dirname($dest); if (!is_dir($baseDir)) { Folder::create($baseDir); } if ($useStreams) { $stream = Stream::getStream(); if (!$stream->upload($src, $dest, null, false)) { throw new FilesystemException(sprintf('%1$s(%2$s, %3$s): %4$s', __METHOD__, $src, $dest, $stream->getError())); } self::invalidateFileCache($dest); return true; } if (is_writable($baseDir) && move_uploaded_file($src, $dest)) { // Short circuit to prevent file permission errors if (Path::setPermissions($dest)) { self::invalidateFileCache($dest); return true; } throw new FilesystemException(__METHOD__ . ': Failed to change file permissions.'); } throw new FilesystemException(__METHOD__ . ': Failed to move file.'); } /** * Invalidate any opcache for a newly written file immediately, if opcache* functions exist and if this was a PHP file. * * @param string $file The path to the file just written to, to flush from opcache * * @return void */ public static function invalidateFileCache($file) { if (function_exists('opcache_invalidate')) { $info = pathinfo($file); if (isset($info['extension']) && $info['extension'] === 'php') { // Force invalidation to be absolutely sure the opcache is cleared for this file. opcache_invalidate($file, true); } } } }
// Force invalidation to be absolutely sure the opcache is cleared for this file.
opcache_invalidate($file, true);
opcache_invalidate($file, true);
en mettant le rapport d'erreur au maximum une autre erreur
Deprecated: Creation of dynamic property plgContentGPXTrackMap::$_gtmversion is deprecated in /home/site/www/plugins/content/gpxtrackmap/gpxtrackmap.php on line 52
Code:
<?php /** * @author * @Copyright * @package GPXTrackMap - GPX track display on maps using the OpenLayers API - Content Plugin for Joomla 2.5 and 3.x * @author Frank Ingermann - info@frankingermann.de * @version 1.4.1 - 06-Sept-2017 * @link http://software.frankingermann.de/gpxtrackmap * * @license GNU/GPL * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For the GNU General Public License, see <http://www.gnu.org/licenses/>. * * Code and idea are based on the great "Simple Image Gallery Extended" (SIGE) plugin * by Viktor Vogel: http://joomla-extensions.kubik-rubik.de/sige-simple-image-gallery-extended * Thanks, Viktor! */ // ajout pour migration vers Joomla 4 use Joomla\CMS\Filesystem\Folder as JFolder; use Joomla\CMS\Filesystem\File as JFile; use Joomla\Archive\Archive as JArchive; defined('_JEXEC') or die; // V1.2.2 fix for J 3.1.4: jimport('joomla.filesystem.file'); class plgContentGPXTrackMap extends JPlugin { protected $_params; protected $_absolute_path; protected $_rootfolder; // WITH / at end protected $_rootpath; // WITHOUT / at end protected $_live_site; protected $_plugin_dir; protected $_markers_dir; protected $_warnings; function __construct(&$subject, $config) { $this->_gtmversion = 'V1.4.1'; $version = new JVersion(); // test for Joomla 2.5 version. The plugin may also work on pre-2.5, but that's untested. // i'll leave out this check for the time being phase - otherwise nobody could test it under J != 2.5... //if($version->PRODUCT == 'Joomla!' AND $version->RELEASE != '2.5') //{ JError::raiseWarning(100, JText::_('PLG_CONTENT_GPXTRACKMAP_NEEDJ25')); // return; // } parent::__construct($subject, $config); if (isset($_SESSION["gtmcount"])) { unset($_SESSION["gtmcount"]); } if (isset($_SESSION["gtmcountarticles"])) { unset($_SESSION["gtmcountarticles"]); } } public function onContentPrepare($context, &$article, &$params, $limitstart) { // check for our trigger token. If it's not on this page: get outta here, don't waste valuable CPU time! if (!preg_match("@{gpxtrackmap}(.*){/gpxtrackmap}@Us", $article->text)) { return true; } if (!isset($_SESSION["gtmcountarticles"])) { $_SESSION["gtmcountarticles"] = -1; } $this->_absolute_path = JPATH_SITE; $this->_live_site = JURI::base(); $this->_plugin_dir = $this->_live_site.'plugins/content/gpxtrackmap/'; $this->_markers_dir = $this->_plugin_dir.'markers/'; if (substr($this->_live_site, -1) == '/') { $this->_live_site = substr($this->_live_site, 0, -1); } // find all plugin calls on the page if(preg_match_all("@{gpxtrackmap}(.*){/gpxtrackmap}@Us", $article->text, $matches, PREG_PATTERN_ORDER) > 0) { // pull in our language file (atm we only need it to localize the map layer names) $lang = JFactory::getLanguage(); $extension = 'plg_content_gpxtrackmap'; $base_dir = JPATH_ADMINISTRATOR; $language_tag = $lang->getTag(); $reload = true; $lang->load($extension, $base_dir, $language_tag, $reload); $_SESSION["gtmcountarticles"]++; $enablegooglemaps = $this->params->get('enablegooglemaps','0'); // where are we? $plginpath = JPATH_PLUGINS.DIRECTORY_SEPARATOR.'content'.DIRECTORY_SEPARATOR.'gpxtrackmap'.DIRECTORY_SEPARATOR; // load script template that will build the OpenLayer script part $scriptfn = $plginpath.'gpxtrackmap.js'; if (!file_exists($scriptfn)) { echo('<h2 style="color: red;"><em>GPXTrackMap Plugin error: Template script file '.$scriptfn.' not found!</em></h2>'); return true; } if (!isset($_SESSION["gtmcount"])) { $_SESSION["gtmcount"] = -1; } if ($_SESSION["gtmcountarticles"] == 0) // first call on page { // the call to the openlayers api and the osm layer definitions: will be put in <head>, // but only once. it's a BIG chunk of code! // V1.1: the script urls are configurable for those that have OpenLayers.js on their server $scriptsrc_ol = $this->params->get('scriptsrc-ol'); $scriptsrc_osm = $this->params->get('scriptsrc-osm'); $scriptsrc_gm = $this->params->get('scriptsrc-gm'); //TODO: fix URL on non-local servers! // V1.3.2 no longer needed: $scriptsrc_hbl = $this->_plugin_dir."hikebikelayer.js"; // revert to defaults if blank: // V1.4.0 use scripts deployed with the plugin as default //OLD: if ($scriptsrc_ol=="") { $scriptsrc_ol = "http://www.openlayers.org/api/OpenLayers.js"; } if ($scriptsrc_ol=="") { $scriptsrc_ol = "/plugins/content/OpenLayers.2.13.2.full.js"; } //OLD: if ($scriptsrc_osm=="") { $scriptsrc_osm = "http://www.openstreetmap.org/openlayers/OpenStreetMap.js"; } if ($scriptsrc_osm=="") { $scriptsrc_osm = "/plugins/content/OpenStreetMap.js"; } if ($scriptsrc_gm=="") { $scriptsrc_gm = "http://maps.google.com/maps/api/js?v=3&sensor=false"; } $head_js = '<script src="'.$scriptsrc_ol.'"></script>'."\n". '<script src="'.$scriptsrc_osm.'"></script>'."\n"; // V1.3.2 no longer needed: '<script src="'.$scriptsrc_hbl.'"></script>'."\n"; // only if Google Maps are explicitly enabled: link in their API // this is also configurable in case the Google guys should change their url... if ($enablegooglemaps==1) { $head_js .= '<script src="'.$scriptsrc_gm.'"></script>'."\n"; } $document = JFactory::getDocument(); if ($document instanceof JDocumentHTML) { $document->addCustomTag($head_js); // put the calls in the <head> tag of the page // CSS fix for Joomla 3 and some J2.5 templates: setting width and height for img tags can distort // the map and diagram displays; disable those stylings for the track map: $head_css = '<style type="text/css"> div.gpxtrack div.olMap img, div.gpxtrack div.olMap svg {max-width: inherit ! important;} '. 'div.gpxtrack img.olTileImage {max-width: 1000px ! important;} '. 'div.gpxtrack div.olControlLayerSwitcher label {display: inline; font-size: 11px; font-weight: bold; border-top: 2px; } '. 'div.gpxtrack input.olButton {margin-right: 3px; margin-top: 0px;}</style>'."\n"; $document->addCustomTag($head_css); } } if (!$this->params->get('gpxroot')) { $this->_rootfolder = '/images/gpxtracks/'; } else { $this->_rootfolder = $this->params->get('gpxroot'); if (substr($this->_rootfolder, -1) !== '/') { $this->_rootfolder = $this->_rootfolder . '/'; } } $this->_rootpath = substr($this->_rootfolder,0,strlen($this->_rootfolder)-1); // now loop through all invocations we found: foreach($matches[0] as $match) { $scripttext = file_get_contents( $scriptfn ); // increase our session's invocation counter. $_SESSION["gtmcount"]++; $gtmcode=''; // this will make up all of the code to replace the {gpxtrackmap}...{/gpxtrackmap} 'invocation' code in the end $gpx_code = preg_replace("@{.+?}@", "", $match); $gpx_array = explode(",", $gpx_code); // syntax is filename[,param1=value1[,param2=value2[...]]] $gpx_file = $gpx_array[0]; // first param must be the gpx filename or url // V1.2.3 gpx files via URL support if (substr_compare($gpx_file,'http://',0,7) == 0) { $externalgpx = 1; $gpx_path = $gpx_file; $gpx_file = parse_url($gpx_file,PHP_URL_PATH); $localpath = parse_url($this->_live_site,PHP_URL_PATH); $gpx_file = substr($gpx_file,strlen($localpath)); $gpx_filepath = $this->_absolute_path.$gpx_file; $path_parts = pathinfo($gpx_file); $gpx_file = $path_parts['basename']; $gpx_dir = $this->_absolute_path.DIRECTORY_SEPARATOR.$path_parts['dirname'].'/'; $gpx_basepath = $this->_live_site.$path_parts['dirname'].'/'; } else { $externalgpx = 0; $gpx_dir = $this->_absolute_path.DIRECTORY_SEPARATOR.$this->_rootfolder; $gpx_basepath = $this->_live_site.$this->_rootfolder; $gpx_path = $gpx_basepath.$gpx_file; $gpx_filepath = $this->_absolute_path.$this->_rootfolder.$gpx_file; } if (! JFile::exists($gpx_filepath)) { $this->_warnings .= '<h2 style="color: red;"><em>GPXTrackMap Plugin error: GPX file "'.$this->_rootfolder.$gpx_file.'" not found!</em></h2>'; } else { unset($this->_params); // if this is the 2nd, 3rd... call: clear previous params $this->_params = array(); // we want a fresh, empty array of params for this run if(count($gpx_array) >= 2) //more params then just the gpx filename passed { for($i = 1; $i < count($gpx_array); $i++) //starting with the first one AFTER the filename... { $parameter_temp = explode("=", $gpx_array[$i]); if(count($parameter_temp) >= 2) //the params should have item=value syntax, lowercase their names: { $this->_params[strtolower(trim($parameter_temp[0]))] = trim($parameter_temp[1]); } } } $this->collectParams(); // see below - gets all params, either from the current invocation or the defaults from the Backend-params $tpldir = substr($plginpath,0,-1); if (!isset($this->_params['tpl'])) { $this->_params['tpl'] = $this->params->get('tpldefault'); } $tpl = $this->_params['tpl']; switch ($tpl) { case (1): { $tplfn = $this->params->get('tpl1'); break; } case (2): { $tplfn = $this->params->get('tpl2'); break; } case (3): { $tplfn = $this->params->get('tpl3'); break; } case (4): { $tplfn = $this->params->get('tpl4'); break; } case (5): { $tplfn = $this->params->get('tpl5'); break; } case (6): { $tplfn = $this->params->get('tpl6'); break; } // V1.1.4 added default: { // V1.2.2: if $tpl is not an integer, assume it's a directly supplied path to the template file: if (!ctype_digit($tpl)) { $tplfn = $tpl; } } } $templateDir = JPATH_SITE.DIRECTORY_SEPARATOR.'templates'.DIRECTORY_SEPARATOR. JFactory::getApplication()->getTemplate(); // localize template dir -> /plugins/content/gpxtrackmap/de-DE/ $lngtag = $lang->getTag(); $tpldir_local = $tpldir.DIRECTORY_SEPARATOR.$lngtag; $dirs = array($tpldir_local,JPATH_SITE/*$this->_live_site*/.$this->_rootfolder.$lngtag,$templateDir.DIRECTORY_SEPARATOR.$lngtag); $phs = array('%PLUGINDIR%','%GPXDIR%','%TEMPLATEDIR%'); // replace %TEMPLATES% placeholder in filenames with the plugin dir path $tplfn_local = str_replace($phs,$dirs,$tplfn); //TODO: add placeholder %GPXDIR% with the /images/gpxtracks directory? could be an easy way for security risks, though... // if template file is not found in the localized dir, try the plugin root dir as default if (!file_exists($tplfn_local)) { $dirs = array($tpldir,JPATH_SITE/*$this->_live_site*/.$this->_rootpath,$templateDir); $tplfn = str_replace($phs,$dirs,$tplfn); } else { $tplfn = $tplfn_local; } $tplfn = strtr( $tplfn , '\\', '/'); if (!file_exists($tplfn)) { $this->_warnings .= '<h2 style="color: red;"><em>GPXTrackMap Plugin error: Layout template file "'.$tplfn.'" not found, using default layout.</em></h2>'; $tpltext = '<div class="gpxtrack">'. '<div class="gpxtrackinfo"><p>%TRACKPOINTS% trackpoints; distance: %DISTANCE-KM% km; time: %DURATION%</p></div>'. '<div class="gpxtrackmap">%TRACKMAP%</div>'. '<div class="gpxtrackdiagram">%TRACKDIAGRAM%</div>'. '<div class="gpxtracklink">%TRACKLINK%</div>'. '</div>'; } else { $tpltext = file_get_contents( $tplfn ); } $mapvar = 'map'.$_SESSION["gtmcount"]; // all maps need a unique var and ID // this should translate the "Base layer" caption in the layer switcher, but it just translates the hint... oh well... $baselayer = "{'title': ".'"'.JTEXT::_("PLG_CONTENT_GTM_BASELAYER").'"}'; // Map controls for Zooming/panning/switching layers $mapcontrols = ''; // another option would be 'new OpenLayers.Control.ZoomPanel(),' ... if ($this->_params['mapnav'] == 1) { $mapcontrols .= 'new OpenLayers.Control.Navigation({documentDrag: true}),'."\n"; } // documentDrag allows dragging outside map box if ($this->_params['mappan'] == 1) { $mapcontrols .= 'new OpenLayers.Control.PanZoomBar(),'."\n"; } // with pan arrows and zoom bar if ($this->_params['mapzoombtns'] == 1) { $mapcontrols .= 'new OpenLayers.Control.Zoom(),'."\n"; } // simple + - buttons if ($this->_params['mapswitch'] == 1) { $mapcontrols .= 'new OpenLayers.Control.LayerSwitcher('.$baselayer.'),'."\n"; } if ($this->_params['mapscale'] == 1) { $mapcontrols .= 'new OpenLayers.Control.ScaleLine({geodesic:true,maxWidth:150}),'."\n"; } // , bottomOutUnits: "", bottomInUnits: "" ill hide lower display in [mi] if ($this->_params['mapoverview'] == 1) { $mapcontrols .= 'new OpenLayers.Control.OverviewMap(),'."\n"; } if ($this->_params['mapmousepos'] == 1) { $mapcontrols .= 'new OpenLayers.Control.MousePosition(),'."\n"; } if ($this->_params['mapgraticule'] == 1) { $mapcontrols .= 'new OpenLayers.Control.Graticule({displayInLayerSwitcher: true, targetSize: 300,'."\n". 'layerName: "'.JTEXT::_("PLG_CONTENT_GTM_MAPGRATICULE_LABEL").'",'."\n". 'intervals: [ 45, 30, 20, 10, 5, 2, 1, 0.5, 0.2, 0.1, 0.05, 0.01 ] }),'."\n"; } // code to disable zooming with the mouse wheel if ($this->_params['mapwheelzoom'] == 1) { $nomousewheelzoom = ''; } else { $nomousewheelzoom = 'controls = '.$mapvar.'.getControlsByClass(\'OpenLayers.Control.Navigation\');'."\n". 'for(var i = 0; i < controls.length; ++i) controls[i].disableZoomWheel();'."\n"; } // layer definitions: // OSM Mapnik (default) $ldmapnik = ' var layerMapnik = new OpenLayers.Layer.OSM.Mapnik("'. JTEXT::_("PLG_CONTENT_GTM_MAPLAYER_OPENSTREETMAP_MAPNIK"). '"); '.$mapvar.'.addLayer(layerMapnik); '."\n"; // OSM Cyclemap // v1.4.1 configurable API key for Thunderforest map layers $ldTfApiKey = ''; if ($this->_params['tfapikey'] != '') { $ldTfApiKey = '?apikey='.$this->_params['tfapikey']; } // v1.4.0 removed http from all tile server URLs that allow access via https if available $ldcycle = "\n". ' var layerCycleMap = new OpenLayers.Layer.OSM("'. JTEXT::_("PLG_CONTENT_GTM_MAPLAYER_OPENSTREETMAP_CYCLEMAP").'", ['."\n". '"//a.tile.thunderforest.com/cycle/${z}/${x}/${y}.png'.$ldTfApiKey.'",'."\n". '"//b.tile.thunderforest.com/cycle/${z}/${x}/${y}.png'.$ldTfApiKey.'",'."\n". '"//c.tile.thunderforest.com/cycle/${z}/${x}/${y}.png'.$ldTfApiKey.'"],'."\n". '{ attribution : \'maps © <a href="http://thunderforest.com/">Thunderforest</a>,'. ' data © <a href="https://openstreetmap.org/copyright">OpenStreetMap</a> contributors <a href="http://opendatacommons.org/licenses/odbl/">ODbl</a>\' '. '});'."\n". $mapvar.'.addLayer(layerCycleMap); '."\n"."\n"; // OSM Mapnik DE, with colors that are more common in german map renderings: // V1.3.2 added crossOriginKeyword: null due to CORS issues $ldmapnikde = ' var layerMapnikDE = new OpenLayers.Layer.OSM("'. JTEXT::_("PLG_CONTENT_GTM_MAPLAYER_OPENSTREETMAP_MAPNIK_DE").'", ['."\n". '"http://a.tile.openstreetmap.de/tiles/osmde/${z}/${x}/${y}.png",'."\n". '"http://b.tile.openstreetmap.de/tiles/osmde/${z}/${x}/${y}.png",'."\n". '"http://c.tile.openstreetmap.de/tiles/osmde/${z}/${x}/${y}.png"],'."\n". '{sphericalMercator: true, tileOptions : {crossOriginKeyword: null}}); '.$mapvar.'.addLayer(layerMapnikDE); '."\n"; // Hike & Bike map - V1.3.2 hikebike url has changed, old URL: http://toolserver.org/tiles/hikebike/ $ldhikebike = 'var layerHikeBike = new OpenLayers.Layer.TMS("'. JTEXT::_("PLG_CONTENT_GTM_MAPLAYER_OPENSTREETMAP_HIKEBIKE").'", "http://a.tiles.wmflabs.org/hikebike/",'."\n". '{ type: \'png\', getURL: osm_getTileURL,'."\n". ' displayOutsideMaxExtent: true, isBaseLayer: true, '."\n". ' attribution: \'Map Data © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors <a href="http://opendatacommons.org/licenses/odbl/">ODbl</a>\','."\n". ' transitionEffect: \'resize\' } ); '.$mapvar.'.addLayer(layerHikeBike); '."\n"; // V1.3.2 added: $ldtransport = ' var layerTransport = new OpenLayers.Layer.OSM("'. JTEXT::_("PLG_CONTENT_GTM_MAPLAYER_THUNDERFOREST_TRANSPORT").'", ['."\n". '"//a.tile.thunderforest.com/transport/${z}/${x}/${y}.png'.$ldTfApiKey.'",'."\n". '"//b.tile.thunderforest.com/transport/${z}/${x}/${y}.png'.$ldTfApiKey.'",'."\n". '"//c.tile.thunderforest.com/transport/${z}/${x}/${y}.png'.$ldTfApiKey.'"],'."\n". '{sphericalMercator: true, numZoomLevels: 19, '. 'attribution : \'maps © <a href="http://thunderforest.com/">Thunderforest</a>,'. ' data © <a href="https://openstreetmap.org/copyright">OpenStreetMap</a> contributors <a href="http://opendatacommons.org/licenses/odbl/">ODbl</a>\' '. '}); '.$mapvar. '.addLayer(layerTransport); '."\n"; // V1.3.2 added: $ldlandscape = ' var layerLandscape = new OpenLayers.Layer.OSM("'. JTEXT::_("PLG_CONTENT_GTM_MAPLAYER_THUNDERFOREST_LANDSCAPE").'", ['."\n". '"//a.tile.thunderforest.com/landscape/${z}/${x}/${y}.png'.$ldTfApiKey.'",'."\n". '"//b.tile.thunderforest.com/landscape/${z}/${x}/${y}.png'.$ldTfApiKey.'",'."\n". '"//c.tile.thunderforest.com/landscape/${z}/${x}/${y}.png'.$ldTfApiKey.'"],'."\n". '{sphericalMercator: true, numZoomLevels: 19,'. 'attribution : \'maps © <a href="http://thunderforest.com/">Thunderforest</a>,'. ' data © <a href="https://openstreetmap.org/copyright">OpenStreetMap</a> contributors <a href="http://opendatacommons.org/licenses/odbl/">ODbl</a>\' '. '}); '.$mapvar. '.addLayer(layerLandscape); '."\n"; // V1.3.2 added: $ldoutdoors = ' var layerOutdoors = new OpenLayers.Layer.OSM("'. JTEXT::_("PLG_CONTENT_GTM_MAPLAYER_THUNDERFOREST_OUTDOORS").'", ['."\n". '"//a.tile.thunderforest.com/outdoors/${z}/${x}/${y}.png'.$ldTfApiKey.'",'."\n". '"//b.tile.thunderforest.com/outdoors/${z}/${x}/${y}.png'.$ldTfApiKey.'",'."\n". '"//c.tile.thunderforest.com/outdoors/${z}/${x}/${y}.png'.$ldTfApiKey.'"],'."\n". '{sphericalMercator: true, numZoomLevels: 19,'. 'attribution : \'maps © <a href="http://thunderforest.com/">Thunderforest</a>,'. ' data © <a href="https://openstreetmap.org/copyright">OpenStreetMap</a> contributors <a href="http://opendatacommons.org/licenses/odbl/">ODbl</a>\' '. '}); '.$mapvar. '.addLayer(layerOutdoors); '."\n"; // V1.3.2 added: $ldmapquest = ' var layerMapQuest = new OpenLayers.Layer.OSM("'. JTEXT::_("PLG_CONTENT_GTM_MAPLAYER_MAPQUEST").'", ['."\n". '"http://otile1.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png",'."\n". '"http://otile2.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png",'."\n". '"http://otile3.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png"],'."\n". '{sphericalMercator: true, numZoomLevels: 19, tileOptions : {crossOriginKeyword: null},'. 'attribution : \'Tiles Courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a> <img src="http://developer.mapquest.com/content/osm/mq_logo.png">,'. ' data © <a href="https://openstreetmap.org/copyright">OpenStreetMap</a> contributors <a href="http://opendatacommons.org/licenses/odbl/">ODbl</a>\' '. '}); '.$mapvar. '.addLayer(layerMapQuest); '."\n"; // V1.3.2 added: $ldopentopo = ' var layerOpenTopo = new OpenLayers.Layer.OSM("'. JTEXT::_("PLG_CONTENT_GTM_MAPLAYER_OPENTOPOMAP").'", ['."\n". '"//a.tile.opentopomap.org/${z}/${x}/${y}.png",'."\n". '"//b.tile.opentopomap.org/${z}/${x}/${y}.png",'."\n". '"//c.tile.opentopomap.org/${z}/${x}/${y}.png"],'."\n". '{sphericalMercator: true, numZoomLevels: 18, '. 'attribution : \'map data © <a href="https://openstreetmap.org/copyright">OpenStreetMap</a> contributors '. '<a href="http://opendatacommons.org/licenses/odbl/">ODbl</a>, '. '<a href="http://viewfinderpanoramas.org">SRTM</a> | '. 'map style: © <a href="https://opentopomap.org">OpenTopoMap</a> '. '<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>\','. 'tileOptions : {crossOriginKeyword: null}}); '.$mapvar. '.addLayer(layerOpenTopo); '."\n"; // V1.3.2 added: $ldopnv = ' var layerOPNV = new OpenLayers.Layer.OSM("'. JTEXT::_("PLG_CONTENT_GTM_MAPLAYER_MEMOMAPS_OPNV").'", ['."\n". '"http://a.tile.memomaps.de/tilegen/${z}/${x}/${y}.png",'."\n". '"http://b.tile.memomaps.de/tilegen/${z}/${x}/${y}.png",'."\n". '"http://c.tile.memomaps.de/tilegen/${z}/${x}/${y}.png"],'."\n". '{sphericalMercator: true, numZoomLevels: 19, tileOptions : {crossOriginKeyword: null},'. 'attribution : \'tiles © <a href="http://memomaps.de/">MeMoMaps.de</a> <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>,'. ' map data © <a href="https://openstreetmap.org/copyright">OpenStreetMap</a> contributors <a href="http://opendatacommons.org/licenses/odbl/">ODbl</a>'. '\','. '}); '.$mapvar. '.addLayer(layerOPNV); '."\n"; /* nice, but license status unknown... $ldcomic = ' var layerComicSans = new OpenLayers.Layer.OSM("'. JTEXT::_("PLG_CONTENT_GTM_MAPLAYER_OPENSTREETMAP_COMICSANS").'", ['."\n". '"http://a.tiles.mapbox.com/v3/examples.bc17bb2a/${z}/${x}/${y}.png",'."\n". '"http://a.tiles.mapbox.com/v3/examples.bc17bb2a/${z}/${x}/${y}.png",'."\n". '"http://a.tiles.mapbox.com/v3/examples.bc17bb2a/${z}/${x}/${y}.png"],'."\n". '{sphericalMercator: true, numZoomLevels: 19}); '.$mapvar. '.addLayer(layerComicSans); '."\n"; */ // Google layers $ldgooglephy =' var gphy = new OpenLayers.Layer.Google("'. JTEXT::_("PLG_CONTENT_GTM_MAPLAYER_GOOGLE_MAPS_PHYSICAL"). '",{type: google.maps.MapTypeId.TERRAIN}); '.$mapvar.'.addLayer(gphy); '."\n"; $ldgooglestr =' var gmap = new OpenLayers.Layer.Google("'. JTEXT::_("PLG_CONTENT_GTM_MAPLAYER_GOOGLE_MAPS_STREET"). '", {numZoomLevels: 20}); '.$mapvar.'.addLayer(gmap); '."\n"; $ldgooglehyb =' var ghyb = new OpenLayers.Layer.Google("'. JTEXT::_("PLG_CONTENT_GTM_MAPLAYER_GOOGLE_MAPS_HYBRID"). '", {type: google.maps.MapTypeId.HYBRID, numZoomLevels: 20}); '.$mapvar.'.addLayer(ghyb); '."\n"; $ldgooglesat =' var gsat = new OpenLayers.Layer.Google("'. JTEXT::_("PLG_CONTENT_GTM_MAPLAYER_GOOGLE_MAPS_SATELLITE"). '",{type: google.maps.MapTypeId.SATELLITE, numZoomLevels: 22}); '.$mapvar.'.addLayer(gsat); '."\n"; // map metrics and layer $maplayer = $this->_params['maplayer']; $maplayers = $this->_params['maplayers']; // V1.3.1 support for up to three custom map layers $ldcustom1 = ''; $ldcustom2 = ''; $ldcustom3 = ''; $ldcustom1fn = $plginpath.'CustomMapLayer1.js'; $ldcustom2fn = $plginpath.'CustomMapLayer2.js'; $ldcustom3fn = $plginpath.'CustomMapLayer3.js'; if (JFile::exists($ldcustom1fn)) { $ldcustom1 = file_get_contents($ldcustom1fn); $ldcustom1 = str_replace('%MAPVAR%',$mapvar,$ldcustom1); } if (JFile::exists($ldcustom2fn)) { $ldcustom2 = file_get_contents($ldcustom2fn); $ldcustom2 = str_replace('%MAPVAR%',$mapvar,$ldcustom2); } if (JFile::exists($ldcustom3fn)) { $ldcustom3 = file_get_contents($ldcustom3fn); $ldcustom3 = str_replace('%MAPVAR%',$mapvar,$ldcustom3); } // add the map layers, default layer first switch ($maplayer) { case(1): $maplayerscode = $ldcycle; break; case(2): $maplayerscode = $ldmapnikde; break; case(3): $maplayerscode = $ldhikebike; break; case(4): { if ($enablegooglemaps==1) { $maplayerscode = $ldgooglestr; } break; } case(5): { if ($enablegooglemaps==1) { $maplayerscode = $ldgooglephy; } break; } case(6): { if ($enablegooglemaps==1) { $maplayerscode = $ldgooglehyb; } break; } case(7): { if ($enablegooglemaps==1) { $maplayerscode = $ldgooglesat; } break; } case(8): { if ($ldcustom1=='') { $this->_warnings .= '<h2 style="color: red;"><em>'.$ldcustom1fn.' does not exist or is empty.</em></h2>'."\n"; } else { $maplayerscode = $ldcustom1; } break; } case(9): { if ($ldcustom2=='') { $this->_warnings .= '<h2 style="color: red;"><em>'.$ldcustom2fn.' does not exist or is empty.</em></h2>'."\n"; } else { $maplayerscode = $ldcustom2; } break; } case(10): { if ($ldcustom3=='') { $this->_warnings .= '<h2 style="color: red;"><em>'.$ldcustom3fn.' does not exist or is empty.</em></h2>'."\n"; } else { $maplayerscode = $ldcustom3; } break; } case(11): $maplayerscode = $ldtransport; break; case(12): $maplayerscode = $ldlandscape; break; case(13): $maplayerscode = $ldoutdoors; break; case(14): $maplayerscode = $ldmapquest; break; case(15): $maplayerscode = $ldopentopo; break; case(16): $maplayerscode = $ldopnv; break; default: $maplayerscode = $ldmapnik; break; } if (is_array($maplayers)) { foreach ($maplayers as $ml) { switch ($ml) { case(0): { if (!($maplayer==0)) { $maplayerscode .= $ldmapnik; } break; } case(1): { if (!($maplayer==1)) { $maplayerscode .= $ldcycle; } break; } case(2): { if (!($maplayer==2)) { $maplayerscode .= $ldmapnikde;} break; } case(3): { if (!($maplayer==3)) { $maplayerscode .= $ldhikebike;} break; } case(4): { if (!($maplayer==4) and ($enablegooglemaps==1)) { $maplayerscode .= $ldgooglestr; } break; } // 2013-02-16 fix - str & hyb exchanged case(5): { if (!($maplayer==5) and ($enablegooglemaps==1)) { $maplayerscode .= $ldgooglephy; } break; } case(6): { if (!($maplayer==6) and ($enablegooglemaps==1)) { $maplayerscode .= $ldgooglehyb; } break; } case(7): { if (!($maplayer==7) and ($enablegooglemaps==1)) { $maplayerscode .= $ldgooglesat; } break; } case(8): { if (!($maplayer==8)) { if ($ldcustom1=='') { $this->_warnings .= '<h2 style="color: red;"><em>'.$ldcustom1fn.' does not exist or is empty.</em></h2>'."\n"; } else { $maplayerscode .= $ldcustom1; } } break; } case(9): { if (!($maplayer==9)) { if ($ldcustom2=='') { $this->_warnings .= '<h2 style="color: red;"><em>'.$ldcustom2fn.' does not exist or is empty.</em></h2>'."\n"; } else { $maplayerscode .= $ldcustom2; } } break; } case(10): { if (!($maplayer==10)) { if ($ldcustom3=='') { $this->_warnings .= '<h2 style="color: red;"><em>'.$ldcustom3fn.' does not exist or is empty.</em></h2>'."\n"; } else { $maplayerscode .= $ldcustom3; } } break; } case(11): { if (!($maplayer==11)) { $maplayerscode .= $ldtransport;} break; } case(12): { if (!($maplayer==12)) { $maplayerscode .= $ldlandscape;} break; } case(13): { if (!($maplayer==13)) { $maplayerscode .= $ldoutdoors;} break; } case(14): { if (!($maplayer==14)) { $maplayerscode .= $ldmapquest;} break; } case(15): { if (!($maplayer==15)) { $maplayerscode .= $ldopentopo;} break; } case(16): { if (!($maplayer==16)) { $maplayerscode .= $ldopnv;} break; } } } } $hillshading = ''; // V1.3.2 2014-12-21: Hillshading / HikeBikeMap on new server, numZoomLevels added // so hillshading layer will be hidden on large zoom instead of showing pink tiles. // This does not work in combination with Bing maps - the x/y/z get messed up, no idea why... // OLD URL: http://toolserver.org/~cmarqu/hill/ if ($this->_params['maphillshading'] >= 1) { $hillshading = 'var hillshading = new OpenLayers.Layer.TMS("'. JTEXT::_("PLG_CONTENT_GTM_MAPHILLSHADING_LABEL").'", "http://a.tiles.wmflabs.org/hillshading/",'."\n". '{type: \'png\', getURL: osm_getTileURL, displayOutsideMaxExtent: true, '."\n". 'isBaseLayer: false, numZoomLevels: 16, transparent: true, "visibility": true}); '.$mapvar.'.addLayer(hillshading); '."\n"; // adding a second hillshading layer makes the effect more intense. if ($this->_params['maphillshading'] >= 2) { $hillshading .= 'var hillshading2 = new OpenLayers.Layer.TMS("'. JTEXT::_("PLG_CONTENT_GTM_MAPHILLSHADING_LABEL").' (2)", "http://a.tiles.wmflabs.org/hillshading/",'."\n". '{type: \'png\', getURL: osm_getTileURL, displayOutsideMaxExtent: true, '."\n". 'isBaseLayer: false, numZoomLevels: 16, transparent: true, "visibility": true}); '.$mapvar.'.addLayer(hillshading2); '."\n"; } } $markerpath = $this->_markers_dir; // optional markers at the start and end of the track $startmarkerfn = $this->markerFilename($this->_params['startmarker'],$this->_params['markerset']); $endmarkerfn = $this->markerFilename($this->_params['endmarker' ],$this->_params['markerset']); // if we have a marker, add the openlayer code to show it: // V1.2.3 fix: ...OR if waypoint marker symbols are enabled, they are on the same layer! if (($startmarkerfn=='') and ($endmarkerfn=='') and ($this->_params['wpshow'] == 0) and ($this->_params['wpsymbols'] == 0)) { $markerlayer = ''; $markercode = ''; } else { $markerlayer = ' layerMarkers'.$_SESSION["gtmcount"].' = new OpenLayers.Layer.Markers("Marker"); '. $mapvar.'.addLayer(layerMarkers'.$_SESSION["gtmcount"].'); '; $markercode = ''; if (!($startmarkerfn=='')) { $markercode .= ' var startpoint = this.features[0].geometry.components[0];'."\n". ' var startsize = new OpenLayers.Size(21, 25);'."\n". ' var startoffset = new OpenLayers.Pixel(-(startsize.w/2), -startsize.h);'."\n". ' var starticon = new OpenLayers.Icon("'.$markerpath.$startmarkerfn.'",startsize,startoffset);'."\n". ' layerMarkers'.$_SESSION["gtmcount"].'.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(startpoint.x, startpoint.y),starticon));'."\n"; } if (!($endmarkerfn=='')) { $markercode .= ' var endpoint = this.features[0].geometry.components[this.features[0].geometry.components.length-1];'."\n". ' var endsize = new OpenLayers.Size(21, 25);'."\n". ' var endoffset = new OpenLayers.Pixel(-(endsize.w/2), -endsize.h);'."\n". ' var endicon = new OpenLayers.Icon("'.$markerpath.$endmarkerfn.'",endsize,endoffset);'."\n". ' layerMarkers'.$_SESSION["gtmcount"].'.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(endpoint.x, endpoint.y),endicon));'."\n"; } } switch ($this->_params['trackstyle']) { case(1): $trackdashstyle = '"dot"'; break; case(2): $trackdashstyle = '"dash"'; break; case(3): $trackdashstyle = '"dashdot"'; break; case(4): $trackdashstyle = '"longdash"'; break; case(5): $trackdashstyle = '"longdashdot"'; break; default: $trackdashstyle = '"solid"'; } switch ($this->_params['wpshow']) { case(1): $extractcode = 'extractWaypoints: true, extractRoutes: true, extractAttributes: true'; break; default: $extractcode = 'extractWaypoints: false, extractRoutes: true, extractAttributes: true'; } // V1.4.0: added option for fixed zoom level. if (($this->_params['zoomlevel'] > 0) and ($this->_params['zoomlevel'])<=20) { $zoomcode = ' this.map.zoomToExtent(this.getDataExtent(),true);'; // needed to center the map $zoomcode .= ' this.map.zoomTo('.$this->_params['zoomlevel'].');'."\n"; } else { // old behaviour (zoomlevel=0): This one will always auto-zoom on the track's extent: $zoomcode = ' this.map.zoomToExtent(this.getDataExtent(),true);'; // 2nd param= zoom to closest level // option to zoom back out one level when track is to "tight" in the boundaries of the auto-zoomed map. // zoomout is actually a zoomDELTA param, where zoomout=2 will zoom out twice, while zoomout=-1 will zoom IN once. // V1.1.4: fixed zoomout = 0 and 2nd for loop as provided by Amos. if (($this->_params['zoomout'] != 0) and (($this->_params['zoomout'])>-15) and ($this->_params['zoomout'])<15) // sanity check { $lvl = $this->_params['zoomout']; if ($lvl > 0) { for ($i=1; $i <= $lvl; $i++) { $zoomcode .= ' this.map.zoomOut();'."\n"; } } else { for ($i=-1; $i >= $lvl; $i--) { $zoomcode .= ' this.map.zoomIn();'."\n"; } } } } $ticode= ''; $edurl = ''; $spdurl = ''; // init $this->_params['haseledata'] = 0; $this->_params['hasspddata'] = 0; $wptcode = ''; if (($this->_params['ti'] == 1) or ($this->_params['ed'] == 1) or ($this->_params['spd'] == 1) or ($this->_params['wpshow'] != 0)) { $tivars = $this->getGpxFileInfo($gpx_dir,$gpx_file); // V1.2.1 fix: if parsing found no <trk>, clear marker code: if ($tivars[2] == 0) { $markercode = ''; } if (($this->_params['wpshow'] == 1) and ($tivars['wptcount'] > 0)) { // V1.2.2 fix: waypoints would show even when turned off $wptcode = $this->makeWptCode($tivars['wptcount'],$tivars['wpts'],$mapvar,$_SESSION["gtmcount"]); } $edurl = $this->_live_site.$this->_rootfolder.$tivars[0]; $spdurl = $this->_live_site.$this->_rootfolder.$tivars[1]; $edurl = $gpx_basepath.$tivars[0]; $spdurl = $gpx_basepath.$tivars[1]; } else { $tivars = array(); } // V1.3.0 allow selection of mootools or jQuery way of adding OnLoad events: if ($this->params->get('usejquery',0) == 1) { $windoweventcode = "jQuery(window).on('load',function()"; // jQuery } else { // code Joomla 3 $windoweventcode = "window.addEvent('load',function()"; // mootools $windoweventcode = "window.addEventListener('load',function()"; // plus de mootools } $mapclass = 'gpxtrackmap'; // CSS class for the DIV tag the map is shown in $gpxlayername = 'GPX Track'; // TODO: make mapclass and gpxlayername configurable // V1.2.1 beta 3 fix: replace blanks in gpx path with %20 for openlayers URL to the track $gpx_path = str_replace(' ', '%20', $gpx_path); // V1.3.3: fullscreen controls $fsctrls = ''; $fsctrlsfn = ''; if ( $this->_params['mapfullscreen'] == 1 ) { if ($this->_params['mappan'] == 1) { $fsctrlsfn = $plginpath.'fullscreencontrols_navbar.html'; } else { $fsctrlsfn = $plginpath.'fullscreencontrols_buttons.html'; } if (file_exists($fsctrlsfn)) { $fsctrls = file_get_contents($fsctrlsfn); $scripttext = $scripttext."\n".$fsctrls; } } // placeholders in the script template: $srch = array('%MAPVAR%','%GPXPATH%','%NOMOUSEWHEELZOOM%','%MAPLAYERS%','%MARKERLAYER%','%GPXLAYERNAME%', '%MAPCONTROLS%','%ZOOMCODE%', '%TRACKCOLOR%','%TRACKWIDTH%','%TRACKOPACITY%','%TRACKDASHSTYLE%','%MARKERCODE%','%MAPCLASS%', '%WPCOLOR%','%WPRADIUS%','%EXTRACTCODE%','%HILLSHADINGLAYER%', '%WPTCODE%', '%WINDOWEVENTCODE%', '%MAPWIDTH%','%MAPHEIGHT%','%MAPFULLSCREEN_ENTER%','%MAPFULLSCREEN_EXIT%'); // V1.3.3 fullscreen toggle // what they will be replaced with: $repl = array($mapvar,$gpx_path,$nomousewheelzoom,$maplayerscode,$markerlayer,$gpxlayername, $mapcontrols,$zoomcode, $this->_params['trackcolor'],$this->_params['trackwidth'],$this->_params['trackopacity'],$trackdashstyle, $markercode,$mapclass, $this->_params['wpcolor'],$this->_params['wpradius'],$extractcode,$hillshading, $wptcode, $windoweventcode, $this->_params['mapwidth'], $this->_params['mapheight'], JTEXT::_("PLG_CONTENT_GTM_MAPFULLSCREEN_ENTER"), JTEXT::_("PLG_CONTENT_GTM_MAPFULLSCREEN_EXIT")); // V1.3.3 fullscreen toggle // replace all the placeholders in the openlayer script template with the params: $mapcode = str_replace($srch,$repl,$scripttext); $mapcode .= '<div class="'.$mapclass.'"'; if (($this->_params['mapwidth']!='0') OR ($this->_params['mapheight']!='0')) { $mapcode .= ' style="'; if ($this->_params['mapwidth']!='0') { $mapcode .= 'width:'.$this->_params['mapwidth'].'; '; } if ($this->_params['mapheight']!='0') { $mapcode .= 'height:'.$this->_params['mapheight'].'; '; } $mapcode .= '"'; } $mapcode .= ' id="'.$mapvar.'"></div>'; // optional track infos $tiplaceholders = array(// placeholders for the track info '%ELEDIAGURL%','%SPDDIAGURL%','%TRACKPOINTS%','%DISTANCE-KM%','%DISTANCE-MI%','%DISTANCE-NM%', '%ELE-UP-M%','%ELE-DOWN-M%','%ELE-MIN-M%','%ELE-MAX-M%','%ELE-DELTA-M%', '%ELE-UP-FT%','%ELE-DOWN-FT%','%ELE-MIN-FT%','%ELE-MAX-FT%','%ELE-DELTA-FT%', '%STARTTIME%','%ENDTIME%','%DURATION%','%DURATIONMOVING%','%DURATIONPAUSED%', '%AVGSPEED-KMH%','%AVGSPEED-MPH%','%AVGSPEED-KN%', '%AVGSPEEDUP-KMH%','%AVGSPEEDUP-MPH%','%AVGSPEEDUP-KN%', '%AVGSPEEDDOWN-KMH%','%AVGSPEEDDOWN-MPH%','%AVGSPEEDDOWN-KN%', '%AVGSPEEDMOVING-KMH%','%AVGSPEEDMOVING-MPH%','%AVGSPEEDMOVING-KN%', '%MAXSPEED-KMH%','%MAXSPEED-MPH%','%MAXSPEED-KN%', '%MAXSPEEDUP-KMH%','%MAXSPEEDUP-MPH%','%MAXSPEEDUP-KN%', '%MAXSPEEDDOWN-KMH%','%MAXSPEEDDOWN-MPH%','%MAXSPEEDDOWN-KN%', '%TRACKPOINTDISTANCE-M%','%TRACKPOINTDISTANCE-FT%'); // elevation diagram $edcode = ''; if (($this->_params['ed'] == 1) and ($this->_params['haseledata'] == 1)) { $edwidth = $this->_params['edwidth']; $edheight = $this->_params['edheight']; $edcode = '<img class="gpxtrackdiagram" src="'.$edurl.'"'; if (($edwidth!='0') OR ($edheight!='0')) { $edcode .= ' style="'; if ($edwidth!='0') { $edcode .= 'width:'.$edwidth.' ! important; '; } if ($edheight!='0') { $edcode .= ' height:'.$edheight.' ! important;'; } $edcode .= '"'; } $edcode .= "/>"."\n"; } // speed diagram $spdcode = ''; if (($this->_params['spd'] == 1) and ($this->_params['hasspddata'] == 1)) { $spdwidth = $this->_params['spdwidth']; $spdheight = $this->_params['spdheight']; $spdcode = '<img class="gpxspeeddiagram" src="'.$spdurl.'"'; if (($spdwidth!='0') OR ($spdheight!='0')) { $spdcode .= ' style="'; if ($spdwidth!='0') { $spdcode .= ' width:'.$spdwidth.' ! important;'; } if ($spdheight!='0') { $spdcode .= ' height:'.$spdheight.' ! important;'; } $spdcode .= '"'; } $spdcode .= "/>"."\n"; } // optional download link for the gpx file: $dlcode = ''; if ($this->_params['dl'] == 1) { if ($this->_params['dlzip']==1) { $zip_fn = $this->ziptrackfile($this->_rootfolder,$gpx_file); if ($zip_fn) { $gpx_path = $this->_live_site.$zip_fn; } // otherwise (sthg went wrong zipping) leave .gpx file... } $dltext = str_replace('%s',basename($gpx_path),$this->_params['dltext']); $cssstyle = ''; if (!($this->_params['dlstyle']=='')) { $cssstyle = ' style="'.$this->_params['dlstyle'].'"'; } // problem if you don't use the zip option: click on button will leave the page and show the gpx file contents in the browser. // if text link is used, it will at least open it in a new tab, but still display the file contents. hmmm. if ($this->_params['dltype']==0) // text link { $dlcode = '<div class="'.$this->_params['dlclass'].'"'.$cssstyle.'>'. '<a href="'.$gpx_path.'" type="application/gpx+xml" download="'.$gpx_file.'" target="_blank">'.$dltext.'</a></div>'; //v1.2.3 the MIMEtype and download clause _should_ force browsers to download the gpx file instead of displaying it, // but this still doesn't work in all browsers. So it's still best to use the ZIP option... } else { $dlcode = '<form class="'.$this->_params['dlclass'].'"'.$cssstyle.'><input type="button" value="'.$dltext.'" '. 'onclick="window.location.href='."'".$gpx_path."'".'" /></form>'; } } // now place the different parts (map, trackinfos, elevation diagram, download link) into the html template: $gtmcode = $tpltext; // replace placeholders for the track info elements $gtmcode = str_replace($tiplaceholders,$tivars,$gtmcode ); // replace placeholders for the map, elevation diagram, speed diagram and download link $placeholders = array('%TRACKMAP%','%TRACKDIAGRAM%','%SPEEDDIAGRAM%','%TRACKDOWNLOAD%'); $vars = array($mapcode,$edcode,$spdcode,$dlcode); $gtmcode = str_replace($placeholders,$vars,$gtmcode ); $gtmcode = '<!-- GPXTrackmap '.$this->_gtmversion.' #'.$_SESSION["gtmcount"].' START -->'."\n".$gtmcode."\n".'<!-- GPXTrackmap #'.$_SESSION["gtmcount"].' END -->'."\n"; } // if !gpxfile exists..else // ok - ready for injection: if ((!$this->_warnings=='') AND ($this->_params['showwarnings']==1)) // V1.3.1 option to turn off warnings { $gtmcode = '<p style="color:yellow; background:red;">'. 'GPXTrackMap plugin warnings:<br />'. $this->_warnings.'</p>'.$gtmcode; } $regex = "@(<p>)?{gpxtrackmap}".$gpx_code."{/gpxtrackmap}(</p>)?@s"; // replace the invoking code with the openlayer js code // and the DIV for the map in the article text: $article->text = preg_replace($regex, $gtmcode, $article->text); unset($gpx_array); // for next loop if we have multiple maps on the page $this->_warnings = ''; } // foreach match } // if <matches found> } private function collectParams() { $names = array( 'mapwidth','mapheight','maplayer','mapnav','mappan','mapzoombtns','mapfullscreen','mapswitch','maplayers','mapgraticule','maphillshading', 'mapscale','mapwheelzoom','mapoverview','mapmousepos','zoomout', 'trackcolor','trackwidth','trackopacity','trackstyle', 'wpshow','wpradius','wpcolor','wppopups','wppopupwidth','wppopupheight','wppopupele','wppopuptimefmt','wppopupdesc','wppopupdescbb','wppopuplinkfmt','wpsymbols', 'startmarker','endmarker','markerset', 'ti','tidecimalsep','tidatefmt','titimefmt','titimeshift','timovespeed', 'dl','dltext','dltype','dlzip','dlclass','dlstyle', 'ed','edwidth','edheight','edlinecolor','edlinewidth','edbgcolor','edfilterorder','edfillmode','edupcolor','eddowncolor','edunits', 'edxgrid','edxgridunits','edxgridlimit','edxgridcolor','edxgridwidth','edygridlines','edygridwidth','edygridcolor', 'spd','spdwidth','spdheight','spdlinecolor','spdlinewidth','spdbgcolor','spdfilterorder','spdfillmode','spdupcolor','spddowncolor','spdunits', 'spdxgrid','spdxgridunits','spdxgridlimit','spdxgridcolor','spdxgridwidth','spdygridlines','spdygridwidth','spdygridcolor', 'cache','tpl','usejquery','showwarnings','zoomlevel','tfapikey'); // expand any preset in the call to its full set of params $this->expandPresets($this->_params,$this->params->get('presets'),$names); // add in everything that was not in the invocation OR in any of the templates from the back-end params - that is, apply defaults: foreach ($names as $name) { if (!array_key_exists($name, $this->_params)) { $this->_params[$name] = $this->params->get($name); } } } private function expandPresets(&$syntaxparams,$backendpresets,$paramnames) { // preset expansion: presets are processed one by one, param by param // when multiple presets are used, the last found setting will "win" - // but individual settings in the call will always win over any preset setting(!) $presets = explode("\n",$backendpresets); foreach ($syntaxparams as $key => $value) { if (($key=='preset') or ($key=='ps')) // $value holds a single preset name OR "tname1-tname2-tname3" { $psetcalls = explode('-',$value); // preset=t1-t2-t3 -> [t1] [t2] [t3] foreach ($psetcalls as $psetcall) // apply each preset in the order of appearance { $psetcall = strtolower(trim($psetcall)); $tfound = 0; foreach ($presets as $presetline) // test each preset call against each preset we have { if (trim($presetline) !== '') { $p = strpos($presetline,':'); // split preset line into preset name and params: where's the ":"?? if ($p === false) // "presets" lines from the backend must have "<name>:<params>" syntax, or it all won't work! { $this->_warnings .= 'Syntax error in preset: '.$presetline.'<br />'."\n"; } else { $psetname = strtolower(trim(substr($presetline,0,$p))); //TODO: strtolower:OK, but trim+substr? REQUIRED?? $psetparams = substr($presetline,$p+1,strlen($presetline)); // see above... if ($psetname==$psetcall) // gotcha! we found (one line of) our preset, apply its params! { $tfound += 1; $tparams_values = explode(',',$psetparams); // preset params into "key=value" strings foreach($tparams_values as $tparam_value) { $key_value = explode('=',$tparam_value); // "key=value" into array[2] $spname = strtolower(trim($key_value[0])); // V1.1.4 fix: individual params should win over preset params, so only use // the preset param if there was no other setting in the invocation: if (!array_key_exists($spname, $syntaxparams)) { $syntaxparams[$spname] = trim($key_value[1]); } } } } } } //foreach presetline we have if ($tfound==0) { $this->_warnings .= 'unknown preset called: "'.$psetcall.'"<br />'."\n"; } } // foreach preset call we found } else { // $key was sthg. else than "preset" or "t": // reverse check here to see if there's any misspelled or unknown parameters in the params from the call: if (!in_array($key,$paramnames)) { $this->_warnings .= 'unknown parameter: "'.$key.'"'."\n"; } } } } private function getGpxFileInfo($filepath,$filename) { $lat = array(); $lon = array(); $ele = array(); $dist = array(); $distdelta = array(); // in km: distance delta between two trackpoints $tim = array(); $speed = array(); // in km/h $hr = array(); // heart rate $cad = array(); // cadence $atemp = array(); // temperature $wpts = array(); // waypoints $n = 0; // get all the waypoint's data: min/max elevation, start and end time, coords $found_ele = 0; // flags if we found any elevation tags $found_time = 0; // flags if we found any time tags $found_wpts = 0; // V1.2.1 fix: properly initialize speeds, the may be left undefined otherwise: $avgspeeddown_kmh = ''; $avgspeeddown_mph = ''; $avgspeeddown_kn = ''; $avgspeedup_kmh = ''; $avgspeedup_mph = ''; $avgspeedup_kn = ''; /* work in progress: read heart rate, cadence and temperature curves $found_hr = 0; // flags if we found any heart rate (hr) tags in TrackPointExtension subtags $found_cad = 0; // flags if we found any cadence (cad) tags $found_atemp = 0; // flags if we found any cadence (cad) tags */ date_default_timezone_set('UTC'); $ts = 0; if (! JFile::exists($filepath.$filename)) { return array (); } /* 2016-12-27 added "@" to suppress gpxx Namespace Warnings thrown by simplexml_load_file */ $gpx = @simplexml_load_file($filepath.$filename); $starttime = 0; $endtime = 0; foreach ($gpx->trk as $trk) { //V1.2.5 auto track color from Garmin files // <extensions> // <gpxx:TrackExtension> // <gpxx:DisplayColor>DarkGray</gpxx:DisplayColor> // </gpxx:TrackExtension> // </extensions> // // if ($this->_params['trackcolor']=='auto') { // foreach ($trk->extensions as $trkexts) { // foreach ($trkexts->gpxx:TrackExtension as $trkext) { //echo($trkext); // } // } // } foreach ($trk->trkseg as $trkseg) { foreach ($trkseg->trkpt as $tpt) { $attrs = $tpt->attributes(); $lat[$n] = (float)$attrs['lat']; $lon[$n] = (float)$attrs['lon']; if ((float)$tpt->ele != 0) { $ele[$n] = (float)$tpt->ele; $found_ele = 1; } else { $ele[$n] = 0; } $ts = $tpt->time; if ((string)$ts != '') { $found_time = 1; $tim[$n] = $this->getGPXTime($ts); // V1.1.4 } else { $tim[$n] = 0; } if ($n == 0) { $minele_m = $ele[$n]; $maxele_m = $ele[$n]; $starttime = $this->getGPXTime($ts); } else { if ($ele[$n] < $minele_m) { $minele_m = $ele[$n]; } if ($ele[$n] > $maxele_m) { $maxele_m = $ele[$n]; } } /* // V1.1.4 experimental: read temp, heart rate, cadence from Strava GPX file foreach ($tpt->extensions as $tpext) { foreach ($tpext->children('gpxtpx',TRUE) as $gpxtpx) { // <gpxtpx:TrackPointExtension> foreach ($gpxtpx->children('gpxtpx',TRUE) as $gpxtpxelement) { switch ($gpxtpxelement->getName()) { case ('hr') : $hr[$n] = (float)$gpxtpxelement; $found_hr = 1; break; // <gpxtpx:hr> case ('cad') : $cad[$n] = (float)$gpxtpxelement; $found_cad = 1; break; // <gpxtpx:cad> case ('atemp'): $atemp[$n] = (float)$gpxtpxelement; $found_atemp = 1; break; // <gpxtpx:atemp> } } } } */ $n++; } } } if ($n > 0) { $endtime = $this->getGPXTime($ts); } // read Waypoint data if popups are activated $wptcount = 0; if ($this->_params['wppopups'] !== 0) { foreach ($gpx->wpt as $wpt) { $found_wpts = 1; $attrs = $wpt->attributes(); $wptlat = (float)$attrs['lat']; $wptlon = (float)$attrs['lon']; if ((string)$wpt->time != '') { $wpttime = $this->getGPXTime($wpt->time); } else { $wpttime = ''; } if ((string)$wpt->ele != '') { $wptele = (float)$wpt->ele; } else { $wptele = ''; } if ((string)$wpt->sym != '') { $wptsym = (string)$wpt->sym; // 'Flag, Green' or similar - currently not used } else { $wptsym = ''; } $wptname = (string)$wpt->name; $wptdesc = strtr((string)$wpt->desc,'"','\"'); if ($wptdesc == '') { $wptdesc = strtr((string)$wpt->description,'"','\"'); } //V1.2.3: since Basecamp doesn't allow HTML in waypoint descriptions, // BBCode can allow at least some basic formatting: if ($this->_params['wppopupdescbb'] == 1) { $bbcode = array( "/\[br\]/is" => "<br />", "/\[b\](.*?)\[\/b\]/is" => "<strong>$1</strong>", "/\[u\](.*?)\[\/u\]/is" => "<u>$1</u>", "/\[i\](.*?)\[\/i\]/is" => "<i>$1</i>", "/\[code\](.*?)\[\/code\]/is" => "<pre>$1</pre>", "/\[quote\](.*?)\[\/quote\]/is" => "<blockquote>$1</blockquote>", "/\[url\=(.*?)\](.*?)\[\/url\]/is" => "<a href='$1' target='_self'>$2</a>", "/\[img\](.*?)\[\/img\]/is" => "<img src='$1' alt='' />" ); $wptdesc = preg_replace(array_keys($bbcode), array_values($bbcode), $wptdesc); } $wptlinks = ''; $linkno = 1; foreach ($wpt->link as $wptlink) { $attrs = $wptlink->attributes(); $wpthref = (string)$attrs['href']; $wptlinks .= $wpthref."\n"; if ($this->_params['wppopupdescbb'] == 1) { $bbcode = array( "/\[link".$linkno."\](.*?)\[\/link".$linkno."\]/is" => "<a href='".$wpthref."' target='_blank'>$1</a>"); $wptdesc = preg_replace(array_keys($bbcode), array_values($bbcode), $wptdesc); } $linkno += 1; } $wpts[] = array('lat' => $wptlat, 'lon' => $wptlon, 'ele' => $wptele, 'time' => $wpttime, 'name' => $wptname, 'desc' => $wptdesc, 'sym' => $wptsym, 'links' => $wptlinks); $wptcount += 1; } } // calculate the track length // source: http://wiki.openstreetmap.org/wiki/User:Aighes/GPX-Track_auf_Website $r0 = 6371.0; // earth radius in [km] $distance_km = 0.0; $duration_moving = 0; $duration_paused = 0; if ($n > 0) { for ($i = 0; $i < ($n-1); $i++) { $a = 0; $b = 0; $c = 0; $distdelta[$i] = 0.0; $speed[$i] = 0.0; if (($lat[$i] !== $lat[$i+1]) and ($lon[$i] !== $lon[$i+1])) { $a = deg2rad(90.0 - $lat[$i]); $b = deg2rad(90.0 - $lat[$i+1]); $gamma = deg2rad(abs($lon[$i+1] - $lon[$i])); $c = $r0 * acos(cos($a)*cos($b) + sin($a)*sin($b)*cos($gamma)); $distdelta[$i] = $c; $distance_km += $c; // the speed calculation is problematic when the trackpoint recording frequency is high, // since the timestamps only resolve to seconds. if ($found_time == 1) { if ((abs($tim[$i]-$tim[$i+1])>1) and ($c != 0.0)) { $speed[$i] = $c / ($tim[$i+1]-$tim[$i]) * 60 * 60; } else { // if distance is less or equal 1s, try to use the trackpoint before the current one to have better accuracy. // not an optimal solution either, but better than calculating with 1s intervals... if (($i>0) and (abs($tim[$i-1]-$tim[$i+1])>1) and ($c != 0.0)) { $speed[$i] = ($distdelta[$i-1]+$c) / ($tim[$i+1]-$tim[$i-1]) * 60 * 60; } } if ($speed[$i] > $this->_params['timovespeed']) { // default: 2.0 km/h $duration_moving += $tim[$i+1]-$tim[$i]; } else { $duration_paused += $tim[$i+1]-$tim[$i]; } } } $dist[$i] = $distance_km; } // fill up last array indexes: $dist[$n-1] = $distance_km; $distdelta[$n-1] = 0.0; $speed[$n-1] = 0.0; $dist[$n] = $distance_km; $distdelta[$n] = 0.0; $speed[$n] = 0.0; // anti-alias speed: if ($this->_params['spdfilterorder'] > 1) { $speed = $this->filterSignal($speed,$n,$this->_params['spdfilterorder']); } } // if n>0 $m_ft = 1 / 0.3048; $kmh_mph = 1 / 1.609; $kmh_kn = 1 / 1.852; // average distance of two trackpoints // fix for error reported by Steve in the forum on 2013-02-13: GPX files w/o any waypoints // can report $n = 0, that again would cause a "div by 0" error in the following: if ($n>0) { $tpdistance_m = round($distance_km / $n * 1000,2); } else { $tpdistance_m = 0; } $tpdistance_ft = round($tpdistance_m * $m_ft,2); // round distances - more precision would be pretentious :-) $distance_mi = round($distance_km * $kmh_mph, 1); $distance_nm = round($distance_km * $kmh_kn, 1); // V1.1.4 added nautical miles $distance_km = round($distance_km, 1); $maxspeed_kmh = 0.0; for ($i=0; $i < ($n-1); $i++) { if ($speed[$i] > $maxspeed_kmh) { $maxspeed_kmh = $speed[$i]; } } // V1.1.4: same for the max. speed $maxspeed_mph = round($maxspeed_kmh * $kmh_mph, 1); $maxspeed_kn = round($maxspeed_kmh * $kmh_kn, 1); $maxspeed_kmh = round($maxspeed_kmh, 1); // add up/down meters $maxspeedup_kmh = 0.0; $maxspeeddown_kmh = 0.0; if ($found_ele == 1) { $up_m = 0.0; $down_m = 0.0; $timeup = 0; // seconds $timedown = 0; $distup = 0.0; // km $distdown = 0.0; // Note: summing up the up/down deltas is not a very good way to calculate the up/down meters, if the elevation data has // a lot of "jitter" or "ripple" - so the results will not be very exact. // one option is to use tools like GPSBabel to filter the GPX track to get better accuracy. // in a first attempt we can do some optional "anti-aliasing" of rippled elevation data with a filter of a given order: // (note: Garmin Basecamp e.g. doesn't do any filtering here and happily reports the same values as with order 0 or 1 (= no filtering). // Magic Maps even reports MORE up/down meters (?!?) than the simple delta addition... no idea how they come up with THAT...) if ($this->_params['edfilterorder'] > 1) { $ele = $this->filterSignal($ele,$n,$this->_params['edfilterorder']); } for ($i=0; $i < ($n-1); $i++) { if ($ele[$i] < $ele[$i+1]) { $up_m += $ele[$i+1] - $ele[$i]; if ($found_time == 1) { if ($speed[$i] > $maxspeedup_kmh) { $maxspeedup_kmh = $speed[$i]; } $timeup += $tim[$i+1]-$tim[$i]; $distup += $distdelta[$i]; } } if ($ele[$i] > $ele[$i+1]) { $down_m += $ele[$i] - $ele[$i+1]; if ($found_time == 1) { if ($speed[$i] > $maxspeeddown_kmh) { $maxspeeddown_kmh = $speed[$i]; } $timedown += $tim[$i+1]-$tim[$i]; $distdown += $distdelta[$i]; } } } if (($timedown>0) and ($distdown>0.0)) { $avgspeeddown_kmh = $distdown / $timedown * 60 * 60; $avgspeeddown_mph = round($avgspeeddown_kmh * $kmh_mph, 1); $avgspeeddown_kn = round($avgspeeddown_kmh * $kmh_kn, 1); $avgspeeddown_kmh = round($avgspeeddown_kmh, 1); } if (($timeup>0) and ($distup>0.0)) { $avgspeedup_kmh = $distup / $timeup * 60 * 60; $avgspeedup_mph = round($avgspeedup_kmh * $kmh_mph, 1); $avgspeedup_kn = round($avgspeedup_kmh * $kmh_kn, 1); $avgspeedup_kmh = round($avgspeedup_kmh, 1); } $maxspeedup_mph = round($maxspeedup_kmh * $kmh_mph, 1); $maxspeedup_kn = round($maxspeedup_kmh * $kmh_kn, 1); $maxspeedup_kmh = round($maxspeedup_kmh, 1); $maxspeeddown_mph = round($maxspeeddown_kmh * $kmh_mph, 1); $maxspeeddown_kn = round($maxspeeddown_kmh * $kmh_kn, 1); $maxspeeddown_kmh = round($maxspeeddown_kmh, 1); // round all elevations - don't pretend better accuracy than there actually is... $up_m = round($up_m); $down_m = round($down_m); $minele_m = round($minele_m); $maxele_m = round($maxele_m); $deltaele_m = round($maxele_m-$minele_m); $up_ft = round($up_m * $m_ft); $down_ft = round($down_m * $m_ft); $minele_ft = round($minele_m * $m_ft); $maxele_ft = round($maxele_m * $m_ft); $deltaele_ft = round( ($maxele_m-$minele_m) * $m_ft); } //v1.2.3 fix: clear vars if ti=0 if ( ($found_ele != 1) or ($this->_params['ti'] != 1) ) { $down_m = "n/a"; $up_m = "n/a"; $minele_m = "n/a"; $maxele_m = "n/a"; $deltaele_m = "n/a"; $down_ft = "n/a"; $up_ft = "n/a"; $minele_ft = "n/a"; $maxele_ft = "n/a"; $deltaele_ft = "n/a"; $avgspeedup_kmh = "n/a"; $avgspeeddown_kmh = "n/a"; $avgspeedup_mph = "n/a"; $avgspeeddown_mph = "n/a"; $avgspeedup_kn = "n/a"; $avgspeeddown_kn = "n/a"; $maxspeedup_kmh = "n/a"; $maxspeeddown_kmh = "n/a"; $maxspeedup_mph = "n/a"; $maxspeeddown_mph = "n/a"; $maxspeedup_kn = "n/a"; $maxspeeddown_kn = "n/a"; } if ($found_time == 1) { $starttimestr = strftime($this->_params['tidatefmt'],$starttime); $endtimestr = strftime($this->_params['tidatefmt'],$endtime); $durationstr = strftime($this->_params['titimefmt'],$endtime-$starttime); $durationmovingstr = strftime($this->_params['titimefmt'],$duration_moving); $durationpausedstr = strftime($this->_params['titimefmt'],$duration_paused); if ($endtime !== $starttime) { // avoids div by 0 $avgspeed_kmh = round($distance_km / ($endtime-$starttime) * 60 * 60,1); $avgspeed_mph = round($distance_mi / ($endtime-$starttime) * 60 * 60,1); $avgspeed_kn = round($distance_nm / ($endtime-$starttime) * 60 * 60,1); } else { $avgspeed_kmh = "n/a"; $avgspeed_mph = "n/a"; $avgspeed_kn = "n/a"; } if ($duration_moving > 0) { // avoids div by 0 $avgspeedmoving_kmh = round($distance_km / ($duration_moving) * 60 * 60,1); $avgspeedmoving_mph = round($distance_mi / ($duration_moving) * 60 * 60,1); $avgspeedmoving_kn = round($distance_nm / ($duration_moving) * 60 * 60,1); } else { $avgspeedmoving_kmh = "n/a"; $avgspeedmoving_mph = "n/a"; $avgspeedmoving_kn = "n/a"; } } if ( ($found_time != 1) or ($this->_params['ti'] != 1) ) { $starttimestr = "n/a"; $endtimestr = "n/a"; $durationstr = "n/a"; $durationmovingstr = "n/a"; // V1.2.0 beta 2 fix $durationpausedstr = "n/a"; $avgspeed_kmh = "n/a"; $avgspeed_mph = "n/a"; $avgspeed_kn = "n/a"; $avgspeedmoving_kmh = "n/a"; // V1.2.0 beta 2 fix $avgspeedmoving_mph = "n/a"; $avgspeedmoving_kn = "n/a"; $maxspeed_kmh = "n/a"; $maxspeed_mph = "n/a"; $maxspeed_kn = "n/a"; } if (($found_ele == 1) and ($this->_params['ed'] == 1)) { $this->_params['haseledata'] = 1; // V1.1.4: option to show units in m or ft in elevation diagram $elediagfn = $this->renderDiagram($dist,$ele,$n,$minele_m,$maxele_m,$distance_km,$this->_params['edunits'],$filepath,$filename,'', $this->_params['edbgcolor'],$this->_params['edlinecolor'],$this->_params['edfillmode'],$this->_params['edupcolor'],$this->_params['eddowncolor'], $this->_params['edlinewidth'], $this->_params['edxgrid'],$this->_params['edxgridunits'],$this->_params['edxgridlimit'], $this->_params['edxgridwidth'],$this->_params['edxgridcolor'], $this->_params['edygridlines'],$this->_params['edygridwidth'],$this->_params['edygridcolor']); if ($elediagfn == "") { $this->_warnings .= 'Unable to write svg file into folder '.$filepath.'. Please check write permissions!'."\n"; } } else { $elediagfn = ''; } // V1.1.4: option to show speed diagram if (($found_time == 1) and ($this->_params['spd'] == 1)) { $this->_params['hasspddata'] = 1; $spddiagfn = $this->renderDiagram($dist,$speed,$n,0.0,$maxspeed_kmh,$distance_km,$this->_params['spdunits'],$filepath,$filename,'_speed', $this->_params['spdbgcolor'],$this->_params['spdlinecolor'],$this->_params['spdfillmode'],$this->_params['spdupcolor'],$this->_params['spddowncolor'], $this->_params['spdlinewidth'], $this->_params['spdxgrid'],$this->_params['spdxgridunits'],$this->_params['spdxgridlimit'], $this->_params['spdxgridwidth'],$this->_params['spdxgridcolor'], $this->_params['spdygridlines'],$this->_params['spdygridwidth'],$this->_params['spdygridcolor']); } else { $spddiagfn = ''; } $sep = $this->_params['tidecimalsep']; if ($sep !== '.') { $distance_km = str_replace('.',$sep,$distance_km); $distance_mi = str_replace('.',$sep,$distance_mi); $distance_nm = str_replace('.',$sep,$distance_nm); $up_m = str_replace('.',$sep,$up_m); $down_m = str_replace('.',$sep,$down_m); $minele_m = str_replace('.',$sep,$minele_m); $maxele_m = str_replace('.',$sep,$maxele_m); $deltaele_m = str_replace('.',$sep,$deltaele_m); $up_ft = str_replace('.',$sep,$up_ft); $down_ft = str_replace('.',$sep,$down_ft); $minele_ft = str_replace('.',$sep,$minele_ft); $maxele_ft = str_replace('.',$sep,$maxele_ft); $deltaele_ft = str_replace('.',$sep,$deltaele_ft); $avgspeed_kmh = str_replace('.',$sep,$avgspeed_kmh); $avgspeed_mph = str_replace('.',$sep,$avgspeed_mph); $avgspeed_kn = str_replace('.',$sep,$avgspeed_kn); $avgspeedup_kmh = str_replace('.',$sep,$avgspeedup_kmh); $avgspeedup_mph = str_replace('.',$sep,$avgspeedup_mph); $avgspeedup_kn = str_replace('.',$sep,$avgspeedup_kn); $avgspeeddown_kmh = str_replace('.',$sep,$avgspeeddown_kmh); $avgspeeddown_mph = str_replace('.',$sep,$avgspeeddown_mph); $avgspeeddown_kn = str_replace('.',$sep,$avgspeeddown_kn); $avgspeedmoving_kmh = str_replace('.',$sep,$avgspeedmoving_kmh); $avgspeedmoving_mph = str_replace('.',$sep,$avgspeedmoving_mph); $avgspeedmoving_kn = str_replace('.',$sep,$avgspeedmoving_kn); $maxspeed_kmh = str_replace('.',$sep,$maxspeed_kmh); $maxspeed_mph = str_replace('.',$sep,$maxspeed_mph); $maxspeed_kn = str_replace('.',$sep,$maxspeed_kn); $maxspeedup_kmh = str_replace('.',$sep,$maxspeedup_kmh); $maxspeedup_mph = str_replace('.',$sep,$maxspeedup_mph); $maxspeedup_kn = str_replace('.',$sep,$maxspeedup_kn); $maxspeeddown_kmh = str_replace('.',$sep,$maxspeeddown_kmh); $maxspeeddown_mph = str_replace('.',$sep,$maxspeeddown_mph); $maxspeeddown_kn = str_replace('.',$sep,$maxspeeddown_kn); $tpdistance_m = str_replace('.',$sep,$tpdistance_m); $tpdistance_ft = str_replace('.',$sep,$tpdistance_ft); } // v1.2.3 fix: clear track infos if ti=0 if ($this->_params['ti'] != 1) { $tpdistance_m = "n/a"; $tpdistance_ft = "n/a"; $distance_km = "n/a"; $distance_nm = "n/a"; $distance_mi = "n/a"; $n = "n/a"; } return array ( $elediagfn, $spddiagfn, $n, $distance_km, $distance_mi, $distance_nm, $up_m, $down_m, $minele_m, $maxele_m, $deltaele_m, $up_ft, $down_ft, $minele_ft, $maxele_ft, $deltaele_ft, $starttimestr, // $starttime, $endtimestr, // $endtime, $durationstr, // $endtime-$starttime $durationmovingstr, $durationpausedstr, $avgspeed_kmh, $avgspeed_mph, $avgspeed_kn, $avgspeedup_kmh, $avgspeedup_mph, $avgspeedup_kn, $avgspeeddown_kmh, $avgspeeddown_mph, $avgspeeddown_kn, $avgspeedmoving_kmh, $avgspeedmoving_mph, $avgspeedmoving_kn, $maxspeed_kmh, $maxspeed_mph, $maxspeed_kn, $maxspeedup_kmh, $maxspeedup_mph, $maxspeedup_kn, $maxspeeddown_kmh, $maxspeeddown_mph, $maxspeeddown_kn, $tpdistance_m, $tpdistance_ft, 'wptcount' => $wptcount, 'wpts' => $wpts); } private function expandWptSymbolFn($symbolfn) { $templateDir = $this->_live_site.DIRECTORY_SEPARATOR.'templates'.DIRECTORY_SEPARATOR. JFactory::getApplication()->getTemplate(); $dirs = array(substr($this->_plugin_dir,0,-1), substr($this->_live_site.$this->_rootfolder,0,-1), $templateDir); //echo("PluginDir:".$dirs[0]."<br />"); //echo("GPXDir:".$dirs[1]."<br />"); //echo("TemplateDir:".$dirs[2]."<br />"); $phs = array('%PLUGINDIR%','%GPXDIR%','%TEMPLATEDIR%'); // replace %TEMPLATES% placeholder in filenames with the plugin dir path $symfn = str_replace($phs,$dirs,$symbolfn); $symfn = strtr( $symfn , '\\', '/'); return $symfn; } private function getWptSymbolFn($symbol,&$symbolwidth,&$symbolheight,&$offsetleft,&$offsettop) { //todo: make default icon size configurable $symbolwidth = 16; $symbolheight = 16; // find symbol in mappings $mappings = explode("\n",$this->params->get('wpsymbolmappings')); // mappings in this format: symbol name["|"symbol name["|"symbolname]]=image file[","image width[","image height]] // Example: Water source|Picninc area=%GPXDIR%/icons/myicon.png,24,24 $defaultsymbolfn = '%PLUGINDIR%/markers/waypointmarker16.png'; foreach ($mappings as $mapping) { $parts = explode('=',$mapping); $syms = explode('|',$parts[0]); foreach ($syms as $sym) { if ($sym == $symbol) { $syminfo = explode(',',$parts[1]); $symfn = $this->expandWptSymbolFn($syminfo[0]); if (isset($syminfo[1]) and ($syminfo[1] != '')) { $symbolwidth = $syminfo[1]; } if (isset($syminfo[2]) and ($syminfo[2] != '')) { $symbolheight = $syminfo[2]; } if (isset($syminfo[3]) and ($syminfo[3] != '')) { $offsetleft = $syminfo[3]; } if (isset($syminfo[4]) and ($syminfo[4] != '')) { $offsettop = $syminfo[4]; } return $symfn; } elseif ($sym == '*') { // "*" is used if no other match was found $syminfo = explode(',',$parts[1]); $defaultsymbolfn = $this->expandWptSymbolFn($syminfo[0]); if (isset($syminfo[1]) and ($syminfo[1] != '')) { $symbolwidth = $syminfo[1]; } if (isset($syminfo[2]) and ($syminfo[2] != '')) { $symbolheight = $syminfo[2]; } if (isset($syminfo[3]) and ($syminfo[3] != '')) { $offsetleft = $syminfo[3]; } if (isset($syminfo[4]) and ($syminfo[4] != '')) { $offsettop = $syminfo[4]; } } } } return $this->expandWptSymbolFn($defaultsymbolfn); } private function makeWptCode($wptcount,$wpts,$mapvar,$mapno) { $s = "\n"."var toMercator = OpenLayers.Projection.transforms['EPSG:4326']['EPSG:3857'];"."\n". "var features = [];"."\n"; if ((!is_numeric($this->_params['wppopupwidth'])) or ($this->_params['wppopupwidth'] <= 0)) { $this->_params['wppopupwidth'] = 300; } if ((!is_numeric($this->_params['wppopupheight'])) or ($this->_params['wppopupheight'] <= 0)) { $this->_params['wppopupheight'] = 300; } $popupsize = $this->_params['wppopupwidth'].','.$this->_params['wppopupheight']; if ($this->_params['wpsymbols'] != 0) { // V1.2.3: add waypoint symbols if ($this->_params['wppopups'] != 0) { // OnClick-handler for the Waypoint symbols $s .= 'var wptmarkerClick'.$mapno.' = function (evt) {'."\n"; $s .= ' if (this.popup == null) {'."\n"; $s .= ' this.popup = this.createPopup(this.closeBox);'."\n"; //todo: make max size configurable! $s .= ' this.popup.maxSize = new OpenLayers.Size('.$popupsize.');'."\n"; $s .= ' map'.$mapno.'.addPopup(this.popup);'."\n"; $s .= ' this.popup.show();'."\n"; $s .= ' } else {'."\n"; $s .= ' this.popup.toggle();'."\n"; $s .= ' }'."\n"; $s .= ' currentPopup = this.popup;'."\n"; $s .= ' OpenLayers.Event.stop(evt);'."\n"; $s .= '};'."\n"; } for ($i=0; $i < $wptcount; $i++) { // if ($wpts[$i]['sym'] !== '') { { // assemble code for Waypoint Symbol marker and optional popup $symbolwidth = 24; $symbolheight= 24; $offsetleft = 0; // offset to top-left corner of the "hot spot" $offsettop = 0; $wptsymbolfn = $this->getWptSymbolFn($wpts[$i]['sym'],$symbolwidth,$symbolheight,$offsetleft,$offsettop); $s .= "\n"; $s .= ' var wptsize'.$i.' = new OpenLayers.Size('.$symbolwidth.','.$symbolheight.');'."\n"; if (($offsetleft != 0) AND ($offsettop != 0)) { $s .= ' var wptoffset'.$i.' = new OpenLayers.Pixel(-('.$offsetleft.'), -('.$offsettop.'));'."\n"; } else { // if no offsets supplied, use the center of the symbol like Basecamp does: $s .= ' var wptoffset'.$i.' = new OpenLayers.Pixel(-(wptsize'.$i.'.w/2), -wptsize'.$i.'.h/2);'."\n"; } $s .= ' var wpticon'.$i.' = new OpenLayers.Icon("'.$wptsymbolfn.'",'."\n"; $s .= ' wptsize'.$i.',wptoffset'.$i.');'."\n"; $s .= ' wptgeo'.$i.' = toMercator(new OpenLayers.Geometry.Point('.$wpts[$i]['lon'].','.$wpts[$i]['lat'].'));'."\n"; $s .= ' wptll'.$i.' = new OpenLayers.LonLat.fromString(wptgeo'.$i.'.toShortString()); '."\n"; $s .= ' var wptfeature'.$i.' = new OpenLayers.Feature(layerMarkers'.$mapno.', wptll'.$i.');'."\n"; $s .= ' wptfeature'.$i.'.data.icon = wpticon'.$i.';'."\n"; $s .= ' wptfeature'.$i.'.closeBox = true;'."\n"; $s .= ' wptfeature'.$i.'.popupClass = OpenLayers.Popup.FramedCloud;'."\n"; // now assemble the html code for the popup. Sadly, this works quite different then // with the Geometry layer (code below in ELSE branch, so a lot of this code is _almost_ // duplicate compared to the code there... $wpthtml = ""; $wptname = $wpts[$i]['name']; $wptele = ''; if (($this->_params['wppopupele'] !== 0) AND ($wpts[$i]['ele'] != '')) { $e = $wpts[$i]['ele']; if ($this->_params['wppopupele'] == 'ft') { $m_ft = 1 / 0.3048; $e = $e * $m_ft; $wptele = ' ('.round($e).' ft)'; } if ($this->_params['wppopupele'] == 'm') { $wptele = ' ('.round($e).' m)'; } } if (($this->_params['wppopuptimefmt'] != '0') AND ((integer)$wpts[$i]['time'] != 0)) { $t = strftime($this->_params['wppopuptimefmt'],(integer)$wpts[$i]['time']); $wpttime= '<br />'.$t; } else { $wpttime= ''; } if (($this->_params['wppopupdesc'] != '0') AND ((string)$wpts[$i]['desc'] != '')) { $d = nl2br((string)$wpts[$i]['desc']); // the attribute text may not contain carriage returns or linefeeds: $d = preg_replace('/\r\n|\r|\n/', '', $d); $wptdesc = '<br />'.$d; } else { $wptdesc = ''; } if (($this->_params['wppopuplinkfmt'] != '0') AND ((string)$wpts[$i]['links'] != '')) { $wptlinks = '<br />'; $l = explode("\n",(string)$wpts[$i]['links']); $n = 1; foreach ($l as $lnk) { if (trim($lnk) != '') { $d = str_replace('%N%',$n,$this->_params['wppopuplinkfmt']); if ($n>1) { $wptlinks .= ' '; } $wptlinks .= '<a href=\''.$lnk.'\' target=\'_blank\'>'.$d.'</a>'; $n += 1; } } } else { $wptlinks = ''; } $wpthtml = "<div style='font-size:.8em'>". "<span class='gpxwptname'>".$wptname."</span>". "<span class='gpxwptele'>".$wptele."</span>". "<span class='gpxwpttime'>".$wpttime."</span>". "<span class='gpxwpdesc'>".$wptdesc."</span>". "<span class='gpxwplinks'>".$wptlinks."</span></div>"; $wpthtml = '"'.$wpthtml.'"'; $s .= ' wptfeature'.$i.'.data.popupContentHTML = '.$wpthtml.';'."\n"; $s .= ' wptfeature'.$i.'.data.overflow = "auto";'."\n"; $s .= ' var wptmarker'.$i.' = wptfeature'.$i.'.createMarker(); '."\n"; if ($this->_params['wppopups'] == 1) { $evt = '"mouseover"'; } else { $evt = '"mousedown"'; } if ($this->_params['wppopups'] != 0) { $s .= ' wptmarker'.$i.'.events.register('.$evt.', wptfeature'.$i.', wptmarkerClick'.$mapno.');'."\n"; // V1.4.1 added for touchevents in mobile/tablet browsers $s .= ' wptmarker'.$i.'.events.register("touchstart", wptfeature'.$i.', wptmarkerClick'.$mapno.');'."\n"; } $s .= ' layerMarkers'.$mapno.'.addMarker(wptmarker'.$i.');'."\n"; } } } else { // no symbols (Graphics), but dots (Geometry layer) // add each waypoint as vector feature to separate vector layer for ($i=0; $i < $wptcount; $i++) { $w = "\n". 'features['.$i.'] = new OpenLayers.Feature.Vector(toMercator(new OpenLayers.Geometry.Point('. $wpts[$i]['lon'].','.$wpts[$i]['lat'].')),'."\n". '{ '; $w .= // attributes for the popup 'wptname: "'.$wpts[$i]['name'].'", '; $wptele = ''; if (($this->_params['wppopupele'] !== 0) AND ($wpts[$i]['ele'] != '')) { $e = $wpts[$i]['ele']; if ($this->_params['wppopupele'] == 'ft') { $m_ft = 1 / 0.3048; $e = $e * $m_ft; $wptele = ' ('.round($e).' ft)'; } if ($this->_params['wppopupele'] == 'm') { $wptele = ' ('.round($e).' m)'; } } if ($wptele == '') { $w .= 'wptele: "", '; } else { $w .= 'wptele: "'.$wptele.'", '; } if (($this->_params['wppopuptimefmt'] != '0') AND ((integer)$wpts[$i]['time'] != 0)) { $t = strftime($this->_params['wppopuptimefmt'],(integer)$wpts[$i]['time']); $w .= 'wpttime: "<br />'.$t.'", '; } else { $w .= 'wpttime: "", '; } if (($this->_params['wppopupdesc'] != '0') AND ((string)$wpts[$i]['desc'] != '')) { $d = nl2br((string)$wpts[$i]['desc']); // the attribute text may not contain carriage returns or linefeeds: $d = preg_replace('/\r\n|\r|\n/', '', $d); $w .= 'wptdesc: "<br />'.$d.'", '."\n"; } else { $w .= 'wptdesc: "", '."\n"; } if (($this->_params['wppopuplinkfmt'] != '0') AND ((string)$wpts[$i]['links'] != '')) { $w .= 'wptlinks: "<br />'; $l = explode("\n",(string)$wpts[$i]['links']); $n = 1; foreach ($l as $lnk) { if (trim($lnk) != '') { $d = str_replace('%N%',$n,$this->_params['wppopuplinkfmt']); if ($n>1) { $w .= ' '; } $w .= '<a href=\''.$lnk.'\' target=\'_blank\'>'.$d.'</a>'; $n += 1; } } $w .='", '."\n"; } else { $w .= 'wptlinks: "", '; } $w .= 'wptnum : '.$i.' '. // v1.2.1 fix: remove trailing comma here '},'."\n". '{ '. 'fillColor : \''.$this->_params['wpcolor'].'\', '. 'fillOpacity : '.$this->_params['trackopacity'].', '. 'strokeColor : "'.$this->_params['trackcolor'].'", '. 'strokeOpacity : '.$this->_params['trackopacity'].', '. 'strokeWidth : 1, '. 'pointRadius : '.$this->_params['wpradius'].', '. 'cursor: "pointer"} );'."\n\n"; $s .= $w; } if ($this->_params['wppopups'] != 0) { // V1.2.2 fix: disabling popups didn't work $s .= // create the layer with listeners to create and destroy popups 'var vector = new OpenLayers.Layer.Vector("Points",{'."\n". ' eventListeners:{'."\n". ' \'featureselected\':function(evt){'."\n". ' var feature = evt.feature;'."\n". ' var popup = new OpenLayers.Popup.FramedCloud("popup",'."\n". ' OpenLayers.LonLat.fromString(feature.geometry.toShortString()),'."\n". ' null,'."\n"; // contents for the popups: $s .= ' "<div style=\'font-size:.8em\'>'. '<span class=\'gpxwptname\'>" + feature.attributes.wptname + "</span>'. '<span class=\'gpxwptele\'>" + feature.attributes.wptele + "</span>'. '<span class=\'gpxwpttime\'>" + feature.attributes.wpttime + "</span>'. '<span class=\'gpxwpdesc\'>" + feature.attributes.wptdesc + "</span>'. '<span class=\'gpxwplinks\'>" + feature.attributes.wptlinks + "</span>"'; $s .= '+ "</div>",'."\n"; $s .= 'null,true); '."\n". //todo: make max size configurable! 'popup.maxSize = new OpenLayers.Size('.$popupsize.');'."\n". 'feature.popup = popup; '."\n". $mapvar.'.addPopup(popup); }, '."\n". ' \'featureunselected\':function(evt){'."\n". ' var feature = evt.feature;'."\n". ' '.$mapvar.'.removePopup(feature.popup);'."\n". ' feature.popup.destroy();'."\n". ' feature.popup = null; } } });'."\n". 'vector.addFeatures(features);'."\n"; $s .= // create the select feature control 'var selector = new OpenLayers.Control.SelectFeature(vector,{'."\n"; if ($this->_params['wppopups'] == 1) { $s .= ' hover:true,'."\n"; } else { $s .= ' toggle:true,'."\n"; } $s .= ' autoActivate:true }); '."\n". $mapvar.'.addLayer(vector); '."\n". $mapvar.'.addControl(selector); '."\n"; } } return $s; } private function filterSignal($s,$n,$order) { $sn = array(); if ($order < $n) { $sum = $s[0]; $sn[0] = $s[0]; for ($i=1; $i < $order; $i++) { $sn[$i] = $sum / $i; $sum = $sum + $s[$i]; } for ($i=$order; $i<$n; $i++) { $sn[$i] = $sum / $order; $sum = $sum - $s[$i-$order] + $s[$i]; } } return $sn; } private function renderDiagram($dist,$data,$n,$mindata,$maxdata,$distance,$uom,$filepath,$filename,$filenamesuffix, $diabgcolor,$dialinecolor,$diafillmode,$diaupcolor,$diadowncolor,$dialinewidth, $xgrids,$xgridunits,$xgridlimit,$xgridwidth,$xgridcolor, $ygridlines,$ygridwidth,$ygridcolor) { $ext = pathinfo($filename,PATHINFO_EXTENSION); $pos = strrpos($filename,$ext); if ($pos !== false) { $destfile = substr_replace($filename, 'svg', $pos, strlen($filename)); // replace .gpx with .svg } if ($filenamesuffix != '') { $fn = pathinfo($filename,PATHINFO_FILENAME); $pos = strrpos($filename,$fn); if ($pos !== false) { $destfile = substr_replace($filename, $fn.$filenamesuffix, $pos, strlen($filename)).'.svg'; // turn track.svg into track-speed.svg } } if (JFile::exists($filepath.$destfile) AND ($this->_params['cache'] == 1)) { return $destfile; } $m_ft = 1 / 0.3048; $kmh_mph = 1 / 1.609; $kmh_kn = 1 / 1.852; $sep = $this->_params['tidecimalsep']; $e = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1000" height="500"'."\n". ' viewBox="0 0 10000 10000" preserveAspectRatio="none">'."\n"; $e .= '<rect x="0" y="0" width="100%" height="100%" stroke="gray" stroke-width="0" fill="'.$diabgcolor.'" fill-opacity="1" />'."\n"; // horizontal altitude lines // v1.2.2 configurable number of grid lines. Bottom coord=500, Top=9500 if ($ygridlines>0) { for ($i=0; $i<$ygridlines; $i++) { if ($i==0) { $yco = 500; } else { $yco = 500 + ($i * (9000/($ygridlines-1))); } $e .= '<line x1="0" y1="'.$yco.'" x2="10000" y2="'.$yco.'" stroke-width="'.$ygridwidth.'" stroke="'.$ygridcolor.'" />'."\n"; } } $d1 = $dist[0]; $a1 = $data[0]; $yrange = ($maxdata-$mindata) * 1.1; // 5% "headroom" above and below $yofs = ($maxdata-$mindata) * 0.05; $xrange = $distance; if ($yrange==0) { return ''; } // x axis grid if (($xgrids > '') AND ((string)$xgrids != '0')) { $xs = explode('/',trim($xgrids)); foreach ($xs as $xgrid) { if ($xgrid > 0.0) { switch ($xgridunits) { case ( 'm') : $xgrid_m = $xgrid * 1.0; break; case ('km') : $xgrid_m = $xgrid * 1000.0; break; case ('ft') : $xgrid_m = $xgrid / $m_ft; break; case ('mi') : $xgrid_m = $xgrid * 1000.0 / $kmh_mph; break; case ('nm') : $xgrid_m = $xgrid * 1000.0 / $kmh_kn; break; } if ($distance*1000 / $xgrid_m <= $xgridlimit) { break; } } } // foreach // auto-correct if still to many grid lines while ($distance*1000 / $xgrid_m > $xgridlimit ) { $xgrid_m = $xgrid_m * 2; $xgrid = $xgrid * 2; } $xofs = $xgrid; // in display units $xofs_m = $xgrid_m; while ($xofs_m < $distance * 1000) { // $distance is [km] ! $xcoord = $xofs_m / $xrange * 10; $e .= '<line x1="'.round($xcoord).'" y1="0" x2="'.round($xcoord).'" y2="10000" stroke-width="'.$xgridwidth.'" stroke="'.$xgridcolor.'" />'."\n"; $xdist = round($xofs,1).' '.$xgridunits; if ($sep !== '.') { $xdist = str_replace('.',$sep,$xdist); } $e .= '<g transform="scale(0.3,1)"><text x="'.round($xcoord*(1/0.3)+100).'" y="9950" font-family="Verdana" font-size="500" fill="black">'.$xdist.'</text></g>'."\n"; $xofs += $xgrid; $xofs_m += $xgrid_m; } } $x1 = 0; $y1 = (($a1-$mindata+$yofs) / $yrange )* 100; $x1coord = round($x1*100); $y1coord = 10000-round($y1*100); $lw = $dialinewidth * 10; // here goes line/polygon diagram... $polyline = '<polyline fill-opacity="0" stroke-width="'.$lw.'" stroke="'.$dialinecolor.'" points="'.$x1coord.','.$y1coord.' '; $polygons = ''; if ($xrange==0) { return ''; } for ($i=1; $i < ($n-1); $i++) { $d2 = $dist[$i]; $a2 = $data[$i]; $x2 = ($d2) / $xrange * 100; $y2 = (($a2-$mindata+$yofs) / $yrange) * 100; $x2coord = round($x2*100); $y2coord = 10000-round($y2*100); $fill = ''; if ($diafillmode == 1) { // delta (up/down) if ($x2<>$x1) { $m = (($y2-$y1)/($x2-$x1)); if ($m>0) { $fill = $diaupcolor; } else { $fill = $diadowncolor; $m = -$m; } $m = round(sqrt(sqrt($m))*0.4,3); // gives better "opacity/color distribution" } else { $m=0; $fill= "white"; } } if ($diafillmode == 2) { // abs $m = ($a2 - $mindata) / ($maxdata-$mindata); // 0..1.0 $fill = $diaupcolor; } if ($fill !== '') { $polygons .= '<polygon fill-opacity="'.$m.'" fill="'.$fill.'" stroke-width="0" points="'. $x1coord.',9500 '.$x1coord.','.$y1coord.' '.$x2coord.','.$y2coord.' '.$x2coord.',9500" />'."\n"; } $polyline .= $x2coord.','.$y2coord.' '; $x1 = $x2; $y1 = $y2; $x1coord = $x2coord; $y1coord = $y2coord; } $e .= $polygons; $e .= $polyline.'" />'; // min/max elevation captions on y axis //TODO: remove "magic consts" in here with calculated offsets... y values go down from top/left origin. $e .= '<g transform="scale(0.3,1)">'."\n"; if ($ygridlines>0) { for ($i=0; $i<$ygridlines; $i++) { if ($i==$ygridlines-1) { $yco = 9950;//500 - 50; $ecur = $mindata; } else { $yco = 500 -50 + ($i * (9000/($ygridlines-1))); $ecur = $maxdata - ( ($maxdata-$mindata) / ($ygridlines-1) * $i ); } if ($uom == "m") { // elevation - data is in [m] $ecur = round($ecur,1); } if ($uom == "ft") { // elevation - data is in [m] $ecur = round($ecur * $m_ft,1); } if ($uom == "km/h") { // speed - data is in [km/h] $ecur = round($ecur,1); } if ($uom == "mph") { // speed - data is in [km/h] $ecur = round($ecur * $kmh_mph,1); } if ($uom == "kn") { // speed - data is in [km/h] $ecur = round($ecur * $kmh_kn,1); } if ($sep !== '.') { $ecur = str_replace('.',$sep,$ecur); } $e .= '<text x="100" y="'.$yco.'" font-family="Verdana" font-size="500" fill="black">'.$ecur.' '.$uom.'</text>'."\n"; } } $e .= '</g>'."\n"; // close surrounding translate() group tag $e .= '</svg>'."\n"; // always re-create (for now), but: see cache setting above if (JFile::exists($filepath.$destfile)) { JFile::delete($filepath.$destfile); } // V1.2.2 check write permission if (! $this->is__writable($filepath.$destfile)) { return ''; } else { $fh = fopen($filepath.$destfile,"c"); fwrite($fh,$e); fclose($fh); return $destfile; } } private function getGPXTime($gpxtimestr) { // timestamps in GPX files have the following format: // 2012-12-03T09:08:43Z // 01234567890123456789 (offsets) $y = (int)substr($gpxtimestr, 0,4); $m = (int)substr($gpxtimestr, 5,2); $d = (int)substr($gpxtimestr, 8,2); $h = (int)substr($gpxtimestr,11,2); $n = (int)substr($gpxtimestr,14,2); $s = (int)substr($gpxtimestr,17,2); $ts = gmmktime($h,$n,$s,$m,$d,$y); // no UTC conversion fanciness, please! just as it appears in the file... if ($this->_params["titimeshift"] != 0) { $ts = $ts + $this->_params["titimeshift"] * 60 * 60; } return $ts; } private function ziptrackfile($filepath,$filename) { $ext = pathinfo($filename,PATHINFO_EXTENSION); $pos = strrpos($filename,$ext); // search from the right //maybe add in a check here if extension is really "gpx" ?? if($pos !== false) { $destfile = substr_replace($filename, 'zip', $pos, strlen($filename)); // replace .gpx with .zip } $fullgpxpath = $this->_absolute_path.DIRECTORY_SEPARATOR.$filepath.$filename; $fullzippath = $this->_absolute_path.DIRECTORY_SEPARATOR.$filepath.$destfile; if (JFile::exists($fullzippath) AND ($this->_params['cache'] == 1)) { return $filepath.$destfile; } jimport('joomla.filesystem.archive'); jimport('joomla.filesystem.file'); // V1.2.2 check write permission if (! $this->is__writable($fullzippath)) { $this->_warnings .= 'Unable to create zip file of the gpx file. Please check write permissions!'."\n"; return false; } if (!JFile::exists($fullgpxpath)) { return false; } /** code Joomla 3 $filesToZip[] = array( 'data' => JFile::read($fullgpxpath), 'name' => JFile::getName($filename)); $zip = JArchive::getAdapter('zip'); $zip->create($fullzippath, $filesToZip); */ // migration vers Joomla 4 $filesToZip[] = array( 'data' => file_get_contents($fullgpxpath), 'name' => basename($filename)); $archive = new JArchive; $zip = $archive->getAdapter('zip'); // migration vers Joomla 4 if (JFile::exists($fullzippath)) // it should now! { return $filepath.$destfile; } else { return false; } } private function markerFilename($markertype, $markerset) { switch($markertype) { case(1): $clr = 'blue'; break; case(2): $clr = 'red'; break; case(3): $clr = 'green'; break; case(4): $clr = 'yellow'; break; case(5): $clr = 'white'; break; case(6): $clr = 'gray'; break; case(7): $clr = 'black'; break; case('blue'): case('red'): case('green'): case('yellow'): case('white'): case('gray'): case('black'): $clr = $markertype; // so one can put "startmarker=red" in the call instead of "startmarker=2" default: $clr = ''; } if ($clr=='') { return ''; } else { return 'marker'.$markerset.'-'.$clr.'.png'; } // marker1-blue.png } private function is__writable($path) { // from www.php.net article on is_writeable: // pour Joomla3 if ($path{strlen($path)-1}=='/') // recursively return a temporary file path if ($path[strlen($path)-1]=='/') // recursively return a temporary file path return is__writable($path.uniqid(mt_rand()).'.tmp'); else if (is_dir($path)) return is__writable($path.'/'.uniqid(mt_rand()).'.tmp'); // check tmp file for read/write capabilities $rm = file_exists($path); $f = @fopen($path, 'a'); if ($f===false) return false; fclose($f); if (!$rm) unlink($path); return true; } }
$this->_gtmversion = 'V1.4.1';
belle journée
Commentaire