Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ IMPORTANT NOTE: This version only works on CACTI 1.x++!

* feature#298: Fit or stretch background images within the map canvas

* feature#295: Use a readable landscape preset for new blank maps

* feature#294: Expose bundled fonts and link comment colours in Map Style

* feature#293: Default new graph assignments to Time Graph View
Expand Down
4 changes: 2 additions & 2 deletions lib/WeatherMap.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -3164,7 +3164,7 @@ function ReadConfig($input, $is_include = false) {

// truetype font definition (actually, we don't really check if it's truetype) - filename + size
if (preg_match('/^\s*FONTDEFINE\s+(\d+)\s+(\S+)\s+(\d+)\s*$/i', $buffer, $matches)) {
if (function_exists('imagettfbbox')) {
if (function_exists('imagettfbbox') && function_exists('imagettftext')) {
// test if this font is valid, before adding it to the font table...
$bounds = imagettfbbox((float)$matches[3], 0, wm_font_file($matches[2]), 'Ignore me');
Comment thread
alcatron marked this conversation as resolved.

Expand All @@ -3178,7 +3178,7 @@ function ReadConfig($input, $is_include = false) {
wm_warn('Failed to load ttf font ' . $matches[2] . " - at config line $linecount [WMWARN30]");
}
} else {
wm_warn("imagettfbbox() is not a defined function. You don't seem to have FreeType compiled into your gd module. [WMWARN31]");
wm_warn("FreeType font functions imagettfbbox() and imagettftext() must both be available in your gd module. [WMWARN31]");
}

$linematched++;
Expand Down
2 changes: 2 additions & 0 deletions lib/editor.actions.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ function newMap($mapfile) {

$map->context = 'editor';

require_once __DIR__ . '/editor.new-map-preset.php';
wm_new_map_preset($map);
$map->WriteConfig($mapfile);
}

Expand Down
55 changes: 55 additions & 0 deletions lib/editor.new-map-preset.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
/*
+-------------------------------------------------------------------------+
| Copyright (C) 2004-2026 The Cacti Group, Howard Jones |
| |
Comment thread
Copilot marked this conversation as resolved.
| 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 2 |
| 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. |
+-------------------------------------------------------------------------+
| Cacti: The Complete RRDtool-based Graphing Solution |
+-------------------------------------------------------------------------+
| This code is designed, written, and maintained by the Cacti Group. See |
| about.php and/or the AUTHORS file for specific developer information. |
+-------------------------------------------------------------------------+
| http://www.cacti.net/ |
+-------------------------------------------------------------------------+
*/

/**
* Apply readable initial defaults only to a newly created blank map.
*
* @param WeatherMap $map
*
* @return void
*/
function wm_new_map_preset($map) {
$map->add_hint('background_sizing', 'fit');
$map->width = 1400;
$map->height = 750;
$map->htmlstyle = 'overlib';
$map->links['DEFAULT']->arrowstyle = 'compact';
$map->links['DEFAULT']->commentfontcolour = [0, 0, 255];
$file = realpath(__DIR__ . '/../docs/example/Vera.ttf');

if ($file !== false && is_readable($file) && function_exists('imagettfbbox') && function_exists('imagettftext') && is_array(imagettfbbox(9, 0, $file, '1G'))) {
$number = 100;

while (isset($map->fonts[$number])) {
$number++;
}
$font = new WMFont();
$font->type = 'truetype';
$font->file = 'docs/example/Vera.ttf';
Comment thread
alcatron marked this conversation as resolved.
$font->size = 9;
$map->fonts[$number] = $font;
$map->links['DEFAULT']->bwfont = $number;
$map->links['DEFAULT']->commentfont = $number;
}
}
90 changes: 90 additions & 0 deletions tests/Support/NewMapPresetEngineRegression.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php
/*
+-------------------------------------------------------------------------+
| Copyright (C) 2004-2026 The Cacti Group, Howard Jones |
| |
Comment thread
Copilot marked this conversation as resolved.
| 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 2 |
| 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. |
+-------------------------------------------------------------------------+
| Cacti: The Complete RRDtool-based Graphing Solution |
+-------------------------------------------------------------------------+
| This code is designed, written, and maintained by the Cacti Group. See |
| about.php and/or the AUTHORS file for specific developer information. |
+-------------------------------------------------------------------------+
| http://www.cacti.net/ |
+-------------------------------------------------------------------------+
*/

require dirname(__DIR__) . '/bootstrap-unit.php';
$plugin = dirname(__DIR__,2);
chdir($plugin);
require $plugin . '/setup.php';
require $plugin . '/lib/WeatherMap.class.php';

if (!function_exists('cacti_count')) {
function cacti_count($value) {
return is_countable($value) ? count($value) : 0;
}
}

if (!function_exists('clean_up_name')) {
function clean_up_name($value) {
return preg_replace('/[^A-Za-z0-9_\-.]/','_',$value);
}
}

if (!defined('MESSAGE_LEVEL_INFO')) {
define('MESSAGE_LEVEL_INFO',0);
}
function wm_engine_assert($value,$message) {
if (!$value) {
throw new RuntimeException($message);
}
}
$directory = sys_get_temp_dir() . '/wm-engine-' . bin2hex(random_bytes(8));
mkdir($directory);

try {
require $plugin . '/lib/editor.new-map-preset.php';
$map = new WeatherMap();
wm_new_map_preset($map);
$map->WriteConfig($directory . '/new.conf');
$saved = new WeatherMap();
$saved->ReadConfig($directory . '/new.conf');
wm_engine_assert($saved->width == 1400 && $saved->height == 750,'canvas');
wm_engine_assert($saved->htmlstyle === 'overlib','dynamic');
wm_engine_assert($saved->links['DEFAULT']->arrowstyle === 'compact','arrows');
wm_engine_assert($saved->links['DEFAULT']->commentfontcolour == [0, 0, 255],'blue');
$font = $saved->fonts[$saved->links['DEFAULT']->commentfont];
wm_engine_assert($font->size == 9 && is_readable($font->file),'font');
$source = file_get_contents($plugin . '/weathermap-cacti-plugin-mgmt.php');
$start = strpos($source,'function newMap(');
eval(str_replace('__DIR__',var_export($plugin,true),substr($source,$start)));
$weathermap_confdir = $directory;
newMap('blank.conf');
$blank = new WeatherMap();
$blank->ReadConfig($directory . '/blank.conf');
wm_engine_assert($blank->width == 1400,'management blank');
$original = new WeatherMap();
$original->width = 900;
$original->height = 500;
$original->htmlstyle = 'static';
$original->WriteConfig($directory . '/source.conf');
newMap('copy.conf','source.conf');
$copy = new WeatherMap();
$copy->ReadConfig($directory . '/copy.conf');
wm_engine_assert($copy->width == 900 && $copy->height == 500 && $copy->htmlstyle === 'static','copy retains source');

print "PASS\n";
} finally {
foreach (glob($directory . '/*') as $file) {
unlink($file);
}rmdir($directory);
}
74 changes: 74 additions & 0 deletions tests/Support/SavedPresetFallbackRegression.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php
/*
+-------------------------------------------------------------------------+
| Copyright (C) 2004-2026 The Cacti Group, Howard Jones |
| |
| 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 2 |
| 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. |
+-------------------------------------------------------------------------+
| Cacti: The Complete RRDtool-based Graphing Solution |
+-------------------------------------------------------------------------+
| This code is designed, written, and maintained by the Cacti Group. See |
| about.php and/or the AUTHORS file for specific developer information. |
+-------------------------------------------------------------------------+
| http://www.cacti.net/ |
+-------------------------------------------------------------------------+
*/

// Collect real execution in the runtime with FreeType disabled when coverage is requested.
$coverageFile = $argv[1] ?? null;
if ($coverageFile !== null && function_exists('xdebug_start_code_coverage')) {
xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);
}

require dirname(__DIR__) . '/bootstrap-unit.php';
$plugin = dirname(__DIR__, 2);
chdir($plugin);
require $plugin . '/setup.php';
require $plugin . '/lib/WeatherMap.class.php';

if (!function_exists('cacti_count')) {
function cacti_count($value) {
return is_countable($value) ? count($value) : 0;
}
}
if (!function_exists('clean_up_name')) {
function clean_up_name($value) {
return preg_replace('/[^A-Za-z0-9_\-.]/', '_', $value);
}
}
$directory = sys_get_temp_dir() . '/wm-fallback-' . bin2hex(random_bytes(8));
mkdir($directory, 0700);
try {
$file = $directory . '/saved.conf';
file_put_contents($file, "WIDTH 200\nHEIGHT 100\nFONTDEFINE 100 docs/example/Vera.ttf 9\nLINK DEFAULT\n BWFONT 100\n COMMENTFONT 100\nNODE A\n LABEL A\n POSITION 20 50\nNODE B\n LABEL B\n POSITION 180 50\nLINK A-B\n NODES A B\n OUTCOMMENT 1G\n");
$map = new WeatherMap();
$map->ReadConfig($file);
if (isset($map->fonts[100])) {
throw new RuntimeException('Unavailable FreeType font was registered');
}
$map->DrawMap($directory . '/saved.png');
$image = imagecreatefrompng($directory . '/saved.png');
if (imagesx($image) !== 200 || imagesy($image) !== 100) {
throw new RuntimeException('Fallback map did not render');
}
imagedestroy($image);
if ($coverageFile !== null && function_exists('xdebug_get_code_coverage')) {
file_put_contents($coverageFile, json_encode(xdebug_get_code_coverage(), JSON_THROW_ON_ERROR));
xdebug_stop_code_coverage();
}

print "PASS";
} finally {
foreach (glob($directory . '/*') as $file) {
unlink($file);
}
rmdir($directory);
}
55 changes: 55 additions & 0 deletions tests/Unit/NewMapPresetDefaultsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
/*
+-------------------------------------------------------------------------+
| Copyright (C) 2004-2026 The Cacti Group, Howard Jones |
| |
Comment thread
Copilot marked this conversation as resolved.
| 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 2 |
| 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. |
+-------------------------------------------------------------------------+
| Cacti: The Complete RRDtool-based Graphing Solution |
+-------------------------------------------------------------------------+
| This code is designed, written, and maintained by the Cacti Group. See |
| about.php and/or the AUTHORS file for specific developer information. |
+-------------------------------------------------------------------------+
| http://www.cacti.net/ |
+-------------------------------------------------------------------------+
*/

beforeAll(function () {
require_once dirname(__DIR__, 2) . '/lib/WeatherMap.functions.php';
require_once dirname(__DIR__, 2) . '/lib/editor.new-map-preset.php';
});

it('UsesReadableLandscapeDefaultsAndAllocatesAnUnusedFontId', function () {
$map = new class {
public $width;
public $height;
public $htmlstyle;
public $links;
public $fonts = [100 => null];
public $hints = [];
public function add_hint($name, $value) {
$this->hints[$name] = $value;
}
};
$map->links = ['DEFAULT' => (object) ['arrowstyle' => 'classic', 'commentfontcolour' => [0, 0, 0], 'bwfont' => 2, 'commentfont' => 1]];
$map->fonts[100] = new WMFont();
wm_new_map_preset($map);
expect([$map->width, $map->height])->toBe([1400, 750])
->and($map->htmlstyle)->toBe('overlib')
->and($map->hints['background_sizing'])->toBe('fit')
->and($map->links['DEFAULT']->arrowstyle)->toBe('compact')
->and($map->links['DEFAULT']->commentfontcolour)->toBe([0, 0, 255])
->and($map->links['DEFAULT']->bwfont)->toBe(101)
->and($map->links['DEFAULT']->commentfont)->toBe(101)
->and($map->fonts[101]->file)->toBe('docs/example/Vera.ttf')
->and($map->fonts[101]->size)->toBe(9)
->and(is_readable(wm_font_file($map->fonts[101]->file)))->toBeTrue();
});
29 changes: 29 additions & 0 deletions tests/Unit/NewMapPresetEngineTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php
/*
+-------------------------------------------------------------------------+
| Copyright (C) 2004-2026 The Cacti Group, Howard Jones |
| |
Comment thread
Copilot marked this conversation as resolved.
| 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 2 |
| 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. |
+-------------------------------------------------------------------------+
| Cacti: The Complete RRDtool-based Graphing Solution |
+-------------------------------------------------------------------------+
| This code is designed, written, and maintained by the Cacti Group. See |
| about.php and/or the AUTHORS file for specific developer information. |
+-------------------------------------------------------------------------+
| http://www.cacti.net/ |
+-------------------------------------------------------------------------+
*/

it('PersistsAndRendersTheNewMapOptionsUsingTheRealEngine', function () {
$lines = [];
exec(escapeshellarg(PHP_BINARY) . ' ' . escapeshellarg(dirname(__DIR__) . '/Support/NewMapPresetEngineRegression.php') . ' 2>&1',$lines,$status);
expect($status)->toBe(0)->and(implode("\n",$lines))->toBe('PASS');
});
Loading