Implement DateTimeRenderer and fix history time format

refs #6980
This commit is contained in:
Alexander Fuhr 2014-09-23 11:36:09 +02:00
parent 18aad562dd
commit e784aa34b6
5 changed files with 339 additions and 7 deletions

View File

@ -0,0 +1,205 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\View;
use DateTime;
class DateTimeRenderer
{
const TYPE_DATETIME = 0;
const TYPE_TIME = 1;
const TYPE_TIMESPAN = 2;
const HOUR = 3600;
/**
* The present DateTime
*
* @var DateTime
*/
protected $now;
/**
* The DateTime tense
*
* @var bool
*/
protected $future;
/**
* The given DateTime type
*
* @var integer
*/
protected $type;
/**
* The given DateTime
*
* @var DateTime
*/
protected $dateTime;
public function __construct($dateTime, $future = false)
{
$this->future = $future;
$this->now = new DateTime();
$this->dateTime = $this->normalize($dateTime);
$this->detectType();
}
/**
* Creates a new DateTimeRenderer
*
* @param DateTime|int $dateTime
* @param bool $future
*
* @return DateTimeRenderer
*/
public static function create($dateTime, $future = false)
{
return new static($dateTime, $future);
}
/**
* Detects the DateTime context
*/
protected function detectType()
{
if ($this->now->format('Y-m-d') !== $this->dateTime->format('Y-m-d')) {
$this->type = self::TYPE_DATETIME;
return;
}
if (
$this->now->format('Y-m-d') === $this->dateTime->format('Y-m-d') &&
(abs($this->now->getTimestamp() - $this->dateTime->getTimestamp()) >= self::HOUR)
) {
$this->type = self::TYPE_TIME;
return;
}
if (
$this->now->format('Y-m-d') === $this->dateTime->format('Y-m-d') &&
(abs($this->now->getTimestamp() - $this->dateTime->getTimestamp()) < self::HOUR)
) {
$this->type = self::TYPE_TIMESPAN;
return;
}
}
/**
* Normalizes the given DateTime
*
* @param DateTime|int $dateTime
*
* @return DateTime
*/
public static function normalize($dateTime)
{
if (! ($dt = $dateTime) instanceof DateTime) {
$dt = new DateTime();
$dt->setTimestamp($dateTime);
}
return $dt;
}
/**
* Checks whether DateTime is a date with time
*
* @return bool
*/
public function isDateTime()
{
return $this->type === self::TYPE_DATETIME;
}
/**
* Checks whether DateTime is a time of the current day
*
* @return bool
*/
public function isTime()
{
return $this->type === self::TYPE_TIME;
}
/**
* Checks whether DateTime is in a defined interval
*
* @return bool
*/
public function isTimespan()
{
return $this->type === self::TYPE_TIMESPAN;
}
/**
* Returns the type of the DateTime
*
* @return mixed
*/
public function getType()
{
return $this->type;
}
/**
* Renders the DateTime on the basis of the type and returns suited text
*
* @param string $dateTimeText
* @param string $timeText
* @param string $timespanText
*
* @return string
*/
public function render($dateTimeText, $timeText, $timespanText)
{
if ($this->isDateTime()) {
return sprintf($dateTimeText, $this);
} elseif ($this->isTime()) {
return sprintf($timeText, $this);
} elseif ($this->isTimespan()) {
return sprintf($timespanText, $this);
}
return $dateTimeText;
}
/**
* Returns a rendered html wrapped text
*
* @return string
*/
public function __toString()
{
switch ($this->type) {
case self::TYPE_DATETIME:
$format = $this->dateTime->format('d.m.Y - H:i:s');
break;
case self::TYPE_TIME:
$format = $this->dateTime->format('H:i:s');
break;
case self::TYPE_TIMESPAN:
$format = $this->dateTime->diff($this->now)->format(t('%im %ss', 'timespan'));
break;
default:
$format = $this->dateTime->format('d.m.Y - H:i:s');
break;
}
$css = '';
if ($this->type === self::TYPE_TIMESPAN) {
$css = $this->future === true ? 'timeuntil' : 'timesince';
}
return sprintf(
'<span class="%s" title="%s">%s</span>',
$css,
$this->dateTime->format('d.m.Y - H:i:s'),
$format
);
}
}

View File

@ -44,3 +44,7 @@ $this->addHelperFunction('prefixedTimeUntil', function ($timestamp, $ucfirst = f
Format::prefixedTimeUntil($timestamp, $ucfirst)
);
});
$this->addHelperFunction('dateTimeRenderer', function ($dateTimeOrTimestamp, $future = false) {
return DateTimeRenderer::create($dateTimeOrTimestamp, $future);
});

View File

@ -44,7 +44,14 @@ foreach ($notifications as $notification):
}
?>
<tr class="state <?= $stateName ?>">
<td class="state"><?= $this->timeSince($notification->notification_start_time) ?></td>
<td class="state">
<?= $this->dateTimeRenderer($notification->notification_start_time)->render(
$this->translate('on %s', 'datetime'),
$this->translate('at %s', 'time'),
$this->translate('%s ago', 'timespan')
);
?>
</td>
<td style="font-size: 0.8em">
<?php if ($isService): ?>
<a href="<?= $href ?>"><?= $notification->service ?></a> on <?= $notification->host ?>

View File

@ -543,25 +543,39 @@
refreshTimeSince: function () {
$('.timesince').each(function (idx, el) {
var m = el.innerHTML.match(/^(.*?)(-?\d+)m\s(-?\d+)s/);
// todo remove after replace timeSince
var mp = el.innerHTML.match(/^(.*?)(-?\d+)d\s(-?\d+)h/);
if (mp !== null) {
return true;
}
var m = el.innerHTML.match(/^(.*?)(-?\d+)(.+\s)(-?\d+)(.+)/);
if (m !== null) {
var nm = parseInt(m[2]);
var ns = parseInt(m[3]);
var ns = parseInt(m[4]);
if (ns < 59) {
ns++;
} else {
ns = 0;
nm++;
}
$(el).html(m[1] + nm + 'm ' + ns + 's');
$(el).html(m[1] + nm + m[3] + ns + m[5]);
}
});
$('.timeuntil').each(function (idx, el) {
var m = el.innerHTML.match(/^(.*?)(-?\d+)m\s(-?\d+)s/);
// todo remove after replace timeUntil
var mp = el.innerHTML.match(/^(.*?)(-?\d+)d\s(-?\d+)h/);
if (mp !== null) {
return true;
}
var m = el.innerHTML.match(/^(.*?)(-?\d+)(.+\s)(-?\d+)(.+)/);
if (m !== null) {
var nm = parseInt(m[2]);
var ns = parseInt(m[3]);
var ns = parseInt(m[4]);
var signed = '';
var sec = 0;
@ -589,7 +603,7 @@
nm = Math.floor(sec/60);
ns = sec - nm * 60;
$(el).html(m[1] + signed + nm + 'm ' + ns + 's');
$(el).html(m[1] + signed + nm + m[3] + ns + m[5]);
}
});
},

View File

@ -0,0 +1,102 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Tests\Icinga\Web;
use DateTime;
use Icinga\Test\BaseTestCase;
use Icinga\Web\View\DateTimeRenderer;
class DateTimeRendererTest extends BaseTestCase
{
public function testWhetherCreateCreatesDateTimeRenderer()
{
$dateTime = new DateTime();
$dt = DateTimeRenderer::create($dateTime);
$this->assertInstanceOf(
'Icinga\Web\View\DateTimeRenderer',
$dt,
'Dashboard::create() could not create DateTimeRenderer'
);
}
/**
* @depends testWhetherCreateCreatesDateTimeRenderer
*/
public function testWhetherIsDateTimeReturnsRightType()
{
$dateTime = new DateTime('+1 day');
$dt = DateTimeRenderer::create($dateTime);
$this->assertTrue(
$dt->isDateTime(),
'Dashboard::isDateTime() returns wrong type'
);
}
/**
* @depends testWhetherCreateCreatesDateTimeRenderer
*/
public function testWhetherIsTimeReturnsRightType()
{
$dateTime = new DateTime('+1 hour');
$dt = DateTimeRenderer::create($dateTime);
$this->assertTrue(
$dt->isTime(),
'Dashboard::isTime() returns wrong type'
);
}
/**
* @depends testWhetherCreateCreatesDateTimeRenderer
*/
public function testWhetherIsTimespanReturnsRightType()
{
$dateTime = new DateTime('+1 minute');
$dt = DateTimeRenderer::create($dateTime);
$this->assertTrue(
$dt->isTimespan(),
'Dashboard::isTimespan() returns wrong type'
);
}
/**
* @depends testWhetherCreateCreatesDateTimeRenderer
*/
public function testWhetherNormalizeReturnsNormalizedDateTime()
{
$dateTime = time();
$dt = DateTimeRenderer::normalize($dateTime);
$this->assertInstanceOf(
'DateTime',
$dt,
'Dashboard::normalize() returns wrong instance'
);
}
/**
* @depends testWhetherCreateCreatesDateTimeRenderer
*/
public function testWhetherRenderReturnsRightText()
{
$dateTime = new DateTime('+1 minute');
$dt = DateTimeRenderer::create($dateTime);
$text = $dt->render(
'#1 The service is down since %s',
'#2 The service is down since %s o\'clock.',
'#3 The service is down for %s.'
);
$this->assertRegExp(
'/#3/',
$text,
'Dashboard::render() returns wrong text'
);
}
}