diff --git a/modules/monitoring/application/controllers/HostsController.php b/modules/monitoring/application/controllers/HostsController.php index 8f88330aa..2a40efc5b 100644 --- a/modules/monitoring/application/controllers/HostsController.php +++ b/modules/monitoring/application/controllers/HostsController.php @@ -56,6 +56,7 @@ class Monitoring_HostsController extends Controller 'host_icon_image', 'host_icon_image_alt', 'host_name', + 'host_address', 'host_state', 'host_problem', 'host_handled', @@ -94,6 +95,7 @@ class Monitoring_HostsController extends Controller 'host_icon_image', 'host_icon_image_alt', 'host_name', + 'host_address', 'host_state', 'host_problem', 'host_handled', diff --git a/modules/monitoring/application/controllers/ServicesController.php b/modules/monitoring/application/controllers/ServicesController.php index 1a8ec9a58..097ee607b 100644 --- a/modules/monitoring/application/controllers/ServicesController.php +++ b/modules/monitoring/application/controllers/ServicesController.php @@ -53,6 +53,7 @@ class Monitoring_ServicesController extends Controller 'host_icon_image', 'host_icon_image_alt', 'host_name', + 'host_address', 'host_output', 'host_state', 'host_problem', @@ -100,6 +101,7 @@ class Monitoring_ServicesController extends Controller 'host_icon_image', 'host_icon_image_alt', 'host_name', + 'host_address', 'host_output', 'host_state', 'host_problem', diff --git a/modules/monitoring/application/views/helpers/IconImage.php b/modules/monitoring/application/views/helpers/IconImage.php index e0e969db4..12108f30b 100644 --- a/modules/monitoring/application/views/helpers/IconImage.php +++ b/modules/monitoring/application/views/helpers/IconImage.php @@ -1,6 +1,8 @@ host_icon_image && ! preg_match('/[\'"]/', $object->host_icon_image)) { return $this->view->img( - 'img/icons/' . $this->view->resolveMacros($object->host_icon_image, $object), + 'img/icons/' . Macro::resolveMacros($object->host_icon_image, $object), null, array( 'alt' => $object->host_icon_image_alt, @@ -48,7 +50,7 @@ class Zend_View_Helper_IconImage extends Zend_View_Helper_Abstract { if ($object->service_icon_image && ! preg_match('/[\'"]/', $object->service_icon_image)) { return $this->view->img( - 'img/icons/' . $this->view->resolveMacros($object->service_icon_image, $object), + 'img/icons/' . Macro::resolveMacros($object->service_icon_image, $object), null, array( 'alt' => $object->service_icon_image_alt, diff --git a/modules/monitoring/application/views/scripts/show/components/actions.phtml b/modules/monitoring/application/views/scripts/show/components/actions.phtml index 35077abc0..329a06fb9 100644 --- a/modules/monitoring/application/views/scripts/show/components/actions.phtml +++ b/modules/monitoring/application/views/scripts/show/components/actions.phtml @@ -1,29 +1,16 @@ %s ', $this->translate('opens in new window')); -$linkText = '%s ' . $newTabInfo . ''; -$localLinkText = '%s'; - -if ($object->action_url) { - if (strpos($object->action_url, "' ") === false) { - $links[] = sprintf($linkText, $this->resolveMacros($object->action_url, $object), 'Action'); - } else { - // TODO: We should find out document what's going on here. Looks strange :p - foreach(explode("' ", $object->action_url) as $url) { - $url = strpos($url, "'") === 0 ? substr($url, 1) : $url; - $url = strrpos($url, "'") === strlen($url) - 1 ? substr($url, 0, strlen($url) - 1) : $url; - $links[] = sprintf($linkText, $this->resolveMacros($url, $object), 'Action'); - } - } +$links = $object->getActionUrls(); +foreach ($links as $i => $link) { + $links[$i] = sprintf('%s ' . $newTabInfo . '', $link, 'Action'); } if (isset($this->actions)) { foreach ($this->actions as $id => $action) { - $links[] = sprintf($localLinkText, $action, $id); + $links[] = sprintf('%s', $action, $id); } } @@ -34,5 +21,5 @@ if (empty($links)) { ?> translate('Actions') ?> - + ", $links) ?> diff --git a/modules/monitoring/application/views/scripts/show/components/notes.phtml b/modules/monitoring/application/views/scripts/show/components/notes.phtml index 678d70c90..4a5041e50 100644 --- a/modules/monitoring/application/views/scripts/show/components/notes.phtml +++ b/modules/monitoring/application/views/scripts/show/components/notes.phtml @@ -1,15 +1,13 @@ getNotes()); $links = $object->getNotesUrls(); -?> - +if (! empty($links) || ! empty($notes)): ?> translate('Notes') ?> resolveMacros($notes, $object); echo $notes . '
'; } // add warning to links that open in new tabs to improve accessibility, as recommended by WCAG20 G201 @@ -19,8 +17,7 @@ $links = $object->getNotesUrls(); ); $linkText = '%s ' . $newTabInfo . ''; foreach ($links as $i => $link) { - $resolved = $this->resolveMacros($link, $object); - $links[$i] = sprintf($linkText, $this->escape($resolved), $this->escape($resolved)); + $links[$i] = sprintf($linkText, $this->escape($link), $this->escape($link)); } echo implode('
', $links); ?> diff --git a/modules/monitoring/library/Monitoring/Object/Host.php b/modules/monitoring/library/Monitoring/Object/Host.php index 6bf6b05cc..dd9b4c0c1 100644 --- a/modules/monitoring/library/Monitoring/Object/Host.php +++ b/modules/monitoring/library/Monitoring/Object/Host.php @@ -7,7 +7,7 @@ use InvalidArgumentException; use Icinga\Module\Monitoring\Backend\MonitoringBackend; /** - * A Icinga host + * An Icinga host */ class Host extends MonitoredObject { @@ -192,7 +192,9 @@ class Host extends MonitoredObject public function getNotesUrls() { - return MonitoredObject::parseAttributeUrls($this->host_notes_url); + return $this->resolveAllStrings( + MonitoredObject::parseAttributeUrls($this->host_notes_url) + ); } public function getNotes() diff --git a/modules/monitoring/application/views/helpers/ResolveMacros.php b/modules/monitoring/library/Monitoring/Object/Macro.php similarity index 55% rename from modules/monitoring/application/views/helpers/ResolveMacros.php rename to modules/monitoring/library/Monitoring/Object/Macro.php index 7d555f8fd..4a9045b58 100644 --- a/modules/monitoring/application/views/helpers/ResolveMacros.php +++ b/modules/monitoring/library/Monitoring/Object/Macro.php @@ -1,36 +1,41 @@ 'host_name', - 'HOSTADDRESS' => 'host_address', - 'SERVICEDESC' => 'service_description' + private static $icingaMacros = array( + 'HOSTNAME' => 'host_name', + 'HOSTADDRESS' => 'host_address', + 'SERVICEDESC' => 'service_description', + 'host.name' => 'host_name', + 'host.address' => 'host_address', + 'service.description' => 'service_description' ); /** * Return the given string with macros being resolved * * @param string $input The string in which to look for macros - * @param MonitoredObject|stdClass $object The host or service used to resolve macros + * @param MonitoredObject|stdClass $object The host or service used to resolve macros * * @return string The substituted or unchanged string */ - public function resolveMacros($input, $object) + public static function resolveMacros($input, $object) { $matches = array(); if (preg_match_all('@\$([^\$\s]+)\$@', $input, $matches)) { foreach ($matches[1] as $key => $value) { - $newValue = $this->resolveMacro($value, $object); + $newValue = self::resolveMacro($value, $object); if ($newValue !== $value) { $input = str_replace($matches[0][$key], $newValue, $input); } @@ -44,14 +49,14 @@ class Zend_View_Helper_ResolveMacros extends Zend_View_Helper_Abstract * Resolve a macro based on the given object * * @param string $macro The macro to resolve - * @param MonitoredObject|stdClass $object The object used to resolve the macro + * @param MonitoredObject|stdClass $object The object used to resolve the macro * * @return string The new value or the macro if it cannot be resolved */ - public function resolveMacro($macro, $object) + public static function resolveMacro($macro, $object) { - if (array_key_exists($macro, $this->icingaMacros) && $object->{$this->icingaMacros[$macro]} !== false) { - return $object->{$this->icingaMacros[$macro]}; + if (array_key_exists($macro, self::$icingaMacros) && $object->{self::$icingaMacros[$macro]} !== false) { + return $object->{self::$icingaMacros[$macro]}; } if (array_key_exists($macro, $object->customvars)) { return $object->customvars[$macro]; diff --git a/modules/monitoring/library/Monitoring/Object/MonitoredObject.php b/modules/monitoring/library/Monitoring/Object/MonitoredObject.php index 236ca2aaa..b68bc0539 100644 --- a/modules/monitoring/library/Monitoring/Object/MonitoredObject.php +++ b/modules/monitoring/library/Monitoring/Object/MonitoredObject.php @@ -569,18 +569,47 @@ abstract class MonitoredObject implements Filterable * * @return string The notes as a string */ - public function getNotes() {} + public abstract function getNotes(); /** * Get all note urls configured for this monitored object * * @return array All note urls as a string */ - public function getNotesUrls() {} + public abstract function getNotesUrls(); + + /** + * Get all action urls configured for this monitored object + * + * @return array All note urls as a string + */ + public function getActionUrls() + { + return $this->resolveAllStrings( + MonitoredObject::parseAttributeUrls($this->action_url) + ); + } + + /** + * Resolve macros in all given strings in the current object context + * + * @param array $strs An array of urls as string + * @return type + */ + protected function resolveAllStrings(array $strs) + { + foreach ($strs as $i => $str) { + $strs[$i] = Macro::resolveMacros($str, $this); + } + return $strs; + } /** * Parse the content of the action_url or notes_url attributes * + * Find all occurences of http links, separated by whitespaces and quoted + * by single or double-ticks. + * * @link http://docs.icinga.org/latest/de/objectdefinitions.html * * @param string $urlString A string containing one or more urls diff --git a/modules/monitoring/library/Monitoring/Object/Service.php b/modules/monitoring/library/Monitoring/Object/Service.php index 17fd143b5..cb5615df1 100644 --- a/modules/monitoring/library/Monitoring/Object/Service.php +++ b/modules/monitoring/library/Monitoring/Object/Service.php @@ -7,7 +7,7 @@ use InvalidArgumentException; use Icinga\Module\Monitoring\Backend\MonitoringBackend; /** - * A Icinga service + * An Icinga service */ class Service extends MonitoredObject { @@ -202,7 +202,9 @@ class Service extends MonitoredObject public function getNotesUrls() { - return MonitoredObject::parseAttributeUrls($this->service_notes_url); + return $this->resolveAllStrings( + MonitoredObject::parseAttributeUrls($this->service_notes_url) + ); } public function getNotes() diff --git a/modules/monitoring/test/php/application/views/helpers/ResolveMacrosTest.php b/modules/monitoring/test/php/application/views/helpers/ResolveMacrosTest.php deleted file mode 100644 index 31bf839a3..000000000 --- a/modules/monitoring/test/php/application/views/helpers/ResolveMacrosTest.php +++ /dev/null @@ -1,78 +0,0 @@ -host_name = 'test'; - $hostMock->host_address = '1.1.1.1'; - - $helper = new Zend_View_Helper_ResolveMacros(); - $this->assertEquals($helper->resolveMacros('$HOSTNAME$', $hostMock), $hostMock->host_name); - $this->assertEquals($helper->resolveMacros('$HOSTADDRESS$', $hostMock), $hostMock->host_address); - } - - public function testServiceMacros() - { - $svcMock = Mockery::mock('service'); - $svcMock->host_name = 'test'; - $svcMock->host_address = '1.1.1.1'; - $svcMock->service_description = 'a service'; - - $helper = new Zend_View_Helper_ResolveMacros(); - $this->assertEquals($helper->resolveMacros('$HOSTNAME$', $svcMock), $svcMock->host_name); - $this->assertEquals($helper->resolveMacros('$HOSTADDRESS$', $svcMock), $svcMock->host_address); - $this->assertEquals($helper->resolveMacros('$SERVICEDESC$', $svcMock), $svcMock->service_description); - } - - public function testCustomvars() - { - $objectMock = Mockery::mock('object'); - $objectMock->customvars = array( - 'CUSTOMVAR' => 'test' - ); - - $helper = new Zend_View_Helper_ResolveMacros(); - $this->assertEquals($helper->resolveMacros('$CUSTOMVAR$', $objectMock), $objectMock->customvars['CUSTOMVAR']); - } - - public function testFaultyMacros() - { - $hostMock = Mockery::mock('host'); - $hostMock->host_name = 'test'; - $hostMock->customvars = array( - 'HOST' => 'te', - 'NAME' => 'st' - ); - - $helper = new Zend_View_Helper_ResolveMacros(); - $this->assertEquals( - $helper->resolveMacros('$$HOSTNAME$ $ HOSTNAME$ $HOST$NAME$', $hostMock), - '$test $ HOSTNAME$ teNAME$' - ); - } - - public function testMacrosWithSpecialCharacters() - { - $objectMock = Mockery::mock('object'); - $objectMock->customvars = array( - 'V€RY_SP3C|@L' => 'not too special!' - ); - - $helper = new Zend_View_Helper_ResolveMacros(); - $this->assertEquals( - $helper->resolveMacros('$V€RY_SP3C|@L$', $objectMock), - $objectMock->customvars['V€RY_SP3C|@L'] - ); - } -} diff --git a/modules/monitoring/test/php/library/Monitoring/Object/MacroTest.php b/modules/monitoring/test/php/library/Monitoring/Object/MacroTest.php new file mode 100644 index 000000000..88cebe63e --- /dev/null +++ b/modules/monitoring/test/php/library/Monitoring/Object/MacroTest.php @@ -0,0 +1,78 @@ +host_name = 'test'; + $hostMock->host_address = '1.1.1.1'; + + $this->assertEquals(Macro::resolveMacros('$HOSTNAME$', $hostMock), $hostMock->host_name); + $this->assertEquals(Macro::resolveMacros('$HOSTADDRESS$', $hostMock), $hostMock->host_address); + $this->assertEquals(Macro::resolveMacros('$host.name$', $hostMock), $hostMock->host_name); + $this->assertEquals(Macro::resolveMacros('$host.address$', $hostMock), $hostMock->host_address); + } + + public function testServiceMacros() + { + $svcMock = Mockery::mock('service'); + $svcMock->host_name = 'test'; + $svcMock->host_address = '1.1.1.1'; + $svcMock->service_description = 'a service'; + + $this->assertEquals(Macro::resolveMacros('$HOSTNAME$', $svcMock), $svcMock->host_name); + $this->assertEquals(Macro::resolveMacros('$HOSTADDRESS$', $svcMock), $svcMock->host_address); + $this->assertEquals(Macro::resolveMacros('$SERVICEDESC$', $svcMock), $svcMock->service_description); + $this->assertEquals(Macro::resolveMacros('$host.name$', $svcMock), $svcMock->host_name); + $this->assertEquals(Macro::resolveMacros('$host.address$', $svcMock), $svcMock->host_address); + $this->assertEquals(Macro::resolveMacros('$service.description', $svcMock), $svcMock->service_description); + } + + public function testCustomvars() + { + $objectMock = Mockery::mock('object'); + $objectMock->customvars = array( + 'CUSTOMVAR' => 'test' + ); + + $this->assertEquals(Macro::resolveMacros('$CUSTOMVAR$', $objectMock), $objectMock->customvars['CUSTOMVAR']); + } + + public function testFaultyMacros() + { + $hostMock = Mockery::mock('host'); + $hostMock->host_name = 'test'; + $hostMock->customvars = array( + 'HOST' => 'te', + 'NAME' => 'st' + ); + + $this->assertEquals( + Macro::resolveMacros('$$HOSTNAME$ $ HOSTNAME$ $HOST$NAME$', $hostMock), + '$test $ HOSTNAME$ teNAME$' + ); + } + + public function testMacrosWithSpecialCharacters() + { + $objectMock = Mockery::mock('object'); + $objectMock->customvars = array( + 'V€RY_SP3C|@L' => 'not too special!' + ); + + $this->assertEquals( + Macro::resolveMacros('$V€RY_SP3C|@L$', $objectMock), + $objectMock->customvars['V€RY_SP3C|@L'] + ); + } +}