Merge pull request #4640 from Icinga/php-81-support

PHP 8.1 Support
This commit is contained in:
Johannes Meyer 2022-03-24 15:40:01 +01:00 committed by GitHub
commit 42997566bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
91 changed files with 383 additions and 1326 deletions

View File

@ -17,14 +17,8 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
php: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0'] php: ['7.2', '7.3', '7.4', '8.0', '8.1']
os: ['ubuntu-latest'] os: ['ubuntu-latest']
include:
- php: '5.6'
allow_failure: true
phplint_options: "--exclude='{(?>.*/)?test/php/.*}' --exclude=library/Icinga/Test/BaseTestCase.php"
- php: '7.0'
allow_failure: true
steps: steps:
- name: Checkout code base - name: Checkout code base
@ -52,16 +46,16 @@ jobs:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
env: env:
phpunit-version: 9.5.4 phpunit-version: 9.5
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
php: ['7.2', '7.3', '7.4', '8.0'] php: ['7.2', '7.3', '7.4', '8.0', '8.1']
os: ['ubuntu-latest'] os: ['ubuntu-latest']
include: include:
- php: '7.2' - php: '7.2'
phpunit-version: 8.5.15 phpunit-version: 8.5
services: services:
mysql: mysql:

View File

@ -1,6 +1,6 @@
# Icinga Web 2 # Icinga Web 2
[![PHP Support](https://img.shields.io/badge/php-%3E%3D%205.6-777BB4?logo=PHP)](https://php.net/) [![PHP Support](https://img.shields.io/badge/php-%3E%3D%207.2-777BB4?logo=PHP)](https://php.net/)
![Build Status](https://github.com/icinga/icingaweb2/workflows/PHP%20Tests/badge.svg?branch=master) ![Build Status](https://github.com/icinga/icingaweb2/workflows/PHP%20Tests/badge.svg?branch=master)
[![Github Tag](https://img.shields.io/github/tag/Icinga/icingaweb2.svg)](https://github.com/Icinga/icingaweb2) [![Github Tag](https://img.shields.io/github/tag/Icinga/icingaweb2.svg)](https://github.com/Icinga/icingaweb2)

View File

@ -41,7 +41,7 @@ class ApplicationStateController extends Controller
setcookie( setcookie(
'icingaweb2-session', 'icingaweb2-session',
$now, $now,
null, 0,
$params['path'], $params['path'],
$params['domain'], $params['domain'],
$params['secure'], $params['secure'],

View File

@ -448,7 +448,7 @@ class RoleForm extends RepositoryForm
$b = array_shift($bParts); $b = array_shift($bParts);
} while ($a === $b); } while ($a === $b);
return strnatcmp($a, $b); return strnatcmp($a ?? '', $b ?? '');
}); });
} }

View File

@ -38,8 +38,7 @@ thoroughly.
* [Icinga 2](https://icinga.com/products/icinga-2/) with the IDO database backend (MySQL or PostgreSQL) * [Icinga 2](https://icinga.com/products/icinga-2/) with the IDO database backend (MySQL or PostgreSQL)
* A web server, e.g. Apache or Nginx * A web server, e.g. Apache or Nginx
* PHP version >= 7.3 * PHP version >= 7.2
* Older versions (5.6+) are only supported up until Icinga Web v2.11
### Optional Requirements ### Optional Requirements
* For exports to PDF also the following PHP modules are required: mbstring, GD, Imagick * For exports to PDF also the following PHP modules are required: mbstring, GD, Imagick
@ -388,8 +387,7 @@ You will need to install certain dependencies depending on your setup:
* [Icinga 2](https://icinga.com/products/icinga-2/) with the IDO database backend (MySQL or PostgreSQL) * [Icinga 2](https://icinga.com/products/icinga-2/) with the IDO database backend (MySQL or PostgreSQL)
* A web server, e.g. Apache or Nginx * A web server, e.g. Apache or Nginx
* PHP version >= 7.3 * PHP version >= 7.2
* Older versions (5.6+) are only supported up until version 2.11
* [Icinga PHP Library (ipl)](https://github.com/Icinga/icinga-php-library) (>= 0.8) * [Icinga PHP Library (ipl)](https://github.com/Icinga/icinga-php-library) (>= 0.8)
* [Icinga PHP Thirdparty](https://github.com/Icinga/icinga-php-thirdparty) (>= 0.10) * [Icinga PHP Thirdparty](https://github.com/Icinga/icinga-php-thirdparty) (>= 0.10)
* The following PHP modules must be installed: cURL, json, gettext, fileinfo, intl, dom, OpenSSL and xml * The following PHP modules must be installed: cURL, json, gettext, fileinfo, intl, dom, OpenSSL and xml

View File

@ -232,7 +232,7 @@ class Benchmark
round(($m->timestamp - floor($m->timestamp)) * 1000) round(($m->timestamp - floor($m->timestamp)) * 1000)
); );
$vals = array( $vals = array(
date('H:i:s', $m->timestamp) . '.' . $micro, date('H:i:s', (int) $m->timestamp) . '.' . $micro,
$m->message $m->message
); );

View File

@ -119,11 +119,11 @@ class Cli extends ApplicationBootstrap
if ($this->params->shift('autocomplete')) { if ($this->params->shift('autocomplete')) {
$this->params->unshift('autocomplete'); $this->params->unshift('autocomplete');
} }
$watch = $this->params->shift('watch'); $watch = $this->params->shift('watch');
if ($watch === true) { if ($watch === true) {
$watch = 5; $this->watchTimeout = 5;
} } elseif (is_numeric($watch)) {
if (preg_match('~^\d+$~', $watch)) {
$this->watchTimeout = (int) $watch; $this->watchTimeout = (int) $watch;
} }

View File

@ -122,7 +122,7 @@ class Config implements Countable, Iterator, Selectable
* *
* @return int * @return int
*/ */
public function count() public function count(): int
{ {
return $this->select()->count(); return $this->select()->count();
} }
@ -130,11 +130,11 @@ class Config implements Countable, Iterator, Selectable
/** /**
* Reset the current position of the internal config object * Reset the current position of the internal config object
* *
* @return ConfigObject * @return void
*/ */
public function rewind() public function rewind(): void
{ {
return $this->config->rewind(); $this->config->rewind();
} }
/** /**
@ -142,7 +142,7 @@ class Config implements Countable, Iterator, Selectable
* *
* @return ConfigObject * @return ConfigObject
*/ */
public function current() public function current(): ConfigObject
{ {
return $this->config->current(); return $this->config->current();
} }
@ -152,7 +152,7 @@ class Config implements Countable, Iterator, Selectable
* *
* @return bool * @return bool
*/ */
public function valid() public function valid(): bool
{ {
return $this->config->valid(); return $this->config->valid();
} }
@ -162,7 +162,7 @@ class Config implements Countable, Iterator, Selectable
* *
* @return string * @return string
*/ */
public function key() public function key(): string
{ {
return $this->config->key(); return $this->config->key();
} }
@ -170,11 +170,11 @@ class Config implements Countable, Iterator, Selectable
/** /**
* Advance the position of the current iteration and return the new section * Advance the position of the current iteration and return the new section
* *
* @return ConfigObject * @return void
*/ */
public function next() public function next(): void
{ {
return $this->config->next(); $this->config->next();
} }
/** /**

View File

@ -34,26 +34,17 @@ class TicketPattern implements ArrayAccess
*/ */
protected $pattern; protected $pattern;
/** public function offsetExists($offset): bool
* {@inheritdoc}
*/
public function offsetExists($offset)
{ {
return isset($this->match[$offset]); return isset($this->match[$offset]);
} }
/** public function offsetGet($offset): ?string
* {@inheritdoc}
*/
public function offsetGet($offset)
{ {
return array_key_exists($offset, $this->match) ? $this->match[$offset] : null; return array_key_exists($offset, $this->match) ? $this->match[$offset] : null;
} }
/** public function offsetSet($offset, $value): void
* {@inheritdoc}
*/
public function offsetSet($offset, $value)
{ {
if ($offset === null) { if ($offset === null) {
$this->match[] = $value; $this->match[] = $value;
@ -62,10 +53,7 @@ class TicketPattern implements ArrayAccess
} }
} }
/** public function offsetUnset($offset): void
* {@inheritdoc}
*/
public function offsetUnset($offset)
{ {
unset($this->match[$offset]); unset($this->match[$offset]);
} }

View File

@ -6,6 +6,7 @@ namespace Icinga\Application;
use ArrayIterator; use ArrayIterator;
use IteratorAggregate; use IteratorAggregate;
use Icinga\Application\Libraries\Library; use Icinga\Application\Libraries\Library;
use Traversable;
class Libraries implements IteratorAggregate class Libraries implements IteratorAggregate
{ {
@ -17,7 +18,7 @@ class Libraries implements IteratorAggregate
* *
* @return ArrayIterator * @return ArrayIterator
*/ */
public function getIterator() public function getIterator(): Traversable
{ {
return new ArrayIterator($this->libraries); return new ArrayIterator($this->libraries);
} }

View File

@ -14,7 +14,7 @@ use ipl\I18n\StaticTranslator;
* *
* @return string * @return string
*/ */
function N_($messageId) function N_(string $messageId): string
{ {
return $messageId; return $messageId;
} }
@ -30,7 +30,7 @@ if (extension_loaded('gettext')) {
/** /**
* @see Translator::translate() For the function documentation. * @see Translator::translate() For the function documentation.
*/ */
function t($messageId, $context = null) function t(string $messageId, ?string $context = null): string
{ {
return StaticTranslator::$instance->translate($messageId, $context); return StaticTranslator::$instance->translate($messageId, $context);
} }
@ -38,7 +38,7 @@ if (extension_loaded('gettext')) {
/** /**
* @see Translator::translateInDomain() For the function documentation. * @see Translator::translateInDomain() For the function documentation.
*/ */
function mt($domain, $messageId, $context = null) function mt(string $domain, string $messageId, ?string $context = null): string
{ {
return StaticTranslator::$instance->translateInDomain($domain, $messageId, $context); return StaticTranslator::$instance->translateInDomain($domain, $messageId, $context);
} }
@ -46,21 +46,21 @@ if (extension_loaded('gettext')) {
/** /**
* @see Translator::translatePlural() For the function documentation. * @see Translator::translatePlural() For the function documentation.
*/ */
function tp($messageId, $messageId2, $number, $context = null) function tp(string $messageId, string $messageId2, ?int $number, ?string $context = null): string
{ {
return StaticTranslator::$instance->translatePlural($messageId, $messageId2, $number, $context); return StaticTranslator::$instance->translatePlural($messageId, $messageId2, $number ?? 0, $context);
} }
/** /**
* @see Translator::translatePluralInDomain() For the function documentation. * @see Translator::translatePluralInDomain() For the function documentation.
*/ */
function mtp($domain, $messageId, $messageId2, $number, $context = null) function mtp(string $domain, string $messageId, string $messageId2, ?int $number, ?string $context = null): string
{ {
return StaticTranslator::$instance->translatePluralInDomain( return StaticTranslator::$instance->translatePluralInDomain(
$domain, $domain,
$messageId, $messageId,
$messageId2, $messageId2,
$number, $number ?? 0,
$context $context
); );
} }
@ -70,7 +70,7 @@ if (extension_loaded('gettext')) {
/** /**
* @see Translator::translate() For the function documentation. * @see Translator::translate() For the function documentation.
*/ */
function t($messageId, $context = null) function t(string $messageId, ?string $context = null): string
{ {
return $messageId; return $messageId;
} }
@ -78,7 +78,7 @@ if (extension_loaded('gettext')) {
/** /**
* @see Translator::translate() For the function documentation. * @see Translator::translate() For the function documentation.
*/ */
function mt($domain, $messageId, $context = null) function mt(string $domain, string $messageId, ?string $context = null): string
{ {
return $messageId; return $messageId;
} }
@ -86,7 +86,7 @@ if (extension_loaded('gettext')) {
/** /**
* @see Translator::translatePlural() For the function documentation. * @see Translator::translatePlural() For the function documentation.
*/ */
function tp($messageId, $messageId2, $number, $context = null) function tp(string $messageId, string $messageId2, ?int $number, ?string $context = null): string
{ {
if ((int) $number !== 1) { if ((int) $number !== 1) {
return $messageId2; return $messageId2;
@ -98,7 +98,7 @@ if (extension_loaded('gettext')) {
/** /**
* @see Translator::translatePlural() For the function documentation. * @see Translator::translatePlural() For the function documentation.
*/ */
function mtp($domain, $messageId, $messageId2, $number, $context = null) function mtp(string $domain, string $messageId, string $messageId2, ?int $number, ?string $context = null): string
{ {
if ((int) $number !== 1) { if ((int) $number !== 1) {
return $messageId2; return $messageId2;

View File

@ -331,7 +331,7 @@ class Auth
setcookie( setcookie(
'icingaweb2-session', 'icingaweb2-session',
time(), time(),
null, 0,
$params['path'], $params['path'],
$params['domain'], $params['domain'],
$params['secure'], $params['secure'],

View File

@ -184,12 +184,12 @@ class AuthChain implements Authenticatable, Iterator
/** /**
* Rewind the chain * Rewind the chain
* *
* @return ConfigObject * @return void
*/ */
public function rewind() public function rewind(): void
{ {
$this->currentBackend = null; $this->currentBackend = null;
return $this->config->rewind(); $this->config->rewind();
} }
/** /**
@ -197,7 +197,7 @@ class AuthChain implements Authenticatable, Iterator
* *
* @return UserBackendInterface * @return UserBackendInterface
*/ */
public function current() public function current(): UserBackendInterface
{ {
return $this->currentBackend; return $this->currentBackend;
} }
@ -207,7 +207,7 @@ class AuthChain implements Authenticatable, Iterator
* *
* @return string * @return string
*/ */
public function key() public function key(): string
{ {
return $this->config->key(); return $this->config->key();
} }
@ -215,11 +215,11 @@ class AuthChain implements Authenticatable, Iterator
/** /**
* Move forward to the next user backend config * Move forward to the next user backend config
* *
* @return ConfigObject * @return void
*/ */
public function next() public function next(): void
{ {
return $this->config->next(); $this->config->next();
} }
/** /**
@ -228,7 +228,7 @@ class AuthChain implements Authenticatable, Iterator
* *
* @return bool * @return bool
*/ */
public function valid() public function valid(): bool
{ {
if (! $this->config->valid()) { if (! $this->config->valid()) {
// Stop when there are no more backends to check // Stop when there are no more backends to check

View File

@ -203,6 +203,10 @@ class DbUserBackend extends DbRepository implements UserBackendInterface, Inspec
$lob = stream_get_contents($lob); $lob = stream_get_contents($lob);
} }
if ($lob === null) {
return '';
}
return $this->ds->getDbType() === 'pgsql' ? pg_unescape_bytea($lob) : $lob; return $this->ds->getDbType() === 'pgsql' ? pg_unescape_bytea($lob) : $lob;
} }

View File

@ -88,7 +88,7 @@ class LdapUserBackend extends LdapRepository implements UserBackendInterface, Do
*/ */
public function setBaseDn($baseDn) public function setBaseDn($baseDn)
{ {
if (($baseDn = trim($baseDn))) { if ($baseDn && ($baseDn = trim($baseDn))) {
$this->baseDn = $baseDn; $this->baseDn = $baseDn;
} }
@ -160,7 +160,7 @@ class LdapUserBackend extends LdapRepository implements UserBackendInterface, Do
*/ */
public function setFilter($filter) public function setFilter($filter)
{ {
if (($filter = trim($filter))) { if ($filter && ($filter = trim($filter))) {
if ($filter[0] === '(') { if ($filter[0] === '(') {
$filter = substr($filter, 1, -1); $filter = substr($filter, 1, -1);
} }
@ -195,9 +195,7 @@ class LdapUserBackend extends LdapRepository implements UserBackendInterface, Do
*/ */
public function setDomain($domain) public function setDomain($domain)
{ {
$domain = trim($domain); if ($domain && ($domain = trim($domain))) {
if (strlen($domain)) {
$this->domain = $domain; $this->domain = $domain;
} }

View File

@ -169,7 +169,7 @@ class LdapUserGroupBackend extends LdapRepository implements Inspectable, UserGr
*/ */
public function setUserBaseDn($baseDn) public function setUserBaseDn($baseDn)
{ {
if (($baseDn = trim($baseDn))) { if ($baseDn && ($baseDn = trim($baseDn))) {
$this->userBaseDn = $baseDn; $this->userBaseDn = $baseDn;
} }
@ -195,7 +195,7 @@ class LdapUserGroupBackend extends LdapRepository implements Inspectable, UserGr
*/ */
public function setGroupBaseDn($baseDn) public function setGroupBaseDn($baseDn)
{ {
if (($baseDn = trim($baseDn))) { if ($baseDn && ($baseDn = trim($baseDn))) {
$this->groupBaseDn = $baseDn; $this->groupBaseDn = $baseDn;
} }
@ -336,7 +336,7 @@ class LdapUserGroupBackend extends LdapRepository implements Inspectable, UserGr
*/ */
public function setUserFilter($filter) public function setUserFilter($filter)
{ {
if (($filter = trim($filter))) { if ($filter && ($filter = trim($filter))) {
if ($filter[0] === '(') { if ($filter[0] === '(') {
$filter = substr($filter, 1, -1); $filter = substr($filter, 1, -1);
} }
@ -366,7 +366,7 @@ class LdapUserGroupBackend extends LdapRepository implements Inspectable, UserGr
*/ */
public function setGroupFilter($filter) public function setGroupFilter($filter)
{ {
if (($filter = trim($filter))) { if ($filter && ($filter = trim($filter))) {
$this->groupFilter = $filter; $this->groupFilter = $filter;
} }
@ -431,9 +431,7 @@ class LdapUserGroupBackend extends LdapRepository implements Inspectable, UserGr
*/ */
public function setDomain($domain) public function setDomain($domain)
{ {
$domain = trim($domain); if ($domain && ($domain = trim($domain))) {
if (strlen($domain)) {
$this->domain = $domain; $this->domain = $domain;
} }

View File

@ -131,7 +131,7 @@ class SVGRenderer
'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'
); );
$this->document = $implementation->createDocument(null, null, $docType); $this->document = $implementation->createDocument(null, '', $docType);
$this->svg = $this->createOuterBox(); $this->svg = $this->createOuterBox();
$this->document->appendChild($this->svg); $this->document->appendChild($this->svg);
} }

View File

@ -68,10 +68,16 @@ class CommentParser
public function dump() public function dump()
{ {
$res = $this->title . "\n" . str_repeat('=', strlen($this->title)) . "\n\n"; if ($this->title) {
$res = $this->title . "\n" . str_repeat('=', strlen($this->title)) . "\n\n";
} else {
$res = '';
}
foreach ($this->paragraphs as $p) { foreach ($this->paragraphs as $p) {
$res .= wordwrap($p, 72) . "\n\n"; $res .= wordwrap($p, 72) . "\n\n";
} }
return $res; return $res;
} }
} }

View File

@ -276,6 +276,10 @@ class Loader
protected function searchMatch($needle, $haystack) protected function searchMatch($needle, $haystack)
{ {
if ($needle === null) {
$needle = '';
}
$this->lastSuggestions = preg_grep(sprintf('/^%s.*$/', preg_quote($needle, '/')), $haystack); $this->lastSuggestions = preg_grep(sprintf('/^%s.*$/', preg_quote($needle, '/')), $haystack);
$match = array_search($needle, $haystack, true); $match = array_search($needle, $haystack, true);
if (false !== $match) { if (false !== $match) {
@ -358,7 +362,7 @@ class Loader
} elseif (! empty($step['object'])) { } elseif (! empty($step['object'])) {
$object = (string) $step['object'] . $step['type']; $object = (string) $step['object'] . $step['type'];
} }
if (is_array($step['args'])) { if (isset($step['args']) && is_array($step['args'])) {
foreach ($step['args'] as & $arg) { foreach ($step['args'] as & $arg) {
if (is_object($arg)) { if (is_object($arg)) {
$arg = sprintf('[%s]', get_class($arg)); $arg = sprintf('[%s]', get_class($arg));

View File

@ -50,11 +50,11 @@ class ConfigObject extends ArrayDatasource implements Iterator, ArrayAccess
/** /**
* Reset the current position of $this->data * Reset the current position of $this->data
* *
* @return mixed * @return void
*/ */
public function rewind() public function rewind(): void
{ {
return reset($this->data); reset($this->data);
} }
/** /**
@ -62,6 +62,7 @@ class ConfigObject extends ArrayDatasource implements Iterator, ArrayAccess
* *
* @return mixed * @return mixed
*/ */
#[\ReturnTypeWillChange]
public function current() public function current()
{ {
return current($this->data); return current($this->data);
@ -72,7 +73,7 @@ class ConfigObject extends ArrayDatasource implements Iterator, ArrayAccess
* *
* @return bool * @return bool
*/ */
public function valid() public function valid(): bool
{ {
return key($this->data) !== null; return key($this->data) !== null;
} }
@ -80,9 +81,9 @@ class ConfigObject extends ArrayDatasource implements Iterator, ArrayAccess
/** /**
* Return the section's or property's name of the current iteration * Return the section's or property's name of the current iteration
* *
* @return mixed * @return string
*/ */
public function key() public function key(): string
{ {
return key($this->data); return key($this->data);
} }
@ -90,11 +91,11 @@ class ConfigObject extends ArrayDatasource implements Iterator, ArrayAccess
/** /**
* Advance the position of the current iteration and return the new section's or property's value * Advance the position of the current iteration and return the new section's or property's value
* *
* @return mixed * @return void
*/ */
public function next() public function next(): void
{ {
return next($this->data); next($this->data);
} }
/** /**
@ -153,7 +154,7 @@ class ConfigObject extends ArrayDatasource implements Iterator, ArrayAccess
* *
* @return bool * @return bool
*/ */
public function offsetExists($key) public function offsetExists($key): bool
{ {
return isset($this->$key); return isset($this->$key);
} }
@ -163,8 +164,9 @@ class ConfigObject extends ArrayDatasource implements Iterator, ArrayAccess
* *
* @param string $key The name of the property or section * @param string $key The name of the property or section
* *
* @return mixed|NULL The value or NULL in case $key does not exist * @return ?mixed The value or NULL in case $key does not exist
*/ */
#[\ReturnTypeWillChange]
public function offsetGet($key) public function offsetGet($key)
{ {
return $this->get($key); return $this->get($key);
@ -178,7 +180,7 @@ class ConfigObject extends ArrayDatasource implements Iterator, ArrayAccess
* *
* @throws ProgrammingError If the key is null * @throws ProgrammingError If the key is null
*/ */
public function offsetSet($key, $value) public function offsetSet($key, $value): void
{ {
if ($key === null) { if ($key === null) {
throw new ProgrammingError('Appending values without an explicit key is not supported'); throw new ProgrammingError('Appending values without an explicit key is not supported');
@ -192,7 +194,7 @@ class ConfigObject extends ArrayDatasource implements Iterator, ArrayAccess
* *
* @param string $key The property or section to remove * @param string $key The property or section to remove
*/ */
public function offsetUnset($key) public function offsetUnset($key): void
{ {
unset($this->$key); unset($this->$key);
} }

View File

@ -356,13 +356,13 @@ class DbQuery extends SimpleQuery
} }
return '(' . implode(" $operator ", $sql) . ')'; return '(' . implode(" $operator ", $sql) . ')';
} elseif ($sign === '=' && strpos($expression, '*') !== false) { } elseif ($sign === '=' && $expression !== null && strpos($expression, '*') !== false) {
if ($expression === '*') { if ($expression === '*') {
return $col . ' IS NOT NULL'; return $col . ' IS NOT NULL';
} }
return $col . ' LIKE ' . $this->escapeForSql($this->escapeWildcards($expression)); return $col . ' LIKE ' . $this->escapeForSql($this->escapeWildcards($expression));
} elseif ($sign === '!=' && strpos($expression, '*') !== false) { } elseif ($sign === '!=' && $expression !== null && strpos($expression, '*') !== false) {
if ($expression === '*') { if ($expression === '*') {
return $col . ' IS NULL'; return $col . ' IS NULL';
} }
@ -410,7 +410,7 @@ class DbQuery extends SimpleQuery
* *
* @return int * @return int
*/ */
public function count() public function count(): int
{ {
if ($this->count === null) { if ($this->count === null) {
$this->count = parent::count(); $this->count = parent::count();

View File

@ -152,7 +152,10 @@ class FilterExpression extends Filter
*/ */
protected function strtolowerRecursive($var) protected function strtolowerRecursive($var)
{ {
if ($var === null || is_scalar($var)) { if ($var === null) {
return '';
}
if (is_scalar($var)) {
return strtolower($var); return strtolower($var);
} }
if (is_array($var)) { if (is_array($var)) {
@ -206,7 +209,7 @@ class FilterExpression extends Filter
return false; return false;
} }
return (bool) preg_match($pattern, $rowValue); return $rowValue !== null && preg_match($pattern, $rowValue);
} }
public function andFilter(Filter $filter) public function andFilter(Filter $filter)

View File

@ -263,7 +263,7 @@ class FilterQueryString
$this->string = $string; $this->string = $string;
$this->length = strlen($string); $this->length = $string ? strlen($string) : 0;
if ($this->length === 0) { if ($this->length === 0) {
return Filter::matchAll(); return Filter::matchAll();

View File

@ -165,7 +165,7 @@ class SimpleQuery implements QueryInterface, Queryable, Iterator
/** /**
* Start or rewind the iteration * Start or rewind the iteration
*/ */
public function rewind() public function rewind(): void
{ {
if ($this->iterator === null) { if ($this->iterator === null) {
$iterator = $this->ds->query($this); $iterator = $this->ds->query($this);
@ -184,8 +184,9 @@ class SimpleQuery implements QueryInterface, Queryable, Iterator
/** /**
* Fetch and return the current row of this query's result * Fetch and return the current row of this query's result
* *
* @return object * @return mixed
*/ */
#[\ReturnTypeWillChange]
public function current() public function current()
{ {
return $this->iterator->current(); return $this->iterator->current();
@ -196,7 +197,7 @@ class SimpleQuery implements QueryInterface, Queryable, Iterator
* *
* @return bool * @return bool
*/ */
public function valid() public function valid(): bool
{ {
$valid = $this->iterator->valid(); $valid = $this->iterator->valid();
if ($valid && $this->peekAhead && $this->hasLimit() && $this->iteratorPosition + 1 === $this->getLimit()) { if ($valid && $this->peekAhead && $this->hasLimit() && $this->iteratorPosition + 1 === $this->getLimit()) {
@ -221,6 +222,7 @@ class SimpleQuery implements QueryInterface, Queryable, Iterator
* *
* @return mixed * @return mixed
*/ */
#[\ReturnTypeWillChange]
public function key() public function key()
{ {
return $this->iterator->key(); return $this->iterator->key();
@ -229,7 +231,7 @@ class SimpleQuery implements QueryInterface, Queryable, Iterator
/** /**
* Advance to the next row of this query's result * Advance to the next row of this query's result
*/ */
public function next() public function next(): void
{ {
$this->iterator->next(); $this->iterator->next();
$this->iteratorPosition += 1; $this->iteratorPosition += 1;
@ -376,7 +378,7 @@ class SimpleQuery implements QueryInterface, Queryable, Iterator
$column = $this->flippedColumns[$column]; $column = $this->flippedColumns[$column];
} }
$result = strcmp(strtolower($a->$column), strtolower($b->$column)); $result = strcmp(strtolower($a->$column ?: ''), strtolower($b->$column ?: ''));
if ($result === 0) { if ($result === 0) {
return $this->compare($a, $b, ++$orderIndex); return $this->compare($a, $b, ++$orderIndex);
} }
@ -648,7 +650,7 @@ class SimpleQuery implements QueryInterface, Queryable, Iterator
* *
* @return int * @return int
*/ */
public function count() public function count(): int
{ {
$query = clone $this; $query = clone $this;
$query->limit(0, 0); $query->limit(0, 0);

View File

@ -5,6 +5,7 @@ namespace Icinga\Data\Tree;
use IteratorAggregate; use IteratorAggregate;
use LogicException; use LogicException;
use Traversable;
/** /**
* A simple tree * A simple tree
@ -80,10 +81,9 @@ class SimpleTree implements IteratorAggregate
} }
/** /**
* {@inheritdoc}
* @return TreeNodeIterator * @return TreeNodeIterator
*/ */
public function getIterator() public function getIterator(): Traversable
{ {
return new TreeNodeIterator($this->sentinel); return new TreeNodeIterator($this->sentinel);
} }

View File

@ -28,59 +28,37 @@ class TreeNodeIterator implements RecursiveIterator
$this->children = new ArrayIterator($node->getChildren()); $this->children = new ArrayIterator($node->getChildren());
} }
/** public function current(): TreeNode
* {@inheritdoc}
*/
public function current()
{ {
return $this->children->current(); return $this->children->current();
} }
/** public function key(): int
* {@inheritdoc}
*/
public function key()
{ {
return $this->children->key(); return $this->children->key();
} }
/** public function next(): void
* {@inheritdoc}
*/
public function next()
{ {
$this->children->next(); $this->children->next();
} }
/** public function rewind(): void
* {@inheritdoc}
*/
public function rewind()
{ {
$this->children->rewind(); $this->children->rewind();
} }
/** public function valid(): bool
* {@inheritdoc}
*/
public function valid()
{ {
return $this->children->valid(); return $this->children->valid();
} }
/** public function hasChildren(): bool
* {@inheritdoc}
*/
public function hasChildren()
{ {
return $this->current()->hasChildren(); return $this->current()->hasChildren();
} }
/** public function getChildren(): TreeNodeIterator
* {@inheritdoc}
* @return TreeNodeIterator
*/
public function getChildren()
{ {
return new static($this->current()); return new static($this->current());
} }

View File

@ -48,7 +48,7 @@ class DateFormatter
{ {
$invert = false; $invert = false;
$now = time(); $now = time();
$time = (float) $time; $time = (int) $time;
$diff = $time - $now; $diff = $time - $now;
if ($diff < 0) { if ($diff < 0) {
$diff = abs($diff); $diff = abs($diff);
@ -94,7 +94,7 @@ class DateFormatter
*/ */
public static function formatDate($date) public static function formatDate($date)
{ {
return date('Y-m-d', (float) $date); return date('Y-m-d', (int) $date);
} }
/** /**
@ -106,7 +106,7 @@ class DateFormatter
*/ */
public static function formatDateTime($dateTime) public static function formatDateTime($dateTime)
{ {
return date('Y-m-d H:i:s', (float) $dateTime); return date('Y-m-d H:i:s', (int) $dateTime);
} }
/** /**
@ -141,7 +141,7 @@ class DateFormatter
*/ */
public static function formatTime($time) public static function formatTime($time)
{ {
return date('H:i:s', (float) $time); return date('H:i:s', (int) $time);
} }
/** /**

View File

@ -11,6 +11,7 @@ use Icinga\Exception\NotWritableError;
use InvalidArgumentException; use InvalidArgumentException;
use RecursiveDirectoryIterator; use RecursiveDirectoryIterator;
use RecursiveIteratorIterator; use RecursiveIteratorIterator;
use Traversable;
use UnexpectedValueException; use UnexpectedValueException;
/** /**
@ -35,10 +36,17 @@ class LocalFileStorage implements StorageInterface
$this->baseDir = rtrim($baseDir, DIRECTORY_SEPARATOR); $this->baseDir = rtrim($baseDir, DIRECTORY_SEPARATOR);
} }
public function getIterator() public function getIterator(): Traversable
{ {
try { try {
return new LocalFileStorageIterator($this->baseDir); return new RecursiveIteratorIterator(
new RecursiveDirectoryIterator(
$this->baseDir,
RecursiveDirectoryIterator::CURRENT_AS_FILEINFO
| RecursiveDirectoryIterator::KEY_AS_PATHNAME
| RecursiveDirectoryIterator::SKIP_DOTS
)
);
} catch (UnexpectedValueException $e) { } catch (UnexpectedValueException $e) {
throw new NotReadableError('Couldn\'t read the directory "%s": %s', $this->baseDir, $e); throw new NotReadableError('Couldn\'t read the directory "%s": %s', $this->baseDir, $e);
} }

View File

@ -1,44 +0,0 @@
<?php
/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */
namespace Icinga\File\Storage;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
/**
* @deprecated This class will be removed once we require PHP 5.6
*/
class LocalFileStorageIterator extends RecursiveIteratorIterator
{
/**
* Constructor
*
* @param string $baseDir
*/
public function __construct($baseDir)
{
parent::__construct(new RecursiveDirectoryIterator($baseDir, RecursiveDirectoryIterator::SKIP_DOTS));
}
public function key()
{
parent::key();
return $this->current();
}
public function current()
{
/** @var RecursiveDirectoryIterator $innerIterator */
$innerIterator = $this->getInnerIterator();
/** @var \SplFileInfo $current */
$current = parent::current();
$subPath = $innerIterator->getSubPath();
return $subPath === ''
? $current->getFilename()
: str_replace(DIRECTORY_SEPARATOR, '/', $subPath) . '/' . $current->getFilename();
}
}

View File

@ -19,7 +19,7 @@ interface StorageInterface extends IteratorAggregate
* *
* @throws NotReadableError If the file list can't be read * @throws NotReadableError If the file list can't be read
*/ */
public function getIterator(); public function getIterator(): Traversable;
/** /**
* Return whether the given file exists * Return whether the given file exists

View File

@ -44,7 +44,7 @@ class FileIterator extends EnumeratingFilterIterator
* *
* @return array * @return array
*/ */
public function current() public function current(): array
{ {
return $this->currentData; return $this->currentData;
} }
@ -56,7 +56,7 @@ class FileIterator extends EnumeratingFilterIterator
* *
* @throws FileReaderException If PHP failed parsing the PCRE pattern * @throws FileReaderException If PHP failed parsing the PCRE pattern
*/ */
public function accept() public function accept(): bool
{ {
$data = array(); $data = array();
$matched = preg_match( $matched = preg_match(

View File

@ -89,7 +89,7 @@ class FileReader implements Selectable, Countable
* *
* @return int * @return int
*/ */
public function count() public function count(): int
{ {
if ($this->count === null) { if ($this->count === null) {
$this->count = iterator_count($this->iterate()); $this->count = iterator_count($this->iterate());

View File

@ -30,7 +30,7 @@ class LogFileIterator implements Iterator
/** /**
* Value for static::current() * Value for static::current()
* *
* @var string * @var array
*/ */
protected $current; protected $current;
@ -68,40 +68,31 @@ class LogFileIterator implements Iterator
$this->fields = $fields; $this->fields = $fields;
} }
public function rewind() public function rewind(): void
{ {
$this->file->rewind(); $this->file->rewind();
$this->index = 0; $this->index = 0;
$this->nextMessage(); $this->nextMessage();
} }
public function next() public function next(): void
{ {
$this->file->next(); $this->file->next();
++$this->index; ++$this->index;
$this->nextMessage(); $this->nextMessage();
} }
/** public function current(): array
* @return string
*/
public function current()
{ {
return $this->current; return $this->current;
} }
/** public function key(): int
* @return int
*/
public function key()
{ {
return $this->index; return $this->index;
} }
/** public function valid(): bool
* @return boolean
*/
public function valid()
{ {
return $this->valid; return $this->valid;
} }

View File

@ -61,31 +61,11 @@ abstract class LdapRepository extends Repository
*/ */
protected function getNormedAttribute($name) protected function getNormedAttribute($name)
{ {
$loweredName = strtolower($name); $loweredName = strtolower($name ?? '');
if (array_key_exists($loweredName, $this->normedAttributes)) { if (array_key_exists($loweredName, $this->normedAttributes)) {
return $this->normedAttributes[$loweredName]; return $this->normedAttributes[$loweredName];
} }
return $name; return $name;
} }
/**
* Return whether the given object DN is related to the given base DN
*
* Will use the current connection's root DN if $baseDn is not given.
*
* @deprecated This was only used by LdapUserGroupBackend::isMemberAttributeAmbiguous
* It will be removed with 2.6.0!
*
* @param string $dn The object DN to check
* @param string $baseDn The base DN to compare the object DN with
*
* @return bool
*/
protected function isRelatedDn($dn, $baseDn = null)
{
$normalizedDn = strtolower(join(',', array_map('trim', explode(',', $dn))));
$normalizedBaseDn = strtolower(join(',', array_map('trim', explode(',', $baseDn ?: $this->ds->getDn()))));
return strpos($normalizedDn, $normalizedBaseDn) !== false;
}
} }

View File

@ -344,7 +344,9 @@ class RepositoryQuery implements QueryInterface, SortRules, FilterColumns, Itera
} }
} }
$baseDirection = strtoupper($sortColumns['order']) === static::SORT_DESC ? static::SORT_DESC : static::SORT_ASC; $baseDirection = isset($sortColumns['order']) && strtoupper($sortColumns['order']) === static::SORT_DESC
? static::SORT_DESC
: static::SORT_ASC;
foreach ($sortColumns['columns'] as $column) { foreach ($sortColumns['columns'] as $column) {
list($column, $specificDirection) = $this->splitOrder($column); list($column, $specificDirection) = $this->splitOrder($column);
@ -690,7 +692,7 @@ class RepositoryQuery implements QueryInterface, SortRules, FilterColumns, Itera
* *
* @return int * @return int
*/ */
public function count() public function count(): int
{ {
return $this->query->count(); return $this->query->count();
} }
@ -708,7 +710,7 @@ class RepositoryQuery implements QueryInterface, SortRules, FilterColumns, Itera
/** /**
* Start or rewind the iteration * Start or rewind the iteration
*/ */
public function rewind() public function rewind(): void
{ {
if ($this->iterator === null) { if ($this->iterator === null) {
if (! $this->hasOrder()) { if (! $this->hasOrder()) {
@ -735,8 +737,9 @@ class RepositoryQuery implements QueryInterface, SortRules, FilterColumns, Itera
/** /**
* Fetch and return the current row of this query's result * Fetch and return the current row of this query's result
* *
* @return object * @return mixed
*/ */
#[\ReturnTypeWillChange]
public function current() public function current()
{ {
$row = $this->iterator->current(); $row = $this->iterator->current();
@ -763,7 +766,7 @@ class RepositoryQuery implements QueryInterface, SortRules, FilterColumns, Itera
* *
* @return bool * @return bool
*/ */
public function valid() public function valid(): bool
{ {
if (! $this->iterator->valid()) { if (! $this->iterator->valid()) {
Benchmark::measure('Query result iteration finished'); Benchmark::measure('Query result iteration finished');
@ -778,6 +781,7 @@ class RepositoryQuery implements QueryInterface, SortRules, FilterColumns, Itera
* *
* @return mixed * @return mixed
*/ */
#[\ReturnTypeWillChange]
public function key() public function key()
{ {
return $this->iterator->key(); return $this->iterator->key();
@ -786,7 +790,7 @@ class RepositoryQuery implements QueryInterface, SortRules, FilterColumns, Itera
/** /**
* Advance to the next row of this query's result * Advance to the next row of this query's result
*/ */
public function next() public function next(): void
{ {
$this->iterator->next(); $this->iterator->next();
} }

View File

@ -432,9 +432,7 @@ class User
*/ */
public function setDomain($domain) public function setDomain($domain)
{ {
$domain = trim($domain); if ($domain && ($domain = trim($domain))) {
if (strlen($domain)) {
$this->domain = $domain; $this->domain = $domain;
} }

View File

@ -49,7 +49,7 @@ class Preferences implements Countable
* *
* @return int The number of preferences * @return int The number of preferences
*/ */
public function count() public function count(): int
{ {
return count($this->preferences); return count($this->preferences);
} }

View File

@ -50,7 +50,7 @@ class DirectoryIterator implements RecursiveIterator
/** /**
* Current key * Current key
* *
* @var string * @var string|false
*/ */
private $key; private $key;
@ -122,35 +122,23 @@ class DirectoryIterator implements RecursiveIterator
return is_dir($path) && is_readable($path); return is_dir($path) && is_readable($path);
} }
/** public function hasChildren(): bool
* {@inheritdoc}
*/
public function hasChildren()
{ {
return static::isReadable($this->current); return static::isReadable($this->current);
} }
/** public function getChildren(): DirectoryIterator
* {@inheritdoc}
*/
public function getChildren()
{ {
return new static($this->current, $this->extension, $this->flags); return new static($this->current, $this->extension, $this->flags);
} }
#[\ReturnTypeWillChange]
/**
* {@inheritdoc}
*/
public function current() public function current()
{ {
return $this->current; return $this->current;
} }
/** public function next(): void
* {@inheritdoc}
*/
public function next()
{ {
do { do {
$this->files->next(); $this->files->next();
@ -200,26 +188,18 @@ class DirectoryIterator implements RecursiveIterator
$this->key = $file; $this->key = $file;
} }
/** #[\ReturnTypeWillChange]
* {@inheritdoc}
*/
public function key() public function key()
{ {
return $this->key; return $this->key;
} }
/** public function valid(): bool
* {@inheritdoc}
*/
public function valid()
{ {
return $this->current !== false; return $this->current !== false;
} }
/** public function rewind(): void
* {@inheritdoc}
*/
public function rewind()
{ {
if ($this->files === null) { if ($this->files === null) {
$files = scandir($this->path); $files = scandir($this->path);

View File

@ -17,19 +17,13 @@ abstract class EnumeratingFilterIterator extends FilterIterator
*/ */
private $index; private $index;
/** public function rewind(): void
* @return void
*/
public function rewind()
{ {
parent::rewind(); parent::rewind();
$this->index = 0; $this->index = 0;
} }
/** public function key(): int
* @return int
*/
public function key()
{ {
return $this->index++; return $this->index++;
} }

View File

@ -114,9 +114,7 @@ class File extends SplFileObject
} }
} }
/** #[\ReturnTypeWillChange]
* @see SplFileObject::fwrite()
*/
public function fwrite($str, $length = null) public function fwrite($str, $length = null)
{ {
$this->assertOpenForWriting(); $this->assertOpenForWriting();
@ -126,10 +124,7 @@ class File extends SplFileObject
return $retVal; return $retVal;
} }
/** public function ftruncate($size): bool
* @see SplFileObject::ftruncate()
*/
public function ftruncate($size)
{ {
$this->assertOpenForWriting(); $this->assertOpenForWriting();
$this->setupErrorHandler(); $this->setupErrorHandler();
@ -138,9 +133,7 @@ class File extends SplFileObject
return $retVal; return $retVal;
} }
/** #[\ReturnTypeWillChange]
* @see SplFileObject::ftell()
*/
public function ftell() public function ftell()
{ {
$this->setupErrorHandler(); $this->setupErrorHandler();
@ -149,10 +142,7 @@ class File extends SplFileObject
return $retVal; return $retVal;
} }
/** public function flock($operation, &$wouldblock = null): bool
* @see SplFileObject::flock()
*/
public function flock($operation, &$wouldblock = null)
{ {
$this->setupErrorHandler(); $this->setupErrorHandler();
$retVal = parent::flock($operation, $wouldblock); $retVal = parent::flock($operation, $wouldblock);
@ -160,9 +150,7 @@ class File extends SplFileObject
return $retVal; return $retVal;
} }
/** #[\ReturnTypeWillChange]
* @see SplFileObject::fgetc()
*/
public function fgetc() public function fgetc()
{ {
$this->setupErrorHandler(); $this->setupErrorHandler();
@ -171,10 +159,7 @@ class File extends SplFileObject
return $retVal; return $retVal;
} }
/** public function fflush(): bool
* @see SplFileObject::fflush()
*/
public function fflush()
{ {
$this->setupErrorHandler(); $this->setupErrorHandler();
$retVal = parent::fflush(); $retVal = parent::fflush();

View File

@ -19,6 +19,10 @@ class StringHelper
*/ */
public static function trimSplit($value, $delimiter = ',', $limit = null) public static function trimSplit($value, $delimiter = ',', $limit = null)
{ {
if ($value === null) {
return [];
}
if ($limit !== null) { if ($limit !== null) {
$exploded = explode($delimiter, $value, $limit); $exploded = explode($delimiter, $value, $limit);
} else { } else {
@ -40,6 +44,10 @@ class StringHelper
*/ */
public static function cname($name, $separator = '_') public static function cname($name, $separator = '_')
{ {
if ($name === null) {
return '';
}
return str_replace(' ', '', ucwords(str_replace($separator, ' ', strtolower($name)))); return str_replace(' ', '', ucwords(str_replace($separator, ' ', strtolower($name))));
} }
@ -54,6 +62,10 @@ class StringHelper
*/ */
public static function ellipsis($string, $maxLength, $ellipsis = '...') public static function ellipsis($string, $maxLength, $ellipsis = '...')
{ {
if ($string === null) {
return '';
}
if (strlen($string) > $maxLength) { if (strlen($string) > $maxLength) {
return substr($string, 0, $maxLength - strlen($ellipsis)) . $ellipsis; return substr($string, 0, $maxLength - strlen($ellipsis)) . $ellipsis;
} }
@ -72,6 +84,10 @@ class StringHelper
*/ */
public static function ellipsisCenter($string, $maxLength, $ellipsis = '...') public static function ellipsisCenter($string, $maxLength, $ellipsis = '...')
{ {
if ($string === null) {
return '';
}
$start = ceil($maxLength / 2.0); $start = ceil($maxLength / 2.0);
$end = floor($maxLength / 2.0); $end = floor($maxLength / 2.0);
if (strlen($string) > $maxLength) { if (strlen($string) > $maxLength) {
@ -117,6 +133,10 @@ class StringHelper
*/ */
public static function endsWith($string, $suffix) public static function endsWith($string, $suffix)
{ {
if ($string === null) {
return false;
}
$stringSuffix = substr($string, -strlen($suffix)); $stringSuffix = substr($string, -strlen($suffix));
return $stringSuffix !== false ? $stringSuffix === $suffix : false; return $stringSuffix !== false ? $stringSuffix === $suffix : false;
} }

View File

@ -5,6 +5,7 @@ namespace Icinga\Web;
use ArrayIterator; use ArrayIterator;
use IteratorAggregate; use IteratorAggregate;
use Traversable;
/** /**
* Maintain a set of cookies * Maintain a set of cookies
@ -23,7 +24,7 @@ class CookieSet implements IteratorAggregate
* *
* @return ArrayIterator An iterator for traversing the cookies in this set * @return ArrayIterator An iterator for traversing the cookies in this set
*/ */
public function getIterator() public function getIterator(): Traversable
{ {
return new ArrayIterator($this->cookies); return new ArrayIterator($this->cookies);
} }

View File

@ -47,59 +47,37 @@ class DomNodeIterator implements RecursiveIterator
$this->children = new IteratorIterator($node->childNodes); $this->children = new IteratorIterator($node->childNodes);
} }
/** public function current(): ?DOMNode
* {@inheritdoc}
*/
public function current()
{ {
return $this->children->current(); return $this->children->current();
} }
/** public function key(): int
* {@inheritdoc}
*/
public function key()
{ {
return $this->children->key(); return $this->children->key();
} }
/** public function next(): void
* {@inheritdoc}
*/
public function next()
{ {
$this->children->next(); $this->children->next();
} }
/** public function rewind(): void
* {@inheritdoc}
*/
public function rewind()
{ {
$this->children->rewind(); $this->children->rewind();
} }
/** public function valid(): bool
* {@inheritdoc}
*/
public function valid()
{ {
return $this->children->valid(); return $this->children->valid();
} }
/** public function hasChildren(): bool
* {@inheritdoc}
*/
public function hasChildren()
{ {
return $this->current()->hasChildNodes(); return $this->current()->hasChildNodes();
} }
/** public function getChildren(): DomNodeIterator
* {@inheritdoc}
* @return DomNodeIterator
*/
public function getChildren()
{ {
return new static($this->current()); return new static($this->current());
} }

View File

@ -67,50 +67,32 @@ class Navigation implements ArrayAccess, Countable, IteratorAggregate
*/ */
protected $layout; protected $layout;
/** public function offsetExists($offset): bool
* {@inheritdoc}
*/
public function offsetExists($offset)
{ {
return isset($this->items[$offset]); return isset($this->items[$offset]);
} }
/** public function offsetGet($offset): ?NavigationItem
* {@inheritdoc}
*/
public function offsetGet($offset)
{ {
return isset($this->items[$offset]) ? $this->items[$offset] : null; return $this->items[$offset] ?? null;
} }
/** public function offsetSet($offset, $value): void
* {@inheritdoc}
*/
public function offsetSet($offset, $value)
{ {
$this->items[$offset] = $value; $this->items[$offset] = $value;
} }
/** public function offsetUnset($offset): void
* {@inheritdoc}
*/
public function offsetUnset($offset)
{ {
unset($this->items[$offset]); unset($this->items[$offset]);
} }
/** public function count(): int
* {@inheritdoc}
*/
public function count()
{ {
return count($this->items); return count($this->items);
} }
/** public function getIterator(): Traversable
* {@inheritdoc}
*/
public function getIterator()
{ {
$this->order(); $this->order();
return new ArrayIterator($this->items); return new ArrayIterator($this->items);

View File

@ -13,6 +13,7 @@ use Icinga\Exception\IcingaException;
use Icinga\Exception\ProgrammingError; use Icinga\Exception\ProgrammingError;
use Icinga\Web\Navigation\Renderer\NavigationItemRenderer; use Icinga\Web\Navigation\Renderer\NavigationItemRenderer;
use Icinga\Web\Url; use Icinga\Web\Url;
use Traversable;
/** /**
* A navigation item * A navigation item
@ -171,9 +172,9 @@ class NavigationItem implements IteratorAggregate
} }
/** /**
* {@inheritdoc} * @return Navigation
*/ */
public function getIterator() public function getIterator(): Traversable
{ {
return $this->getChildren(); return $this->getChildren();
} }

View File

@ -165,52 +165,32 @@ class NavigationRenderer implements RecursiveIterator, NavigationRendererInterfa
return $this; return $this;
} }
/** public function getChildren(): NavigationRenderer
* {@inheritdoc}
*/
public function getChildren()
{ {
return new static($this->current()->getChildren(), $this->skipOuterElement); return new static($this->current()->getChildren(), $this->skipOuterElement);
} }
/** public function hasChildren(): bool
* {@inheritdoc}
*/
public function hasChildren()
{ {
return $this->current()->hasChildren(); return $this->current()->hasChildren();
} }
/** public function current(): NavigationItem
* {@inheritdoc}
*
* @return NavigationItem
*/
public function current()
{ {
return $this->iterator->current(); return $this->iterator->current();
} }
/** public function key(): int
* {@inheritdoc}
*/
public function key()
{ {
return $this->iterator->key(); return $this->iterator->key();
} }
/** public function next(): void
* {@inheritdoc}
*/
public function next()
{ {
$this->iterator->next(); $this->iterator->next();
} }
/** public function rewind(): void
* {@inheritdoc}
*/
public function rewind()
{ {
$this->iterator->rewind(); $this->iterator->rewind();
if (! $this->skipOuterElement) { if (! $this->skipOuterElement) {
@ -218,10 +198,7 @@ class NavigationRenderer implements RecursiveIterator, NavigationRendererInterfa
} }
} }
/** public function valid(): bool
* {@inheritdoc}
*/
public function valid()
{ {
$valid = $this->iterator->valid(); $valid = $this->iterator->valid();
if (! $this->skipOuterElement && !$valid) { if (! $this->skipOuterElement && !$valid) {

View File

@ -121,34 +121,22 @@ class RecursiveNavigationRenderer extends RecursiveIteratorIterator implements N
return $this->getInnerIterator()->getHeading(); return $this->getInnerIterator()->getHeading();
} }
/** public function beginIteration(): void
* {@inheritdoc}
*/
public function beginIteration()
{ {
$this->content[] = $this->getInnerIterator()->beginMarkup(); $this->content[] = $this->getInnerIterator()->beginMarkup();
} }
/** public function endIteration(): void
* {@inheritdoc}
*/
public function endIteration()
{ {
$this->content[] = $this->getInnerIterator()->endMarkup(); $this->content[] = $this->getInnerIterator()->endMarkup();
} }
/** public function beginChildren(): void
* {@inheritdoc}
*/
public function beginChildren()
{ {
$this->content[] = $this->getInnerIterator()->beginChildrenMarkup($this->getDepth() + 1); $this->content[] = $this->getInnerIterator()->beginChildrenMarkup($this->getDepth() + 1);
} }
/** public function endChildren(): void
* {@inheritdoc}
*/
public function endChildren()
{ {
$this->content[] = $this->getInnerIterator()->endChildrenMarkup(); $this->content[] = $this->getInnerIterator()->endChildrenMarkup();
$this->content[] = $this->getInnerIterator()->endItemMarkup(); $this->content[] = $this->getInnerIterator()->endItemMarkup();

View File

@ -73,7 +73,7 @@ class QueryAdapter implements Zend_Paginator_Adapter_Interface
* *
* @return int * @return int
*/ */
public function count() public function count(): int
{ {
if ($this->count === null) { if ($this->count === null) {
$this->count = $this->query->count(); $this->count = $this->query->count();

View File

@ -389,12 +389,12 @@ class Response extends Zend_Controller_Response_Http
/** @var Cookie $cookie */ /** @var Cookie $cookie */
setcookie( setcookie(
$cookie->getName(), $cookie->getName(),
$cookie->getValue(), $cookie->getValue() ?? '',
$cookie->getExpire(), $cookie->getExpire() ?? 0,
$cookie->getPath(), $cookie->getPath(),
$cookie->getDomain(), $cookie->getDomain() ?? '',
$cookie->isSecure(), $cookie->isSecure(),
$cookie->isHttpOnly() $cookie->isHttpOnly() ?? true
); );
} }
} }

View File

@ -7,6 +7,7 @@ use Exception;
use ArrayIterator; use ArrayIterator;
use Icinga\Exception\IcingaException; use Icinga\Exception\IcingaException;
use IteratorAggregate; use IteratorAggregate;
use Traversable;
/** /**
* Container for session values * Container for session values
@ -32,7 +33,7 @@ class SessionNamespace implements IteratorAggregate
* *
* @return ArrayIterator * @return ArrayIterator
*/ */
public function getIterator() public function getIterator(): Traversable
{ {
return new ArrayIterator($this->getAll()); return new ArrayIterator($this->getAll());
} }

View File

@ -104,7 +104,7 @@ class View extends Zend_View_Abstract
*/ */
public function escape($value) public function escape($value)
{ {
return htmlspecialchars($value, ENT_COMPAT | ENT_SUBSTITUTE | ENT_HTML5, self::CHARSET, true); return htmlspecialchars($value ?: '', ENT_COMPAT | ENT_SUBSTITUTE | ENT_HTML5, self::CHARSET, true);
} }
/** /**

View File

@ -225,7 +225,7 @@ class SortBox extends AbstractWidget
// TODO(el): ToggleButton :) // TODO(el): ToggleButton :)
$toggle = array('asc' => 'sort-name-down', 'desc' => 'sort-name-up'); $toggle = array('asc' => 'sort-name-down', 'desc' => 'sort-name-up');
unset($toggle[strtolower($direction) ?: 'asc']); unset($toggle[isset($direction) ? strtolower($direction) : 'asc']);
$newDirection = key($toggle); $newDirection = key($toggle);
$icon = current($toggle); $icon = current($toggle);

View File

@ -403,7 +403,7 @@ EOT;
* *
* @see Countable * @see Countable
*/ */
public function count() public function count(): int
{ {
return count($this->tabs); return count($this->tabs);
} }

View File

@ -64,11 +64,10 @@ class Zend_Controller_Action_HelperBroker_PriorityStack implements IteratorAggre
* Magic property overloading for unsetting if helper is exists by name * Magic property overloading for unsetting if helper is exists by name
* *
* @param string $helperName The helper name * @param string $helperName The helper name
* @return Zend_Controller_Action_Helper_Abstract
*/ */
public function __unset($helperName) public function __unset($helperName)
{ {
return $this->offsetUnset($helperName); $this->offsetUnset($helperName);
} }
/** /**
@ -86,9 +85,9 @@ class Zend_Controller_Action_HelperBroker_PriorityStack implements IteratorAggre
/** /**
* Return something iterable * Return something iterable
* *
* @return array * @return Traversable
*/ */
public function getIterator() public function getIterator(): Traversable
{ {
return new ArrayObject($this->_helpersByPriority); return new ArrayObject($this->_helpersByPriority);
} }
@ -97,9 +96,9 @@ class Zend_Controller_Action_HelperBroker_PriorityStack implements IteratorAggre
* offsetExists() * offsetExists()
* *
* @param int|string $priorityOrHelperName * @param int|string $priorityOrHelperName
* @return Zend_Controller_Action_HelperBroker_PriorityStack * @return bool
*/ */
public function offsetExists($priorityOrHelperName) public function offsetExists($priorityOrHelperName): bool
{ {
if (is_string($priorityOrHelperName)) { if (is_string($priorityOrHelperName)) {
return array_key_exists($priorityOrHelperName, $this->_helpersByNameRef); return array_key_exists($priorityOrHelperName, $this->_helpersByNameRef);
@ -112,9 +111,9 @@ class Zend_Controller_Action_HelperBroker_PriorityStack implements IteratorAggre
* offsetGet() * offsetGet()
* *
* @param int|string $priorityOrHelperName * @param int|string $priorityOrHelperName
* @return Zend_Controller_Action_HelperBroker_PriorityStack * @return Zend_Controller_Action_Helper_Abstract
*/ */
public function offsetGet($priorityOrHelperName) public function offsetGet($priorityOrHelperName): Zend_Controller_Action_Helper_Abstract
{ {
if (!$this->offsetExists($priorityOrHelperName)) { if (!$this->offsetExists($priorityOrHelperName)) {
throw new Zend_Controller_Action_Exception('A helper with priority ' . $priorityOrHelperName . ' does not exist.'); throw new Zend_Controller_Action_Exception('A helper with priority ' . $priorityOrHelperName . ' does not exist.');
@ -132,9 +131,8 @@ class Zend_Controller_Action_HelperBroker_PriorityStack implements IteratorAggre
* *
* @param int $priority * @param int $priority
* @param Zend_Controller_Action_Helper_Abstract $helper * @param Zend_Controller_Action_Helper_Abstract $helper
* @return Zend_Controller_Action_HelperBroker_PriorityStack
*/ */
public function offsetSet($priority, $helper) public function offsetSet($priority, $helper): void
{ {
$priority = (int) $priority; $priority = (int) $priority;
@ -161,16 +159,14 @@ class Zend_Controller_Action_HelperBroker_PriorityStack implements IteratorAggre
} }
krsort($this->_helpersByPriority); // always make sure priority and LIFO are both enforced krsort($this->_helpersByPriority); // always make sure priority and LIFO are both enforced
return $this;
} }
/** /**
* offsetUnset() * offsetUnset()
* *
* @param int|string $priorityOrHelperName Priority integer or the helper name * @param int|string $priorityOrHelperName Priority integer or the helper name
* @return Zend_Controller_Action_HelperBroker_PriorityStack
*/ */
public function offsetUnset($priorityOrHelperName) public function offsetUnset($priorityOrHelperName): void
{ {
if (!$this->offsetExists($priorityOrHelperName)) { if (!$this->offsetExists($priorityOrHelperName)) {
throw new Zend_Controller_Action_Exception('A helper with priority or name ' . $priorityOrHelperName . ' does not exist.'); throw new Zend_Controller_Action_Exception('A helper with priority or name ' . $priorityOrHelperName . ' does not exist.');
@ -187,7 +183,6 @@ class Zend_Controller_Action_HelperBroker_PriorityStack implements IteratorAggre
unset($this->_helpersByNameRef[$helperName]); unset($this->_helpersByNameRef[$helperName]);
unset($this->_helpersByPriority[$priority]); unset($this->_helpersByPriority[$priority]);
return $this;
} }
/** /**
@ -195,7 +190,7 @@ class Zend_Controller_Action_HelperBroker_PriorityStack implements IteratorAggre
* *
* @return int * @return int
*/ */
public function count() public function count(): int
{ {
return count($this->_helpersByPriority); return count($this->_helpersByPriority);
} }

View File

@ -271,11 +271,12 @@ class Zend_Controller_Router_Route extends Zend_Controller_Router_Route_Abstract
// Translate value if required // Translate value if required
$part = $this->_parts[$pos]; $part = $this->_parts[$pos];
if ($this->_isTranslated if ($this->_isTranslated
&& $part !== null
&& (substr($part, 0, 1) === '@' && substr($part, 1, 1) !== '@' && (substr($part, 0, 1) === '@' && substr($part, 1, 1) !== '@'
&& $name === null) && $name === null)
|| $name !== null && in_array($name, $this->_translatable) || $name !== null && in_array($name, $this->_translatable)
) { ) {
if (substr($part, 0, 1) === '@') { if ($part && substr($part, 0, 1) === '@') {
$part = substr($part, 1); $part = substr($part, 1);
} }
@ -284,7 +285,7 @@ class Zend_Controller_Router_Route extends Zend_Controller_Router_Route_Abstract
} }
} }
if (substr($part, 0, 2) === '@@') { if ($part && substr($part, 0, 2) === '@@') {
$part = substr($part, 1); $part = substr($part, 1);
} }

View File

@ -286,7 +286,9 @@ abstract class Zend_Db_Adapter_Pdo_Abstract extends Zend_Db_Adapter_Abstract
*/ */
protected function _quote($value) protected function _quote($value)
{ {
if (is_int($value) || is_float($value)) { if ($value === null) {
$value = '';
} elseif (is_int($value) || is_float($value)) {
return $value; return $value;
} }
$this->_connect(); $this->_connect();

View File

@ -135,7 +135,7 @@ abstract class Zend_Db_Statement implements Zend_Db_Statement_Interface
$sql = $this->_stripQuoted($sql); $sql = $this->_stripQuoted($sql);
// split into text and params // split into text and params
$this->_sqlSplit = preg_split('/(\?|\:[a-zA-Z0-9_]+)/', $this->_sqlSplit = empty($sql) ? [] : preg_split('/(\?|\:[a-zA-Z0-9_]+)/',
$sql, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY); $sql, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
// map params // map params
@ -186,14 +186,18 @@ abstract class Zend_Db_Statement implements Zend_Db_Statement_Interface
// remove 'foo\'bar' // remove 'foo\'bar'
if (!empty($q)) { if (!empty($q)) {
$escapeChar = preg_quote($escapeChar); $escapeChar = preg_quote($escapeChar);
// this segfaults only after 65,000 characters instead of 9,000 if ($sql !== null) {
$sql = preg_replace("/$q([^$q{$escapeChar}]*|($qe)*)*$q/s", '', $sql); // this segfaults only after 65,000 characters instead of 9,000
$sql = preg_replace("/$q([^$q{$escapeChar}]*|($qe)*)*$q/s", '', $sql);
}
} }
// get a version of the SQL statement with all quoted // get a version of the SQL statement with all quoted
// values and delimited identifiers stripped out // values and delimited identifiers stripped out
// remove "foo\"bar" // remove "foo\"bar"
$sql = preg_replace("/\"(\\\\\"|[^\"])*\"/Us", '', $sql); if ($sql !== null) {
$sql = preg_replace("/\"(\\\\\"|[^\"])*\"/Us", '', $sql);
}
// get the character for delimited id quotes, // get the character for delimited id quotes,
// this is usually " but in MySQL is ` // this is usually " but in MySQL is `
@ -205,7 +209,10 @@ abstract class Zend_Db_Statement implements Zend_Db_Statement_Interface
$de = substr($de, 1, 2); $de = substr($de, 1, 2);
$de = preg_quote($de); $de = preg_quote($de);
// Note: $de and $d where never used..., now they are: // Note: $de and $d where never used..., now they are:
$sql = preg_replace("/$d($de|\\\\{2}|[^$d])*$d/Us", '', $sql); if ($sql !== null) {
$sql = preg_replace("/$d($de|\\\\{2}|[^$d])*$d/Us", '', $sql);
}
return $sql; return $sql;
} }

View File

@ -240,6 +240,12 @@ class Zend_Db_Statement_Pdo extends Zend_Db_Statement implements IteratorAggrega
if ($style === null) { if ($style === null) {
$style = $this->_fetchMode; $style = $this->_fetchMode;
} }
if ($cursor === null) {
$cursor = PDO::FETCH_ORI_NEXT;
}
if ($offset === null) {
$offset = 0;
}
try { try {
return $this->_stmt->fetch($style, $cursor, $offset); return $this->_stmt->fetch($style, $cursor, $offset);
} catch (PDOException $e) { } catch (PDOException $e) {
@ -252,7 +258,7 @@ class Zend_Db_Statement_Pdo extends Zend_Db_Statement implements IteratorAggrega
* *
* @return IteratorIterator * @return IteratorIterator
*/ */
public function getIterator() public function getIterator(): Traversable
{ {
return new IteratorIterator($this->_stmt); return new IteratorIterator($this->_stmt);
} }

View File

@ -3246,6 +3246,7 @@ class Zend_Form implements Iterator, Countable, Zend_Validate_Interface
* @throws Zend_Form_Exception * @throws Zend_Form_Exception
* @return Zend_Form_Element|Zend_Form_DisplayGroup|Zend_Form * @return Zend_Form_Element|Zend_Form_DisplayGroup|Zend_Form
*/ */
#[\ReturnTypeWillChange]
public function current() public function current()
{ {
$this->_sort(); $this->_sort();
@ -3268,7 +3269,7 @@ class Zend_Form implements Iterator, Countable, Zend_Validate_Interface
* *
* @return string * @return string
*/ */
public function key() public function key(): string
{ {
$this->_sort(); $this->_sort();
return key($this->_order); return key($this->_order);
@ -3279,7 +3280,7 @@ class Zend_Form implements Iterator, Countable, Zend_Validate_Interface
* *
* @return void * @return void
*/ */
public function next() public function next(): void
{ {
$this->_sort(); $this->_sort();
next($this->_order); next($this->_order);
@ -3290,7 +3291,7 @@ class Zend_Form implements Iterator, Countable, Zend_Validate_Interface
* *
* @return void * @return void
*/ */
public function rewind() public function rewind(): void
{ {
$this->_sort(); $this->_sort();
reset($this->_order); reset($this->_order);
@ -3301,7 +3302,7 @@ class Zend_Form implements Iterator, Countable, Zend_Validate_Interface
* *
* @return bool * @return bool
*/ */
public function valid() public function valid(): bool
{ {
$this->_sort(); $this->_sort();
return (current($this->_order) !== false); return (current($this->_order) !== false);
@ -3312,7 +3313,7 @@ class Zend_Form implements Iterator, Countable, Zend_Validate_Interface
* *
* @return int * @return int
*/ */
public function count() public function count(): int
{ {
return count($this->_order); return count($this->_order);
} }

View File

@ -158,7 +158,7 @@ class Zend_Form_Decorator_Description extends Zend_Form_Decorator_Abstract
} }
$description = $element->getDescription(); $description = $element->getDescription();
$description = trim($description); $description = trim($description ?: '');
if (!empty($description) && (null !== ($translator = $element->getTranslator()))) { if (!empty($description) && (null !== ($translator = $element->getTranslator()))) {
$description = $translator->translate($description); $description = $translator->translate($description);

View File

@ -91,7 +91,7 @@ class Zend_Form_Decorator_HtmlTag extends Zend_Form_Decorator_Abstract
$val = implode(' ', $val); $val = implode(' ', $val);
} }
} }
$val = htmlspecialchars($val, ENT_COMPAT, $enc); $val = htmlspecialchars($val ?? '', ENT_COMPAT, $enc);
$xhtml .= " $key=\"$val\""; $xhtml .= " $key=\"$val\"";
} }
return $xhtml; return $xhtml;

View File

@ -298,7 +298,7 @@ class Zend_Form_Decorator_Label extends Zend_Form_Decorator_Abstract
} }
$label = $element->getLabel(); $label = $element->getLabel();
$label = trim($label); $label = trim($label ?? '');
if (empty($label)) { if (empty($label)) {
return ''; return '';

View File

@ -1036,7 +1036,7 @@ class Zend_Form_DisplayGroup implements Iterator,Countable
* *
* @return Zend_Form_Element * @return Zend_Form_Element
*/ */
public function current() public function current(): Zend_Form_Element
{ {
$this->_sort(); $this->_sort();
current($this->_elementOrder); current($this->_elementOrder);
@ -1049,7 +1049,7 @@ class Zend_Form_DisplayGroup implements Iterator,Countable
* *
* @return string * @return string
*/ */
public function key() public function key(): string
{ {
$this->_sort(); $this->_sort();
return key($this->_elementOrder); return key($this->_elementOrder);
@ -1060,7 +1060,7 @@ class Zend_Form_DisplayGroup implements Iterator,Countable
* *
* @return void * @return void
*/ */
public function next() public function next(): void
{ {
$this->_sort(); $this->_sort();
next($this->_elementOrder); next($this->_elementOrder);
@ -1071,7 +1071,7 @@ class Zend_Form_DisplayGroup implements Iterator,Countable
* *
* @return void * @return void
*/ */
public function rewind() public function rewind(): void
{ {
$this->_sort(); $this->_sort();
reset($this->_elementOrder); reset($this->_elementOrder);
@ -1082,7 +1082,7 @@ class Zend_Form_DisplayGroup implements Iterator,Countable
* *
* @return bool * @return bool
*/ */
public function valid() public function valid(): bool
{ {
$this->_sort(); $this->_sort();
return (current($this->_elementOrder) !== false); return (current($this->_elementOrder) !== false);
@ -1093,7 +1093,7 @@ class Zend_Form_DisplayGroup implements Iterator,Countable
* *
* @return int * @return int
*/ */
public function count() public function count(): int
{ {
return count($this->_elements); return count($this->_elements);
} }

View File

@ -510,7 +510,7 @@ class Zend_Paginator implements Countable, IteratorAggregate
* *
* @return integer * @return integer
*/ */
public function count() public function count(): int
{ {
if (!$this->_pageCount) { if (!$this->_pageCount) {
$this->_pageCount = $this->_calculatePageCount(); $this->_pageCount = $this->_calculatePageCount();
@ -812,7 +812,7 @@ class Zend_Paginator implements Countable, IteratorAggregate
* *
* @return Traversable * @return Traversable
*/ */
public function getIterator() public function getIterator(): Traversable
{ {
return $this->getCurrentItems(); return $this->getCurrentItems();
} }

View File

@ -70,6 +70,16 @@ class Zend_Paginator_SerializableLimitIterator extends LimitIterator implements
)); ));
} }
public function __serialize(): array
{
return array(
'it' => $this->getInnerIterator(),
'offset' => $this->_offset,
'count' => $this->_count,
'pos' => $this->getPosition(),
);
}
/** /**
* @param string $data representation of the instance * @param string $data representation of the instance
*/ */
@ -80,12 +90,19 @@ class Zend_Paginator_SerializableLimitIterator extends LimitIterator implements
$this->seek($dataArr['pos']+$dataArr['offset']); $this->seek($dataArr['pos']+$dataArr['offset']);
} }
public function __unserialize(array $data): void
{
$this->__construct($data['it'], $data['offset'], $data['count']);
$this->seek($data['pos']+$data['offset']);
}
/** /**
* Returns value of the Iterator * Returns value of the Iterator
* *
* @param int $offset * @param int $offset
* @return mixed * @return mixed
*/ */
#[\ReturnTypeWillChange]
public function offsetGet($offset) public function offsetGet($offset)
{ {
$currentOffset = $this->key(); $currentOffset = $this->key();
@ -102,7 +119,7 @@ class Zend_Paginator_SerializableLimitIterator extends LimitIterator implements
* @param int $offset * @param int $offset
* @param mixed $value * @param mixed $value
*/ */
public function offsetSet($offset, $value) public function offsetSet($offset, $value): void
{ {
} }
@ -111,7 +128,7 @@ class Zend_Paginator_SerializableLimitIterator extends LimitIterator implements
* *
* @param int $offset * @param int $offset
*/ */
public function offsetExists($offset) public function offsetExists($offset): bool
{ {
if ($offset > 0 && $offset < $this->_count) { if ($offset > 0 && $offset < $this->_count) {
try { try {
@ -136,7 +153,7 @@ class Zend_Paginator_SerializableLimitIterator extends LimitIterator implements
* *
* @param int $offset * @param int $offset
*/ */
public function offsetUnset($offset) public function offsetUnset($offset): void
{ {
} }
} }

View File

@ -230,7 +230,7 @@ class Zend_View_Helper_HeadLink extends Zend_View_Helper_Placeholder_Container_S
* @param array $value * @param array $value
* @return void * @return void
*/ */
public function offsetSet($index, $value) public function offsetSet($index, $value): void
{ {
if (!$this->_isValid($value)) { if (!$this->_isValid($value)) {
$e = new Zend_View_Exception('offsetSet() expects a data token; please use one of the custom offsetSet*() methods'); $e = new Zend_View_Exception('offsetSet() expects a data token; please use one of the custom offsetSet*() methods');
@ -238,7 +238,7 @@ class Zend_View_Helper_HeadLink extends Zend_View_Helper_Placeholder_Container_S
throw $e; throw $e;
} }
return $this->getContainer()->offsetSet($index, $value); $this->getContainer()->offsetSet($index, $value);
} }
/** /**

View File

@ -168,7 +168,8 @@ class Zend_View_Helper_HeadMeta extends Zend_View_Helper_Placeholder_Container_S
$item = $this->createData($type, $args[0], $args[1], $args[2]); $item = $this->createData($type, $args[0], $args[1], $args[2]);
if ('offsetSet' == $action) { if ('offsetSet' == $action) {
return $this->offsetSet($index, $item); $this->offsetSet($index, $item);
return $this;
} }
$this->$action($item); $this->$action($item);
@ -254,7 +255,7 @@ class Zend_View_Helper_HeadMeta extends Zend_View_Helper_Placeholder_Container_S
* @return void * @return void
* @throws Zend_View_Exception * @throws Zend_View_Exception
*/ */
public function offsetSet($index, $value) public function offsetSet($index, $value): void
{ {
if (!$this->_isValid($value)) { if (!$this->_isValid($value)) {
$e = new Zend_View_Exception('Invalid value passed to offsetSet; please use offsetSetName() or offsetSetHttpEquiv()'); $e = new Zend_View_Exception('Invalid value passed to offsetSet; please use offsetSetName() or offsetSetHttpEquiv()');
@ -262,7 +263,7 @@ class Zend_View_Helper_HeadMeta extends Zend_View_Helper_Placeholder_Container_S
throw $e; throw $e;
} }
return $this->getContainer()->offsetSet($index, $value); $this->getContainer()->offsetSet($index, $value);
} }
/** /**
@ -272,7 +273,7 @@ class Zend_View_Helper_HeadMeta extends Zend_View_Helper_Placeholder_Container_S
* @return void * @return void
* @throws Zend_View_Exception * @throws Zend_View_Exception
*/ */
public function offsetUnset($index) public function offsetUnset($index): void
{ {
if (!in_array($index, $this->getContainer()->getKeys())) { if (!in_array($index, $this->getContainer()->getKeys())) {
$e = new Zend_View_Exception('Invalid index passed to offsetUnset()'); $e = new Zend_View_Exception('Invalid index passed to offsetUnset()');
@ -280,7 +281,7 @@ class Zend_View_Helper_HeadMeta extends Zend_View_Helper_Placeholder_Container_S
throw $e; throw $e;
} }
return $this->getContainer()->offsetUnset($index); $this->getContainer()->offsetUnset($index);
} }
/** /**

View File

@ -363,7 +363,7 @@ class Zend_View_Helper_HeadScript extends Zend_View_Helper_Placeholder_Container
* @param mixed $value * @param mixed $value
* @return void * @return void
*/ */
public function offsetSet($index, $value) public function offsetSet($index, $value): void
{ {
if (!$this->_isValid($value)) { if (!$this->_isValid($value)) {
$e = new Zend_View_Exception('Invalid argument passed to offsetSet(); please use one of the helper methods, offsetSetScript() or offsetSetFile()'); $e = new Zend_View_Exception('Invalid argument passed to offsetSet(); please use one of the helper methods, offsetSetScript() or offsetSetFile()');
@ -371,7 +371,7 @@ class Zend_View_Helper_HeadScript extends Zend_View_Helper_Placeholder_Container
throw $e; throw $e;
} }
return $this->getContainer()->offsetSet($index, $value); $this->getContainer()->offsetSet($index, $value);
} }
/** /**

View File

@ -217,7 +217,7 @@ class Zend_View_Helper_HeadStyle extends Zend_View_Helper_Placeholder_Container_
* @param mixed $value * @param mixed $value
* @return void * @return void
*/ */
public function offsetSet($index, $value) public function offsetSet($index, $value): void
{ {
if (!$this->_isValid($value)) { if (!$this->_isValid($value)) {
$e = new Zend_View_Exception('Invalid value passed to offsetSet; please use offsetSetStyle()'); $e = new Zend_View_Exception('Invalid value passed to offsetSet; please use offsetSetStyle()');
@ -225,7 +225,7 @@ class Zend_View_Helper_HeadStyle extends Zend_View_Helper_Placeholder_Container_
throw $e; throw $e;
} }
return $this->getContainer()->offsetSet($index, $value); $this->getContainer()->offsetSet($index, $value);
} }
/** /**

View File

@ -258,7 +258,7 @@ abstract class Zend_View_Helper_Placeholder_Container_Standalone extends Zend_Vi
* *
* @return int * @return int
*/ */
public function count() public function count(): int
{ {
$container = $this->getContainer(); $container = $this->getContainer();
return count($container); return count($container);
@ -270,7 +270,7 @@ abstract class Zend_View_Helper_Placeholder_Container_Standalone extends Zend_Vi
* @param string|int $offset * @param string|int $offset
* @return bool * @return bool
*/ */
public function offsetExists($offset) public function offsetExists($offset): bool
{ {
return $this->getContainer()->offsetExists($offset); return $this->getContainer()->offsetExists($offset);
} }
@ -281,6 +281,7 @@ abstract class Zend_View_Helper_Placeholder_Container_Standalone extends Zend_Vi
* @param string|int $offset * @param string|int $offset
* @return mixed * @return mixed
*/ */
#[\ReturnTypeWillChange]
public function offsetGet($offset) public function offsetGet($offset)
{ {
return $this->getContainer()->offsetGet($offset); return $this->getContainer()->offsetGet($offset);
@ -293,9 +294,9 @@ abstract class Zend_View_Helper_Placeholder_Container_Standalone extends Zend_Vi
* @param mixed $value * @param mixed $value
* @return void * @return void
*/ */
public function offsetSet($offset, $value) public function offsetSet($offset, $value): void
{ {
return $this->getContainer()->offsetSet($offset, $value); $this->getContainer()->offsetSet($offset, $value);
} }
/** /**
@ -304,9 +305,9 @@ abstract class Zend_View_Helper_Placeholder_Container_Standalone extends Zend_Vi
* @param string|int $offset * @param string|int $offset
* @return void * @return void
*/ */
public function offsetUnset($offset) public function offsetUnset($offset): void
{ {
return $this->getContainer()->offsetUnset($offset); $this->getContainer()->offsetUnset($offset);
} }
/** /**
@ -314,7 +315,7 @@ abstract class Zend_View_Helper_Placeholder_Container_Standalone extends Zend_Vi
* *
* @return Iterator * @return Iterator
*/ */
public function getIterator() public function getIterator(): Traversable
{ {
return $this->getContainer()->getIterator(); return $this->getContainer()->getIterator();
} }

View File

@ -41,7 +41,7 @@ class DocSectionFilterIterator extends RecursiveFilterIterator implements Counta
* @return bool Whether the current element of the iterator is acceptable * @return bool Whether the current element of the iterator is acceptable
* through this filter * through this filter
*/ */
public function accept() public function accept(): bool
{ {
$section = $this->current(); $section = $this->current();
/** @var \Icinga\Module\Doc\DocSection $section */ /** @var \Icinga\Module\Doc\DocSection $section */
@ -51,18 +51,12 @@ class DocSectionFilterIterator extends RecursiveFilterIterator implements Counta
return false; return false;
} }
/** public function getChildren(): self
* {@inheritdoc}
*/
public function getChildren()
{ {
return new static($this->getInnerIterator()->getChildren(), $this->chapter); return new static($this->getInnerIterator()->getChildren(), $this->chapter);
} }
/** public function count(): int
* {@inheritdoc}
*/
public function count()
{ {
return iterator_count($this); return iterator_count($this);
} }

View File

@ -9,10 +9,6 @@ use Icinga\Module\Doc\Search\DocSearchMatch;
/** /**
* Renderer for doc searches * Renderer for doc searches
*
* @method DocSearchIterator getInnerIterator() {
* @{inheritdoc}
* }
*/ */
class DocSearchRenderer extends DocRenderer class DocSearchRenderer extends DocRenderer
{ {
@ -33,45 +29,30 @@ class DocSearchRenderer extends DocRenderer
parent::__construct($iterator, RecursiveIteratorIterator::SELF_FIRST); parent::__construct($iterator, RecursiveIteratorIterator::SELF_FIRST);
} }
/** public function beginIteration(): void
* {@inheritdoc}
*/
public function beginIteration()
{ {
$this->content[] = '<nav role="navigation"><ul class="toc">'; $this->content[] = '<nav role="navigation"><ul class="toc">';
} }
/** public function endIteration(): void
* {@inheritdoc}
*/
public function endIteration()
{ {
$this->content[] = '</ul></nav>'; $this->content[] = '</ul></nav>';
} }
/** public function beginChildren(): void
* {@inheritdoc}
*/
public function beginChildren()
{ {
if ($this->getInnerIterator()->getMatches()) { if ($this->getInnerIterator()->getMatches()) {
$this->content[] = '<ul class="toc">'; $this->content[] = '<ul class="toc">';
} }
} }
/** public function endChildren(): void
* {@inheritdoc}
*/
public function endChildren()
{ {
if ($this->getInnerIterator()->getMatches()) { if ($this->getInnerIterator()->getMatches()) {
$this->content[] = '</ul>'; $this->content[] = '</ul>';
} }
} }
/**
* {@inheritdoc}
*/
public function render() public function render()
{ {
foreach ($this as $section) { foreach ($this as $section) {

View File

@ -3,16 +3,11 @@
namespace Icinga\Module\Doc\Renderer; namespace Icinga\Module\Doc\Renderer;
use Icinga\Web\View;
use Icinga\Data\Tree\TreeNodeIterator; use Icinga\Data\Tree\TreeNodeIterator;
use RecursiveIteratorIterator; use RecursiveIteratorIterator;
/** /**
* TOC renderer * TOC renderer
*
* @method TreeNodeIterator getInnerIterator() {
* {@inheritdoc}
* }
*/ */
class DocTocRenderer extends DocRenderer class DocTocRenderer extends DocRenderer
{ {
@ -47,41 +42,26 @@ class DocTocRenderer extends DocRenderer
parent::__construct($iterator, RecursiveIteratorIterator::SELF_FIRST); parent::__construct($iterator, RecursiveIteratorIterator::SELF_FIRST);
} }
/** public function beginIteration(): void
* {@inheritdoc}
*/
public function beginIteration()
{ {
$this->content[] = sprintf('<nav role="navigation"><%s class="%s">', static::HTML_LIST_TAG, static::CSS_CLASS); $this->content[] = sprintf('<nav role="navigation"><%s class="%s">', static::HTML_LIST_TAG, static::CSS_CLASS);
} }
/** public function endIteration(): void
* {@inheritdoc}
*/
public function endIteration()
{ {
$this->content[] = sprintf('</%s></nav>', static::HTML_LIST_TAG); $this->content[] = sprintf('</%s></nav>', static::HTML_LIST_TAG);
} }
/** public function beginChildren(): void
* {@inheritdoc}
*/
public function beginChildren()
{ {
$this->content[] = sprintf('<%s class="%s">', static::HTML_LIST_TAG, static::CSS_CLASS); $this->content[] = sprintf('<%s class="%s">', static::HTML_LIST_TAG, static::CSS_CLASS);
} }
/** public function endChildren(): void
* {@inheritdoc}
*/
public function endChildren()
{ {
$this->content[] = sprintf('</%s>', static::HTML_LIST_TAG); $this->content[] = sprintf('</%s>', static::HTML_LIST_TAG);
} }
/**
* {@inheritdoc}
*/
public function render() public function render()
{ {
if ($this->getInnerIterator()->isEmpty()) { if ($this->getInnerIterator()->isEmpty()) {

View File

@ -9,10 +9,6 @@ use Icinga\Data\Tree\TreeNodeIterator;
/** /**
* Iterator over doc sections that match a given search criteria * Iterator over doc sections that match a given search criteria
*
* @method TreeNodeIterator getInnerIterator() {
* {@inheritdoc}
* }
*/ */
class DocSearchIterator extends RecursiveFilterIterator class DocSearchIterator extends RecursiveFilterIterator
{ {
@ -48,7 +44,7 @@ class DocSearchIterator extends RecursiveFilterIterator
* @return bool Whether the current element of the iterator is acceptable * @return bool Whether the current element of the iterator is acceptable
* through this filter * through this filter
*/ */
public function accept() public function accept(): bool
{ {
$section = $this->current(); $section = $this->current();
/** @var $section \Icinga\Module\Doc\DocSection */ /** @var $section \Icinga\Module\Doc\DocSection */
@ -84,10 +80,7 @@ class DocSearchIterator extends RecursiveFilterIterator
return $this->search; return $this->search;
} }
/** public function getChildren(): self
* {@inheritdoc}
*/
public function getChildren()
{ {
return new static($this->getInnerIterator()->getChildren(), $this->search); return new static($this->getInnerIterator()->getChildren(), $this->search);
} }

View File

@ -1,652 +0,0 @@
<?php
/* Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Controllers;
use stdClass;
use DateInterval;
use DatePeriod;
use DateTime;
use Zend_Controller_Action_Exception;
use Icinga\Chart\GridChart;
use Icinga\Chart\Unit\LinearUnit;
use Icinga\Chart\Unit\StaticAxis;
use Icinga\Data\Filter\FilterExpression;
use Icinga\Module\Monitoring\Controller;
use Icinga\Module\Monitoring\Web\Widget\SelectBox;
use Icinga\Web\Url;
use Icinga\Web\Widget\Tabextension\DashboardAction;
use Icinga\Web\Widget\Tabextension\MenuAction;
class AlertsummaryController extends Controller
{
/**
* @var array
*/
private $notificationData;
/**
* @var array
*/
private $problemData;
/**
* Init data set
*/
public function init()
{
$this->notificationData = $this->createNotificationData();
$this->problemData = $this->createProblemData();
}
/**
* Create full report
*/
public function indexAction()
{
$this->getTabs()->add(
'alertsummary',
array(
'title' => $this->translate(
'Show recent alerts and visualize notifications and problems'
. ' based on their amount and chronological distribution'
),
'label' => $this->translate('Alert Summary'),
'url' => Url::fromRequest()
)
)->extend(new DashboardAction())->extend(new MenuAction())->activate('alertsummary');
$this->view->title = $this->translate('Alert Summary');
$this->view->intervalBox = $this->createIntervalBox();
list($recentAlerts, $recentAlertsUrl) = $this->createRecentAlerts();
$this->view->recentAlerts = $recentAlerts;
$this->view->recentAlertsUrl = $recentAlertsUrl;
$this->view->interval = $this->getInterval();
$this->view->defectChart = $this->createDefectImage();
$this->view->healingChart = $this->createHealingChart();
$this->view->perf = $this->createNotificationPerfdata();
$this->view->trend = $this->createTrendInformation();
$this->setAutorefreshInterval(15);
$query = $this->backend->select()->from(
'notification',
array(
'host_name',
'host_display_name',
'service_description',
'service_display_name',
'notification_output',
'notification_contact_name',
'notification_start_time',
'notification_state'
)
);
$this->applyRestriction('monitoring/filter/objects', $query);
$this->view->notifications = $query;
$this->view->notificationsUrl = 'monitoring/list/notifications';
$this->setupLimitControl();
if (($limit = $this->params->get('limit'))) {
$query->limit($limit);
} else {
$query->limit(25);
}
}
/**
* Create data for charts
*
* @return array
*/
private function createNotificationData()
{
$interval = $this->getInterval();
$query = $this->backend->select()->from(
'notification',
array(
'notification_start_time'
)
);
$this->applyRestriction('monitoring/filter/objects', $query);
$query->addFilter(
new FilterExpression(
'notification_start_time',
'>=',
$this->getBeginDate($interval)->format('Y-m-d H:i:s')
)
);
$query->order('notification_start_time', 'asc');
$records = $query->getQuery()->fetchAll();
$data = array();
$period = $this->createPeriod($interval);
foreach ($period as $entry) {
$id = $this->getPeriodFormat($interval, $entry->getTimestamp());
$data[$id] = array($id, 0);
}
foreach ($records as $item) {
$id = $this->getPeriodFormat($interval, $item->notification_start_time);
if (empty($data[$id])) {
$data[$id] = array($id, 0);
}
$data[$id][1]++;
}
return $data;
}
/**
* Trend information for notifications
*
* @return stdClass
*/
private function createTrendInformation()
{
$date = new DateTime();
$beginDate = $date->sub(new DateInterval('P3D'));
$query = $this->backend->select()->from(
'notification',
array(
'notification_start_time'
)
);
$this->applyRestriction('monitoring/filter/objects', $query);
$query->addFilter(
new FilterExpression(
'notification_start_time',
'>=',
$beginDate->format('Y-m-d H:i:s')
)
);
$query->order('notification_start_time', 'asc');
$records = $query->getQuery()->fetchAll();
$slots = array();
$period = new DatePeriod($beginDate, new DateInterval('P1D'), 2, DatePeriod::EXCLUDE_START_DATE);
foreach ($period as $entry) {
$slots[$entry->format('Y-m-d')] = 0;
}
foreach ($records as $item) {
$id = strftime('%Y-%m-%d', $item->notification_start_time);
if (isset($slots[$id])) {
$slots[$id]++;
}
}
$yesterday = array_shift($slots);
$today = array_shift($slots);
$out = new stdClass();
if ($yesterday === $today) {
$out->trend = $this->translate('unchanged');
} elseif ($yesterday > $today) {
$out->trend = $this->translate('down');
} else {
$out->trend = $this->translate('up');
}
if ($yesterday <= 0) {
$out->percent = 100;
} elseif ($yesterday === $today) {
$out->percent = 0;
} else {
$out->percent = sprintf(
'%.2f',
100 - ((100/($yesterday > $today ? $yesterday : $today)) * ($yesterday > $today ? $today : $yesterday))
);
}
return $out;
}
/**
* Perfdata for notifications
*
* @return stdClass
*/
private function createNotificationPerfdata()
{
$interval = $this->getInterval();
$query = $this->backend->select()->from(
'notification',
array(
'notification_start_time'
)
);
$this->applyRestriction('monitoring/filter/objects', $query);
$query->addFilter(
new FilterExpression(
'notification_start_time',
'>=',
$this->getBeginDate($interval)->format('Y-m-d H:i:s')
)
);
$query->order('notification_start_time', 'desc');
$records = $query->getQuery()->fetchAll();
$slots = array();
foreach ($records as $item) {
$id = strftime('%Y-%m-%d %H:%I:00', $item->notification_start_time);
if (empty($slots[$id])) {
$slots[$id] = 0;
}
$slots[$id]++;
}
$out = new stdClass();
if (! empty($slots)) {
$out->avg = sprintf('%.2f', array_sum($slots) / count($slots));
} else {
$out->avg = '0.0';
}
$out->last = array_shift($slots);
return $out;
}
/**
* Problems for notifications
*
* @return array
*/
private function createProblemData()
{
$interval = $this->getInterval();
$query = $this->backend->select()->from(
'eventhistory',
array(
'timestamp'
)
);
$this->applyRestriction('monitoring/filter/objects', $query);
$query->addFilter(
new FilterExpression(
'timestamp',
'>=',
$this->getBeginDate($interval)->getTimestamp()
)
);
$query->addFilter(
new FilterExpression(
'state',
'>',
0
)
);
$defects = array();
$records = $query->getQuery()->fetchAll();
$period = $this->createPeriod($interval);
foreach ($period as $entry) {
$id = $this->getPeriodFormat($interval, $entry->getTimestamp());
$defects[$id] = array($id, 0);
}
foreach ($records as $item) {
$id = $this->getPeriodFormat($interval, $item->timestamp);
if (empty($defects[$id])) {
$defects[$id] = array($id, 0);
}
$defects[$id][1]++;
}
return $defects;
}
/**
* Healing svg image
*
* @return GridChart
*/
public function createHealingChart()
{
$gridChart = new GridChart();
$gridChart->title = $this->translate('Healing Chart');
$gridChart->description = $this->translate('Notifications and average reaction time per hour.');
$gridChart->alignTopLeft();
$gridChart->setAxisLabel($this->createPeriodDescription(), $this->translate('Notifications'))
->setXAxis(new StaticAxis())
->setYAxis(new LinearUnit(10))
->setAxisMin(null, 0);
$interval = $this->getInterval();
$query = $this->backend->select()->from(
'notification',
array(
'notification_object_id',
'notification_start_time',
'notification_state',
'acknowledgement_entry_time'
)
);
$this->applyRestriction('monitoring/filter/objects', $query);
$query->addFilter(
new FilterExpression(
'notification_start_time',
'>=',
$this->getBeginDate($interval)->format('Y-m-d H:i:s')
)
);
$query->order('notification_start_time', 'asc');
$records = $query->getQuery()->fetchAll();
$interval = $this->getInterval();
$period = $this->createPeriod($interval);
$dAvg = array();
$dMax = array();
$notifications = array();
$rData = array();
foreach ($period as $entry) {
$id = $this->getPeriodFormat($interval, $entry->getTimestamp());
$dMax[$id] = array($id, 0);
$dAvg[$id] = array($id, 0, 0);
$notifications[$id] = array($id, 0);
}
foreach ($records as $item) {
$id = $this->getPeriodFormat($interval, $item->notification_start_time);
if ($item->notification_state == '0' && isset($rData[$item->notification_object_id])) {
$rData[$item->notification_object_id]['recover'] =
$item->notification_start_time - $rData[$item->notification_object_id]['entry'];
} elseif ($item->notification_state !== '0') {
$recover = 0;
if ($item->acknowledgement_entry_time) {
$recover = $item->acknowledgement_entry_time - $item->notification_start_time;
/*
* Acknowledgements may happen before the actual notification starts, since notifications
* can be configured to start a certain time after the problem. In that case we assume
* a reaction time of 0s.
*/
if ($recover < 0) {
$recover = 0;
}
}
$rData[$item->notification_object_id] = array(
'id' => $id,
'entry' => $item->notification_start_time,
'recover' => $recover
);
}
}
foreach ($rData as $item) {
$notifications[$item['id']][1]++;
if ($item['recover'] > $dMax[$item['id']][1]) {
$dMax[$item['id']][1] = (int) $item['recover'];
}
$dAvg[$item['id']][1] += (int) $item['recover'];
$dAvg[$item['id']][2]++;
}
foreach ($dAvg as &$item) {
if ($item[2] > 0) {
$item[1] = ($item[1]/$item[2])/60/60;
}
}
foreach ($dMax as &$item) {
$item[1] = $item[1]/60/60;
}
$gridChart->drawBars(
array(
'label' => $this->translate('Notifications'),
'color' => '#07C0D9',
'data' => $notifications,
'showPoints' => true,
'tooltip' => '<b>{title}:</b> {value} {label}'
)
);
$gridChart->drawLines(
array(
'label' => $this->translate('Avg (min)'),
'color' => '#ffaa44',
'data' => $dAvg,
'showPoints' => true,
'tooltip' => $this->translate('<b>{title}:</b> {value}m min. reaction time')
)
);
$gridChart->drawLines(
array(
'label' => $this->translate('Max (min)'),
'color' => '#ff5566',
'data' => $dMax,
'showPoints' => true,
'tooltip' => $this->translate('<b>{title}:</b> {value}m max. reaction time')
)
);
return $gridChart;
}
/**
* Notifications and defects
*
* @return GridChart
*/
public function createDefectImage()
{
$gridChart = new GridChart();
$gridChart->title = $this->translate('Defect Chart');
$gridChart->description = $this->translate('Notifications and defects per hour');
$gridChart->alignTopLeft();
$gridChart->setAxisLabel($this->createPeriodDescription(), $this->translate('Notifications'))
->setXAxis(new StaticAxis())
->setYAxis(new LinearUnit(10))
->setAxisMin(null, 0);
$gridChart->drawBars(
array(
'label' => $this->translate('Notifications'),
'color' => '#07C0D9',
'data' => $this->notificationData,
'showPoints' => true,
'tooltip' => '<b>{title}:</b> {value} {label}'
)
);
$gridChart->drawLines(
array(
'label' => $this->translate('Defects'),
'color' => '#ff5566',
'data' => $this->problemData,
'showPoints' => true,
'tooltip' => '<b>{title}:</b> {value} {label}'
)
);
return $gridChart;
}
/**
* Top recent alerts
*
* @return array
*/
private function createRecentAlerts()
{
$query = $this->backend->select()->from(
'notification',
array(
'host_name',
'host_display_name',
'service_description',
'service_display_name',
'notification_output',
'notification_contact_name',
'notification_start_time',
'notification_state'
)
);
$this->applyRestriction('monitoring/filter/objects', $query);
$query->order('notification_start_time', 'desc');
return array(
$query->limit(5),
'monitoring/list/notifications?sort=notification_start_time&dir=desc'
);
}
/**
* Interval selector box
*
* @return SelectBox
*/
private function createIntervalBox()
{
$box = new SelectBox(
'intervalBox',
array(
'1d' => $this->translate('One day'),
'1w' => $this->translate('One week'),
'1m' => $this->translate('One month'),
'1y' => $this->translate('One year')
),
$this->translate('Report interval'),
'interval'
);
$box->applyRequest($this->getRequest());
return $box;
}
/**
* Return reasonable date time format for an interval
*
* @param string $interval
* @param string $timestamp
*
* @return string
*/
private function getPeriodFormat($interval, $timestamp)
{
$format = '';
if ($interval === '1d') {
$format = '%H:00';
} elseif ($interval === '1w') {
$format = '%Y-%m-%d';
} elseif ($interval === '1m') {
$format = '%Y-%m-%d';
} elseif ($interval === '1y') {
$format = '%Y-%m';
}
return strftime($format, $timestamp);
}
/**
* Create a reasonable period based in interval strings
*
* @param $interval
* @return DatePeriod
*/
private function createPeriod($interval)
{
if ($interval === '1d') {
return new DatePeriod($this->getBeginDate($interval), new DateInterval('PT1H'), 24);
} elseif ($interval === '1w') {
return new DatePeriod($this->getBeginDate($interval), new DateInterval('P1D'), 7);
} elseif ($interval === '1m') {
return new DatePeriod($this->getBeginDate($interval), new DateInterval('P1D'), 31);
} elseif ($interval === '1y') {
return new DatePeriod($this->getBeginDate($interval), new DateInterval('P1M'), 12);
}
}
/**
* Return start timestamps based on interval strings
*
* @param $interval
* @return DateTime|null
*/
private function getBeginDate($interval)
{
$new = new DateTime();
if ($interval === '1d') {
return $new->sub(new DateInterval('P1D'));
} elseif ($interval === '1w') {
return $new->sub(new DateInterval('P1W'));
} elseif ($interval === '1m') {
return $new->sub(new DateInterval('P1M'));
} elseif ($interval === '1y') {
return $new->sub(new DateInterval('P1Y'));
}
return null;
}
/**
* Getter for interval
*
* @return string
*
* @throws Zend_Controller_Action_Exception
*/
private function getInterval()
{
$interval = $this->getParam('interval', '1d');
if (false === in_array($interval, array('1d', '1w', '1m', '1y'))) {
throw new Zend_Controller_Action_Exception($this->translate('Value for interval not valid'));
}
return $interval;
}
/**
* Create a human-readable description of the current interval size
*
* @return string The description of the current interval size
*/
private function createPeriodDescription()
{
$int = $this->getInterval();
switch ($int) {
case '1d':
return $this->translate('Hour');
break;
case '1w':
return $this->translate('Day');
break;
case '1m':
return $this->translate('Day');
break;
case '1y':
return $this->translate('Month');
break;
}
}
}

View File

@ -275,7 +275,7 @@ class TimelineController extends Controller
{ {
$startTime = new DateTime(); $startTime = new DateTime();
$startParam = $this->_request->getParam('start'); $startParam = $this->_request->getParam('start');
$startTimestamp = is_numeric($startParam) ? intval($startParam) : strtotime($startParam); $startTimestamp = is_numeric($startParam) ? intval($startParam) : strtotime($startParam ?? '');
if ($startTimestamp !== false) { if ($startTimestamp !== false) {
$startTime->setTimestamp($startTimestamp); $startTime->setTimestamp($startTimestamp);
} else { } else {
@ -284,7 +284,7 @@ class TimelineController extends Controller
$endTime = clone $startTime; $endTime = clone $startTime;
$endParam = $this->_request->getParam('end'); $endParam = $this->_request->getParam('end');
$endTimestamp = is_numeric($endParam) ? intval($endParam) : strtotime($endParam); $endTimestamp = is_numeric($endParam) ? intval($endParam) : strtotime($endParam ?? '');
if ($endTimestamp !== false) { if ($endTimestamp !== false) {
$endTime->setTimestamp($endTimestamp); $endTime->setTimestamp($endTimestamp);
} else { } else {

View File

@ -1,79 +0,0 @@
<?php if (! $this->compact): ?>
<div class="controls">
<?= $this->tabs; ?>
<div style="float: right;" class="dont-print">
<?= $intervalBox; ?>
</div>
<?= $this->limiter; ?>
</div>
<?php endif ?>
<div class="content alertsummary">
<!-- <h1><?= $this->translate('Alert summary'); ?></h1> -->
<div class="hbox">
<div class="hbox-item">
<h2><?= $this->translate('Notifications and Problems'); ?></h2>
<div style="width: 400px; height: 400px;">
<?= $defectChart->render(); ?>
</div>
</div>
<div class="hbox-item">
<h2><?= $this->translate('Time to Reaction (Ack, Recover)'); ?></h2>
<div style="width: 400px; height: 400px;">
<?= $healingChart->render(); ?>
</div>
</div>
</div>
<h2><?= $this->translate('Trend'); ?></h2>
<div class="alertsummary-flex-container">
<div class="alertsummary-flex">
<?= $this->translate('Average') ?>
<strong><?= $this->perf->avg; ?></strong>
<?= $this->translate('notifications per hour'); ?>,
<strong><?= $this->perf->last; ?></strong>
<?= $this->translate('in the last hour'); ?>.
<?= $this->translate('Trend for the last 24h'); ?>
(<?= $this->trend->percent; ?>%
<strong><?= $this->translate($this->trend->trend); ?></strong>)
<span>
<?php if ($this->trend->trend === 'up'): ?>
<?= $this->icon('up-open'); ?>
<?php elseif ($this->trend->trend === 'unchanged'): ?>
<?= $this->icon('right-open'); ?>
<?php else: ?>
<?= $this->icon('down-open'); ?>
<?php endif; ?>
</span>
</div>
</div>
<?php if ($this->recentAlerts): ?>
<h1><?= $this->translate('Top 5 Recent Alerts'); ?></h1>
<div class="alertsummary-flex-container">
<div class="alertsummary-flex">
<?= $this->partial('list/notifications.phtml', array(
'notifications' => $this->recentAlerts,
'compact' => true,
'notificationsUrl' => $recentAlertsUrl
)); ?>
</div>
</div>
<?php endif; ?>
<h1><?= $this->translate('History'); ?></h1>
<div class="alertsummary-flex-container">
<div class="alertsummary-flex">
<?= $this->partial('list/notifications.phtml', array(
'notifications' => $this->notifications,
'compact' => true,
'notificationsUrl' => $notificationsUrl
)); ?>
</div>
</div>
</div>

View File

@ -30,7 +30,7 @@ $history->limit($limit * $page);
?> ?>
<div class="content"> <div class="content">
<?php <?php
$dateFormat = $this->translate('%A, %B %e, %Y', 'date.verbose'); $dateFormatter = new IntlDateFormatter(setlocale(LC_TIME, 0), IntlDateFormatter::FULL, IntlDateFormatter::LONG);
$lastDate = null; $lastDate = null;
$flappingMsg = $this->translate('Flapping with a %.2f%% state change rate'); $flappingMsg = $this->translate('Flapping with a %.2f%% state change rate');
$rowAction = Url::fromPath('monitoring/event/show'); $rowAction = Url::fromPath('monitoring/event/show');
@ -161,7 +161,7 @@ $rowAction = Url::fromPath('monitoring/event/show');
break; break;
} ?> } ?>
<?php <?php
$currentDate = strftime($dateFormat, (int) $event->timestamp); $currentDate = $dateFormatter->format($event->timestamp);
if ($currentDate !== $lastDate): if ($currentDate !== $lastDate):
$lastDate = $currentDate; $lastDate = $currentDate;
?> ?>

View File

@ -22,10 +22,7 @@ class ColumnFilterIterator extends FilterIterator
parent::__construct(new ArrayIterator($columns)); parent::__construct(new ArrayIterator($columns));
} }
/** public function accept(): bool
* {@inheritdoc}
*/
public function accept()
{ {
$column = $this->current(); $column = $this->current();
return ! ($column instanceof Zend_Db_Expr || $column === '(NULL)'); return ! ($column instanceof Zend_Db_Expr || $column === '(NULL)');

View File

@ -10,7 +10,7 @@ class CustomvarProtectionIterator extends IteratorIterator
{ {
const IS_CV_RE = '~^_(host|service)_([a-zA-Z0-9_]+)$~'; const IS_CV_RE = '~^_(host|service)_([a-zA-Z0-9_]+)$~';
public function current() public function current(): object
{ {
$row = parent::current(); $row = parent::current();

View File

@ -17,6 +17,7 @@ use Icinga\Module\Monitoring\Backend\Ido\Query\IdoQuery;
use Icinga\Module\Monitoring\Backend\MonitoringBackend; use Icinga\Module\Monitoring\Backend\MonitoringBackend;
use Icinga\Web\Request; use Icinga\Web\Request;
use Icinga\Web\Url; use Icinga\Web\Url;
use Traversable;
/** /**
* A read-only view of an underlying query * A read-only view of an underlying query
@ -58,7 +59,7 @@ abstract class DataView implements QueryInterface, SortRules, FilterColumns, Ite
* *
* @return IdoQuery * @return IdoQuery
*/ */
public function getIterator() public function getIterator(): Traversable
{ {
return $this->getQuery(); return $this->getQuery();
} }
@ -499,7 +500,7 @@ abstract class DataView implements QueryInterface, SortRules, FilterColumns, Ite
* *
* @return int * @return int
*/ */
public function count() public function count(): int
{ {
return $this->query->count(); return $this->query->count();
} }

View File

@ -9,6 +9,7 @@ use Icinga\Data\Filter\Filter;
use Icinga\Data\Filterable; use Icinga\Data\Filterable;
use IteratorAggregate; use IteratorAggregate;
use Icinga\Module\Monitoring\Backend\MonitoringBackend; use Icinga\Module\Monitoring\Backend\MonitoringBackend;
use Traversable;
abstract class ObjectList implements Countable, IteratorAggregate, Filterable abstract class ObjectList implements Countable, IteratorAggregate, Filterable
{ {
@ -118,10 +119,7 @@ abstract class ObjectList implements Countable, IteratorAggregate, Filterable
return $this->objects; return $this->objects;
} }
/** public function count(): int
* @return int
*/
public function count()
{ {
if ($this->count === null) { if ($this->count === null) {
$this->count = (int) $this->backend $this->count = (int) $this->backend
@ -135,7 +133,7 @@ abstract class ObjectList implements Countable, IteratorAggregate, Filterable
return $this->count; return $this->count;
} }
public function getIterator() public function getIterator(): Traversable
{ {
if ($this->objects === null) { if ($this->objects === null) {
$this->fetch(); $this->fetch();

View File

@ -5,6 +5,7 @@ namespace Icinga\Module\Monitoring\Plugin;
use ArrayIterator; use ArrayIterator;
use IteratorAggregate; use IteratorAggregate;
use Traversable;
class PerfdataSet implements IteratorAggregate class PerfdataSet implements IteratorAggregate
{ {
@ -36,7 +37,7 @@ class PerfdataSet implements IteratorAggregate
*/ */
protected function __construct($perfdataStr) protected function __construct($perfdataStr)
{ {
if (($perfdataStr = trim($perfdataStr)) !== '') { if ($perfdataStr && ($perfdataStr = trim($perfdataStr))) {
$this->perfdataStr = $perfdataStr; $this->perfdataStr = $perfdataStr;
$this->parse(); $this->parse();
} }
@ -47,7 +48,7 @@ class PerfdataSet implements IteratorAggregate
* *
* @return ArrayIterator * @return ArrayIterator
*/ */
public function getIterator() public function getIterator(): Traversable
{ {
return new ArrayIterator($this->asArray()); return new ArrayIterator($this->asArray());
} }

View File

@ -12,6 +12,7 @@ use Icinga\Data\Filter\Filter;
use Icinga\Web\Hook; use Icinga\Web\Hook;
use Icinga\Web\Session\SessionNamespace; use Icinga\Web\Session\SessionNamespace;
use Icinga\Module\Monitoring\DataView\DataView; use Icinga\Module\Monitoring\DataView\DataView;
use Traversable;
/** /**
* Represents a set of events in a specific range of time * Represents a set of events in a specific range of time
@ -100,7 +101,7 @@ class TimeLine implements IteratorAggregate
* *
* @return ArrayIterator * @return ArrayIterator
*/ */
public function getIterator() public function getIterator(): Traversable
{ {
return new ArrayIterator($this->toArray()); return new ArrayIterator($this->toArray());
} }

View File

@ -207,7 +207,7 @@ class TimeRange implements Iterator
/** /**
* Reset the iterator to its initial state * Reset the iterator to its initial state
*/ */
public function rewind() public function rewind(): void
{ {
$this->current = clone $this->start; $this->current = clone $this->start;
} }
@ -217,7 +217,7 @@ class TimeRange implements Iterator
* *
* @return bool * @return bool
*/ */
public function valid() public function valid(): bool
{ {
if ($this->negative) { if ($this->negative) {
return $this->current > $this->end; return $this->current > $this->end;
@ -231,7 +231,7 @@ class TimeRange implements Iterator
* *
* @return StdClass * @return StdClass
*/ */
public function current() public function current(): object
{ {
return $this->getTimeframe($this->current); return $this->getTimeframe($this->current);
} }
@ -241,7 +241,7 @@ class TimeRange implements Iterator
* *
* @return int * @return int
*/ */
public function key() public function key(): int
{ {
return $this->current->getTimestamp(); return $this->current->getTimestamp();
} }
@ -249,7 +249,7 @@ class TimeRange implements Iterator
/** /**
* Advance the iterator position by one * Advance the iterator position by one
*/ */
public function next() public function next(): void
{ {
$this->applyInterval($this->current, 0); $this->applyInterval($this->current, 0);
} }

View File

@ -5,6 +5,7 @@ namespace Icinga\Module\Setup;
use LogicException; use LogicException;
use RecursiveIterator; use RecursiveIterator;
use Traversable;
/** /**
* Container to store and handle requirements * Container to store and handle requirements
@ -258,7 +259,7 @@ class RequirementSet implements RecursiveIterator
* *
* @return bool * @return bool
*/ */
public function hasChildren() public function hasChildren(): bool
{ {
$current = $this->current(); $current = $this->current();
return $current instanceof static; return $current instanceof static;
@ -267,9 +268,9 @@ class RequirementSet implements RecursiveIterator
/** /**
* Return a iterator for the current nested set of requirements * Return a iterator for the current nested set of requirements
* *
* @return RecursiveIterator * @return ?RecursiveIterator
*/ */
public function getChildren() public function getChildren(): ?RecursiveIterator
{ {
return $this->current(); return $this->current();
} }
@ -277,7 +278,7 @@ class RequirementSet implements RecursiveIterator
/** /**
* Rewind the iterator to its first element * Rewind the iterator to its first element
*/ */
public function rewind() public function rewind(): void
{ {
reset($this->requirements); reset($this->requirements);
} }
@ -287,7 +288,7 @@ class RequirementSet implements RecursiveIterator
* *
* @return bool * @return bool
*/ */
public function valid() public function valid(): bool
{ {
return $this->key() !== null; return $this->key() !== null;
} }
@ -297,6 +298,7 @@ class RequirementSet implements RecursiveIterator
* *
* @return Requirement|RequirementSet * @return Requirement|RequirementSet
*/ */
#[\ReturnTypeWillChange]
public function current() public function current()
{ {
return current($this->requirements); return current($this->requirements);
@ -307,7 +309,7 @@ class RequirementSet implements RecursiveIterator
* *
* @return int * @return int
*/ */
public function key() public function key(): int
{ {
return key($this->requirements); return key($this->requirements);
} }
@ -315,7 +317,7 @@ class RequirementSet implements RecursiveIterator
/** /**
* Advance the iterator to the next element * Advance the iterator to the next element
*/ */
public function next() public function next(): void
{ {
next($this->requirements); next($this->requirements);
} }

View File

@ -7,17 +7,17 @@ use RecursiveIteratorIterator;
class RequirementsRenderer extends RecursiveIteratorIterator class RequirementsRenderer extends RecursiveIteratorIterator
{ {
public function beginIteration() public function beginIteration(): void
{ {
$this->tags[] = '<ul class="requirements">'; $this->tags[] = '<ul class="requirements">';
} }
public function endIteration() public function endIteration(): void
{ {
$this->tags[] = '</ul>'; $this->tags[] = '</ul>';
} }
public function beginChildren() public function beginChildren(): void
{ {
$this->tags[] = '<li>'; $this->tags[] = '<li>';
$currentSet = $this->getSubIterator(); $currentSet = $this->getSubIterator();
@ -25,7 +25,7 @@ class RequirementsRenderer extends RecursiveIteratorIterator
$this->tags[] = '<ul class="set-state ' . $state . '">'; $this->tags[] = '<ul class="set-state ' . $state . '">';
} }
public function endChildren() public function endChildren(): void
{ {
$this->tags[] = '</ul>'; $this->tags[] = '</ul>';
$this->tags[] = '</li>'; $this->tags[] = '</li>';

View File

@ -6,6 +6,7 @@ namespace Icinga\Module\Setup;
use ArrayIterator; use ArrayIterator;
use IteratorAggregate; use IteratorAggregate;
use Icinga\Module\Setup\Exception\SetupException; use Icinga\Module\Setup\Exception\SetupException;
use Traversable;
/** /**
* Container for multiple configuration steps * Container for multiple configuration steps
@ -21,7 +22,7 @@ class Setup implements IteratorAggregate
$this->steps = array(); $this->steps = array();
} }
public function getIterator() public function getIterator(): Traversable
{ {
return new ArrayIterator($this->getSteps()); return new ArrayIterator($this->getSteps());
} }

View File

@ -566,29 +566,14 @@ class WebWizard extends Wizard implements SetupWizard
public function getRequirements($skipModules = false) public function getRequirements($skipModules = false)
{ {
$set = new RequirementSet(); $set = new RequirementSet();
$phpVersion = Platform::getPhpVersion();
if (version_compare($phpVersion, '5.6', '>=') $set->add(new PhpVersionRequirement(array(
&& version_compare($phpVersion, '7.3', '<') 'condition' => array('>=', '7.2'),
) { 'description' => sprintf(mt(
$set->add(new PhpVersionRequirement(array( 'setup',
'optional' => true, 'Running Icinga Web 2 requires PHP version %s.'
'condition' => array('>=', '7.3'), ), '7.2')
'description' => mt( )));
'setup',
'Running Icinga Web 2 requires PHP version 7.3.'
. ' Older versions are only supported up until version 2.11.'
)
)));
} else {
$set->add(new PhpVersionRequirement(array(
'condition' => array('>=', '7.3'),
'description' => mt(
'setup',
'Running Icinga Web 2 requires PHP version 7.3.'
)
)));
}
$set->add(new OSRequirement(array( $set->add(new OSRequirement(array(
'optional' => true, 'optional' => true,

View File

@ -51,7 +51,10 @@ class LocalFileStorageTest extends BaseTestCase
{ {
$lfs = new TemporaryLocalFileStorage(); $lfs = new TemporaryLocalFileStorage();
$lfs->create('foobar', 'Hello world!'); $lfs->create('foobar', 'Hello world!');
static::assertSame(array('foobar'), array_values(iterator_to_array($lfs->getIterator())));
foreach ($lfs as $path => $_) {
$this->assertEquals($lfs->resolvePath('foobar'), $path);
}
} }
public function testGetIteratorThrowsNotReadableError() public function testGetIteratorThrowsNotReadableError()