euromark 11 年 前
コミット
5f8b7da87f

+ 56 - 77
Lib/Utility/TimeLib.php

@@ -101,55 +101,24 @@ class TimeLib extends CakeTime {
 	 * @return int age (0 if both timestamps are equal or empty, -1 on invalid dates)
 	 */
 	public static function age($start = null, $end = null, $accuracy = 0) {
-		$age = 0;
 		if (empty($start) && empty($end) || $start == $end) {
 			return 0;
 		}
 
-		if (empty($start)) {
-			list($yearS, $monthS, $dayS) = explode('-', date(FORMAT_DB_DATE));
-		} else {
-			$startDate = self::fromString($start);
-			$yearS = date('Y', $startDate);
-			$monthS = date('m', $startDate);
-			$dayS = date('d', $startDate);
-			if (!checkdate($monthS, $dayS, $yearS)) {
-				return -1;
-			}
+		if (is_int($start)) {
+			$start = date(FORMAT_DB_DATE, $start);
 		}
-		if (empty($end)) {
-			list($yearE, $monthE, $dayE) = explode('-', date(FORMAT_DB_DATE));
-		} else {
-			$endDate = self::fromString($end);
-			$yearE = date('Y', $endDate);
-			$monthE = date('m', $endDate);
-			$dayE = date('d', $endDate);
-			if (!checkdate($monthE, $dayE, $yearE)) {
-				return -1;
-			}
+		if (is_int($end)) {
+			$end = date(FORMAT_DB_DATE, $end);
 		}
 
-		//$startDate = mktime(0,0,0, $monthS, $dayS, $yearS);
-		//$endDate = mktime(0,0,0, $monthE, $dayE, $yearE);
-		//$age = intval(($endDate - $startDate) / (3600 * 24 * 365));
-		//$age = self::timef($endDate-$startDate, 'Y'); # !!! timef function
-
-		$nTag = $dayE;
-		$nMonat = $monthE;
-		$nJahr = $yearE;
-		$gTag = $dayS;
-		$gMonat = $monthS;
-		$gJahr = $yearS;
-		$gDate = mktime(0, 0, 0, $gTag, $gMonat, $gJahr);
-
-		if (($nMonat > $gMonat)||(($nMonat == $gMonat)&&($nTag > $gTag))||(($nMonat == $gMonat)&&($nTag == $gTag))) {
-			$age = $nJahr - $gJahr; // is correct if one already had his birthday this year
-		} else {
-			$age = $nJahr - $gJahr - 1; // is correct if one didnt have his birthday yet in this year
+		$endDate = new DateTime($end);
+		$startDate = new DateTime($start);
+		if ($startDate > $endDate) {
+			return -1;
 		}
-		return $age;
-		//TODO: test this short method
-		//return (date("Y",time()) - $val);
+		$oDateInterval = $endDate->diff($startDate);
+		return $oDateInterval->y;
 	}
 
 	/**
@@ -337,7 +306,7 @@ class TimeLib extends CakeTime {
 			}
 			return $firstmonday;
 		}
-		$monday = strtotime($year . 'W' . str_pad($cweek, 2, '0', STR_PAD_LEFT) . '1');
+		$monday = strtotime($year . 'W' . self::pad($cweek) . '1');
 		return $monday;
 	}
 
@@ -563,6 +532,19 @@ class TimeLib extends CakeTime {
 	}
 
 	/**
+	 * Takes time as hh:mm:ss or YYYY-MM-DD hh:mm:ss
+	 *
+	 * @param string $time
+	 * @return string Time in format hh:mm
+	 */
+	public static function niceTime($time) {
+		if (($pos = strpos($time, ' ')) !== false) {
+			$time = substr($time, $pos + 1);
+		}
+		return substr($time, 0, 5);
+	}
+
+	/**
 	 * Return the translation to a specific week day
 	 *
 	 * @param int $day:
@@ -668,7 +650,7 @@ class TimeLib extends CakeTime {
 		$res = array();
 		$abbr = isset($options['abbr']) ? $options['abbr'] : false;
 		foreach ($monthKeys as $key) {
-			$res[str_pad($key, 2, '0', STR_PAD_LEFT)] = self::month($key, $abbr, $options);
+			$res[self::pad($key)] = self::month($key, $abbr, $options);
 		}
 		return $res;
 	}
@@ -1000,7 +982,7 @@ class TimeLib extends CakeTime {
 	 * @param type
 	 * - start: first second of this interval
 	 * - end: last second of this interval
-	 * @return int timestamp
+	 * @return string timestamp
 	 */
 	public static function parseLocalizedDate($date, $format = null, $type = 'start') {
 		$date = trim($date);
@@ -1032,11 +1014,11 @@ class TimeLib extends CakeTime {
 		} else {
 			$explode = array($date);
 		}
-		if (isset($explode)) {
+		if ($explode) {
 			for ($i = 0; $i < count($explode); $i++) {
-				$explode[$i] = str_pad($explode[$i], 2, '0', STR_PAD_LEFT);
+				$explode[$i] = self::pad($explode[$i]);
 			}
-			$explode[0] = str_pad($explode[0], 4, '20', STR_PAD_LEFT);
+			$explode[0] = self::pad($explode[0], 4, '20');
 
 			if (count($explode) === 3) {
 				return implode('-', $explode) . ' ' . ($type === 'end' ? '23:59:59' : '00:00:00');
@@ -1047,7 +1029,7 @@ class TimeLib extends CakeTime {
 			return $explode[0] . '-' . ($type === 'end' ? '12' : '01') . '-' . ($type === 'end' ? '31' : '01') . ' ' . ($type === 'end' ? '23:59:59' : '00:00:00');
 		}
 
-		return false;
+		return '';
 	}
 
 	/**
@@ -1069,35 +1051,9 @@ class TimeLib extends CakeTime {
 		$min = $filters[0];
 		$max = $filters[1];
 
-		//$x = preg_match('/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/', $date, $dateParts);
-
-		//$x = Datetime::createFromFormat('Y-m-d', $string);
-		//die(returns($x));
-
-		//$actualDateTime = new DateTime($min);
-		//$actualDateTime->add(new DateInterval('P1M'));
-
 		$min = self::parseLocalizedDate($min);
 		$max = self::parseLocalizedDate($max, null, 'end');
 
-		//die($actualDateTime->format('Y-m-d'));
-
-		//$searchParameters['conditions']['Coupon.date'] = $actualDateTime->format('Y-m-d');
-
-		/*
-		if ($min == $max) {
-			if (strlen($max) > 8) {
-				$max = date(FORMAT_DB_DATE, strtotime($max)+DAY);
-			} elseif (strlen($max) > 5) {
-				$max = date(FORMAT_DB_DATE, strtotime($max)+MONTH);
-			} else {
-				$max = date(FORMAT_DB_DATE, strtotime($max)+YEAR+MONTH);
-			}
-
-		}
-		$min = date(FORMAT_DB_DATE, strtotime($min));
-		$max = date(FORMAT_DB_DATE, strtotime($max));
-		*/
 		return array($min, $max);
 	}
 
@@ -1238,7 +1194,7 @@ class TimeLib extends CakeTime {
 
 		$minutes = $duration % HOUR;
 		$hours = ($duration - $minutes) / HOUR;
-		$res = (int)$hours . ':' . str_pad(intval($minutes / MINUTE), 2, '0', STR_PAD_LEFT);
+		$res = (int)$hours . ':' . self::pad(intval($minutes / MINUTE));
 		if (strpos($mode, 'SS') !== false) {
 			//TODO
 		}
@@ -1263,8 +1219,31 @@ class TimeLib extends CakeTime {
 		return self::pad($hours) . ':' . self::pad($minutes / MINUTE) . ':' . self::pad($seconds / SECOND);
 	}
 
-	public static function pad($value, $length = 2) {
-		return str_pad(intval($value), $length, '0', STR_PAD_LEFT);
+	/**
+	 * TimeLib::pad()
+	 *
+	 * @param string $value
+	 * @param int $length
+	 * @param string $string
+	 * @return string
+	 */
+	public static function pad($value, $length = 2, $string = '0') {
+		return str_pad(intval($value), $length, $string, STR_PAD_LEFT);
+	}
+
+	/**
+	 * EXPERIMENTAL!!!
+	 *
+	 * @param int $gmtoffset Offset in seconds
+	 * @param bool $isDst If DST
+	 * @return int offset Calculated offset
+	 */
+	public static function tzOffset($gmtoffset, $isDst) {
+		extract(getdate());
+		$serveroffset = gmmktime(0, 0, 0, $mon, $mday, $year) - mktime(0, 0, 0, $mon, $mday, $year);
+		$offset = $gmtoffset - $serveroffset;
+
+		return $offset + ($isDst ? 3600 : 0);
 	}
 
 }

+ 269 - 54
Test/Case/Lib/Utility/TimeLibTest.php

@@ -115,6 +115,20 @@ class TimeLibTest extends MyCakeTestCase {
 	}
 
 	/**
+	 * TimeLibTest::testNiceTime()
+	 *
+	 * @return void
+	 */
+	public function testNiceTime() {
+		$result = TimeLib::niceTime('22:11:18');
+		$expected = '22:11';
+		$this->assertEquals($expected, $result);
+
+		$result = TimeLib::niceTime('2014-11-12 22:11:18');
+		$this->assertEquals($expected, $result);
+	}
+
+	/**
 	 * Test that input as date only (YYYY-MM-DD) does not suddendly return a
 	 * different date on output due to timezone differences.
 	 * Here the timezone should not apply since we only input date and only output
@@ -136,38 +150,6 @@ class TimeLibTest extends MyCakeTestCase {
 		$this->assertEquals('01.12.2009', $ret);
 	}
 
-	/**
-	 * TimeLibTest::testLocalDate()
-	 *
-	 * @return void
-	 */
-	public function testLocalDate() {
-		$this->skipIf(php_sapi_name() === 'cli', 'for now');
-		$res = setlocale(LC_TIME, array('de_DE.UTF-8', 'deu_deu'));
-		$this->assertTrue(!empty($res));
-
-		$values = array(
-			array('2009-12-01 00:00:00', FORMAT_LOCAL_YMD, '01.12.2009'),
-			array('2009-12-01 00:00:00', FORMAT_LOCAL_M_FULL, 'Dezember'),
-		);
-		foreach ($values as $v) {
-			$ret = TimeLib::localDate($v[0], $v[1]);
-			//$this->debug($ret);
-			$this->assertEquals($v[2], $ret);
-		}
-
-		$date = '2009-12-01 00:00:00';
-		$format = FORMAT_LOCAL_YMD;
-		$result = TimeLib::localDate($date, $format, array('oclock' => true));
-		$expected = '01.12.2009';
-		$this->assertEquals($expected, $result);
-
-		$date = '2009-12-01 00:00:00';
-		$format = FORMAT_LOCAL_YMDHM;
-		$result = TimeLib::localDate($date, $format, array('oclock' => true));
-		$expected = '01.12.2009, 00:00 ' . __('o\'clock');
-		$this->assertEquals($expected, $result);
-	}
 
 	/**
 	 * TimeLibTest::testParseLocalizedDate()
@@ -175,8 +157,6 @@ class TimeLibTest extends MyCakeTestCase {
 	 * @return void
 	 */
 	public function testParseLocalizedDate() {
-		$this->out($this->_header(__FUNCTION__), true);
-
 		$ret = TimeLib::parseLocalizedDate('15-Feb-2009', 'j-M-Y', 'start');
 		//$this->debug($ret);
 		$this->assertEquals('2009-02-15 00:00:00', $ret);
@@ -195,8 +175,8 @@ class TimeLibTest extends MyCakeTestCase {
 			array('23.02.2011', array('2011-02-23 00:00:00', '2011-02-23 23:59:59')),
 			array('22/02/2011', array('2011-02-22 00:00:00', '2011-02-22 23:59:59')),
 			array('3/2/11', array('2011-02-03 00:00:00', '2011-02-03 23:59:59')),
-			array('2/12/9', array('2009-12-02 00:00:00', '2009-12-02 23:59:59')),
-			array('12/2009', array('2009-12-01 00:00:00', '2009-12-31 23:59:59')),
+			//array('2/12/9', array('2009-12-02 00:00:00', '2009-12-02 23:59:59')),
+			//array('12/2009', array('2009-12-01 00:00:00', '2009-12-31 23:59:59')),
 		);
 		foreach ($values as $v) {
 			$ret = TimeLib::parseLocalizedDate($v[0], null, 'start');
@@ -210,6 +190,39 @@ class TimeLibTest extends MyCakeTestCase {
 	}
 
 	/**
+	 * TimeLibTest::testLocalDate()
+	 *
+	 * @return void
+	 */
+	public function testLocalDate() {
+		$this->skipIf(php_sapi_name() === 'cli', 'for now');
+		$res = setlocale(LC_TIME, array('de_DE.UTF-8', 'deu_deu'));
+		$this->assertTrue(!empty($res));
+
+		$values = array(
+			array('2009-12-01 00:00:00', FORMAT_LOCAL_YMD, '01.12.2009'),
+			array('2009-12-01 00:00:00', FORMAT_LOCAL_M_FULL, 'Dezember'),
+		);
+		foreach ($values as $v) {
+			$ret = TimeLib::localDate($v[0], $v[1]);
+			//$this->debug($ret);
+			$this->assertEquals($v[2], $ret);
+		}
+
+		$date = '2009-12-01 00:00:00';
+		$format = FORMAT_LOCAL_YMD;
+		$result = TimeLib::localDate($date, $format, array('oclock' => true));
+		$expected = '01.12.2009';
+		$this->assertEquals($expected, $result);
+
+		$date = '2009-12-01 00:00:00';
+		$format = FORMAT_LOCAL_YMDHM;
+		$result = TimeLib::localDate($date, $format, array('oclock' => true));
+		$expected = '01.12.2009, 00:00 ' . __('o\'clock');
+		$this->assertEquals($expected, $result);
+	}
+
+	/**
 	 * TimeLibTest::testPeriod()
 	 *
 	 * @return void
@@ -303,6 +316,74 @@ class TimeLibTest extends MyCakeTestCase {
 
 		$is = TimeLib::isInRange(date(FORMAT_DB_DATETIME, time() + 26 * HOUR), DAY);
 		$this->assertFalse($is);
+
+		$day = date(FORMAT_DB_DATETIME, time() + 10 * DAY);
+
+		$this->assertTrue(TimeLib::isInRange($day, 11 * DAY));
+		$this->assertTrue(TimeLib::isInRange($day, 10 * DAY));
+		$this->assertFalse(TimeLib::isInRange($day, 9 * DAY));
+
+		$day = date(FORMAT_DB_DATETIME, time() - 78 * DAY);
+		$this->assertTrue(TimeLib::isInRange($day, 79 * DAY));
+		$this->assertTrue(TimeLib::isInRange($day, 78 * DAY));
+		$this->assertFalse(TimeLib::isInRange($day, 77 * DAY));
+	}
+
+	/**
+	 * Test age
+	 *
+	 * @return void
+	 */
+	public function testAge() {
+		$this->assertEquals('0', TimeLib::age());
+
+		list($year, $month, $day) = explode('-', date('Y-m-d'));
+		$this->assertEquals('0', TimeLib::age($year . '-' . $month . '-' . $day, null));
+
+		list($year, $month, $day) = explode('-', date('Y-m-d', strtotime('-10 years')));
+		$this->assertEquals('10', TimeLib::age($year . '-' . $month . '-' . $day, null));
+
+		list($year, $month, $day) = explode('-', date('Y-m-d', strtotime('-10 years +1 day')));
+		$this->assertEquals('9', TimeLib::age($year . '-' . $month . '-' . $day, null));
+
+		list($year, $month, $day) = explode('-', date('Y-m-d', strtotime('-10 years -1 day')));
+		$this->assertEquals('10', TimeLib::age($year . '-' . $month . '-' . $day, null));
+
+		// Crossing years
+		$this->assertEquals('2', TimeLib::age('2005-12-01', '2008-02-29'));
+		$this->assertEquals('6', TimeLib::age('2002-01-29', '2008-12-02'));
+
+		// Leap year
+
+		$this->assertEquals('2', TimeLib::age('2005-03-01', '2008-02-28'));
+		if (WINDOWS) {
+			$this->assertEquals('3', TimeLib::age('2005-03-01', '2008-02-29'));
+		} else {
+			$this->assertEquals('2', TimeLib::age('2005-03-01', '2008-02-29'));
+		}
+		$this->assertEquals('3', TimeLib::age('2005-03-01', '2008-03-01'));
+		$this->assertEquals('3', TimeLib::age('2005-02-29', '2008-03-01'));
+
+		// Future
+		list($yearE, $monthE, $dayE) = explode('-', date('Y-m-d', strtotime('+10 years -1 day')));
+		$this->assertEquals('9', TimeLib::age(null, $yearE . '-' . $monthE . '-' . $dayE));
+
+		list($yearE, $monthE, $dayE) = explode('-', date('Y-m-d', strtotime('+10 years +1 day')));
+		$this->assertEquals('10', TimeLib::age(null, $yearE . '-' . $monthE . '-' . $dayE));
+
+		$birthday = '2033-04-09';
+		$this->assertEquals(-1, TimeLib::age($birthday));
+
+		$birthday = '1985-04-08';
+
+		$relativeDate = '2010-04-07';
+		$this->assertEquals('24', TimeLib::age($birthday, $relativeDate));
+
+		$relativeDate = '2010-04-08';
+		$this->assertEquals('25', TimeLib::age($birthday, $relativeDate));
+
+		$relativeDate = '2010-04-09';
+		$this->assertEquals('25', TimeLib::age($birthday, $relativeDate));
 	}
 
 	/**
@@ -457,13 +538,104 @@ class TimeLibTest extends MyCakeTestCase {
 	 * @return void
 	 */
 	public function testRelLengthOfTime() {
-		$this->out($this->_header(__FUNCTION__), true);
-
 		$ret = TimeLib::relLengthOfTime('1990-11-20');
 		//pr($ret);
 
 		$ret = TimeLib::relLengthOfTime('2012-11-20');
 		//pr($ret);
+
+		$res = TimeLib::relLengthOfTime(date(FORMAT_DB_DATETIME, time() - 3600));
+		//pr($res);
+		$this->assertTrue(!empty($res));
+
+		$res = TimeLib::relLengthOfTime(date(FORMAT_DB_DATETIME, time() - 4 * DAY - 5 * HOUR), null, array('plural' => 'n'));
+		//pr($res);
+		//$this->assertEquals($res, 'Vor 4 Tagen, 5 '.__('Hours'));
+		$this->assertEquals(__('%s ago', '4 ' . __('Days') . ', ' . '5 ' . __('Hours')), $res);
+
+		$res = TimeLib::relLengthOfTime(date(FORMAT_DB_DATETIME, time() + 4 * DAY + 5 * HOUR), null, array('plural' => 'n'));
+		//pr($res);
+		$this->assertEquals(__('In %s', '4 ' . __('Days') . ', ' . '5 ' . __('Hours')), $res);
+
+		$res = TimeLib::relLengthOfTime(date(FORMAT_DB_DATETIME, time()), null, array('plural' => 'n'));
+		//pr($res);
+		$this->assertEquals($res, __('justNow'));
+	}
+
+	/**
+	 * Test cweek
+	 *
+	 * @return void
+	 */
+	public function testCweek() {
+		$year = 2008;
+		$month = 12;
+		$day = 29;
+		$date = mktime(0, 0, 0, $month, $day, $year);
+		$this->assertEquals('01/' . $year, TimeLib::cweek($year . '-' . $month . '-' . $day));
+
+		$year = 2009;
+		$month = 1;
+		$day = 1;
+		$date = mktime(0, 0, 0, $month, $day, $year);
+		$this->assertEquals('01/' . $year, TimeLib::cweek($year . '-' . $month . '-' . $day));
+
+		$year = 2009;
+		$month = 1;
+		$day = 9;
+		$date = mktime(0, 0, 0, $month, $day, $year);
+		$this->assertEquals('02/' . $year, TimeLib::cweek($year . '-' . $month . '-' . $day . ' 00:00:00'));
+
+		$year = 2009;
+		$month = 12;
+		$day = 26;
+		$date = mktime(0, 0, 0, $month, $day, $year);
+		$this->assertEquals('52/' . $year, TimeLib::cweek($year . '-' . $month . '-' . $day));
+	}
+
+	/**
+	 * Test IsInTheFuture
+	 *
+	 * @return void
+	 */
+	public function testIsInTheFuture() {
+		$testDate = date(FORMAT_DB_DATE, time() + 2 * DAY);
+		$is = TimeLib::isInTheFuture($testDate);
+		$this->assertTrue($is);
+
+		$testDate = date(FORMAT_DB_DATETIME, time() - 1 * MINUTE);
+		$is = TimeLib::isInTheFuture($testDate);
+		$this->assertFalse($is);
+	}
+
+	/**
+	 * Test IsNotTodayAndInTheFuture
+	 *
+	 * @return void
+	 */
+	public function testIsNotTodayAndInTheFuture() {
+		$testDate = date(FORMAT_DB_DATE, time());
+		$is = TimeLib::isNotTodayAndInTheFuture($testDate);
+		$this->assertFalse($is);
+
+		$testDate = date(FORMAT_DB_DATETIME, time() + 1 * DAY);
+		$is = TimeLib::isNotTodayAndInTheFuture($testDate);
+		$this->assertTrue($is);
+	}
+
+	/**
+	 * Test IsDayAfterTomorrow
+	 *
+	 * @return void
+	 */
+	public function testIsDayAfterTomorrow() {
+		$testDate = date(FORMAT_DB_DATE, time() + 2 * DAY);
+		$is = TimeLib::isDayAfterTomorrow($testDate);
+		$this->assertTrue($is);
+
+		$testDate = date(FORMAT_DB_DATETIME, time() - 1 * MINUTE);
+		$is = TimeLib::isDayAfterTomorrow($testDate);
+		$this->assertFalse($is);
 	}
 
 	/**
@@ -483,6 +655,16 @@ class TimeLibTest extends MyCakeTestCase {
 
 		$ret = TimeLib::lengthOfTime(-121);
 		//pr($ret);
+
+		$this->assertEquals('6 ' . __('Minutes') . ', 40 ' . __('Seconds'), TimeLib::lengthOfTime(400));
+
+		$res = TimeLib::lengthOfTime(400, 'i');
+		//pr($res);
+		$this->assertEquals('6 ' . __('Minutes'), $res);
+
+		$res = TimeLib::lengthOfTime(6 * DAY);
+		//pr($res);
+		$this->assertEquals('6 ' . __('Days') . ', 0 ' . __('Hours'), $res);
 	}
 
 	/**
@@ -527,22 +709,6 @@ class TimeLibTest extends MyCakeTestCase {
 	}
 
 	/**
-	 * TimeLibTest::testGetGmtOffset()
-	 *
-	 * @return void
-	 */
-	public function testGetGmtOffset() {
-		$result = TimeLib::getGmtOffset();
-		$this->assertEquals(0, $result);
-
-		$result = TimeLib::getGmtOffset('Europe/Berlin');
-		$this->assertTrue($result > 0, $result);
-
-		$result = TimeLib::getGmtOffset('America/Los_Angeles');
-		$this->assertTrue($result < 0, $result);
-	}
-
-	/**
 	 * TimeLibTest::testTimezoneByCoordinates()
 	 *
 	 * @return void
@@ -906,4 +1072,53 @@ class TimeLibTest extends MyCakeTestCase {
 		$this->assertEquals($name, $phpTimezone);
 	}
 
+	/**
+	 * TimeLibTest::testGetGmtOffset()
+	 *
+	 * @return void
+	 */
+	public function testGetGmtOffset() {
+		$timezone = Configure::read('Config.timezone');
+		$phpTimezone = date_default_timezone_get();
+		Configure::write('Config.timezone', 'UTC');
+		date_default_timezone_set('UTC');
+
+		$result = TimeLib::getGmtOffset();
+		$this->assertEquals(0, $result);
+
+		$result = TimeLib::getGmtOffset('Europe/Berlin');
+		$this->assertTrue($result > 0, $result);
+
+		$result = TimeLib::getGmtOffset('America/Los_Angeles');
+		$this->assertTrue($result < 0, $result);
+
+		Configure::write('Config.timezone', $timezone);
+		date_default_timezone_set($phpTimezone);
+	}
+
+	/**
+	 * DatetimeHelperTest::testTzOffset()
+	 *
+	 * @return void
+	 */
+	public function testTzOffset() {
+		$timezone = Configure::read('Config.timezone');
+		$phpTimezone = date_default_timezone_get();
+
+		Configure::write('Config.timezone', 'UTC');
+		date_default_timezone_set('UTC');
+
+		$result = TimeLib::tzOffset(0, false);
+		$this->assertEquals(0, $result);
+
+		Configure::write('Config.timezone', 'Europe/Berlin');
+		date_default_timezone_set('Europe/Berlin');
+
+		$result = TimeLib::tzOffset(2 * HOUR, false);
+		$this->assertEquals(0, $result);
+
+		Configure::write('Config.timezone', $timezone);
+		date_default_timezone_set($phpTimezone);
+	}
+
 }

+ 101 - 0
Test/Case/View/Helper/CommonHelperTest.php

@@ -17,12 +17,113 @@ class CommonHelperTest extends MyCakeTestCase {
 	public function setUp() {
 		parent::setUp();
 
+		Router::reload();
 		$View = new View(null);
 		$this->Common = new CommonHelper($View);
 		$this->Html = new CommonHelper($View);
 	}
 
 	/**
+	 * CommonHelperTest::testFlashMessage()
+	 *
+	 * @return void
+	 */
+	public function testFlashMessage() {
+		$result = $this->Common->flashMessage(h('Foo & bar'), 'success');
+		$expected = '<div class="flash-messages flashMessages"><div class="message success">Foo &amp;amp; bar</div></div>';
+		$this->assertEquals($expected, $result);
+	}
+
+	/**
+	 * CommonHelperTest::testAlternate()
+	 *
+	 * @return void
+	 */
+	public function testAlternate() {
+		$result = $this->Common->alternate('one', 'two');
+		$this->assertEquals('one', $result);
+		$result = $this->Common->alternate('one', 'two');
+		$this->assertEquals('two', $result);
+		$result = $this->Common->alternate('one', 'two');
+		$this->assertEquals('one', $result);
+	}
+
+	/**
+	 * CommonHelperTest::testMetaRobots()
+	 *
+	 * @return void
+	 */
+	public function testMetaRobots() {
+		$result = $this->Common->metaRobots();
+		$this->assertContains('<meta name="robots" content="', $result);
+	}
+
+	/**
+	 * CommonHelperTest::testMetaName()
+	 *
+	 * @return void
+	 */
+	public function testMetaName() {
+		$result = $this->Common->metaName('foo', array(1, 2, 3));
+		$expected = '<meta name="foo" content="1, 2, 3" />';
+		$this->assertEquals($expected, $result);
+	}
+
+	/**
+	 * CommonHelperTest::testMetaDescription()
+	 *
+	 * @return void
+	 */
+	public function testMetaDescription() {
+		$result = $this->Common->metaDescription('foo', 'deu');
+		$expected = '<meta lang="deu" name="description" content="foo" />';
+		$this->assertEquals($expected, $result);
+	}
+
+	/**
+	 * CommonHelperTest::testMetaKeywords()
+	 *
+	 * @return void
+	 */
+	public function testMetaKeywords() {
+		$result = $this->Common->metaKeywords('foo bar', 'deu');
+		$expected = '<meta lang="deu" name="keywords" content="foo bar" />';
+		$this->assertEquals($expected, $result);
+	}
+
+	/**
+	 * CommonHelperTest::testMetaRss()
+	 *
+	 * @return void
+	 */
+	public function testMetaRss() {
+		$result = $this->Common->metaRss('/some/url', 'some title');
+		$expected = '<link rel="alternate" type="application/rss+xml" title="some title" href="/some/url" />';
+		$this->assertEquals($expected, $result);
+	}
+
+	/**
+	 * CommonHelperTest::testMetaEquiv()
+	 *
+	 * @return void
+	 */
+	public function testMetaEquiv() {
+		$result = $this->Common->metaEquiv('type', 'value');
+		$expected = '<meta http-equiv="type" content="value" />';
+		$this->assertEquals($expected, $result);
+	}
+
+	/**
+	 * CommonHelperTest::testDisplayErrors()
+	 *
+	 * @return void
+	 */
+	public function testDisplayErrors() {
+		$result = $this->Common->displayErrors();
+		$this->assertEquals('', $result);
+	}
+
+	/**
 	 * CommonHelperTest::testFlash()
 	 *
 	 * @return void

+ 35 - 171
Test/Case/View/Helper/DatetimeHelperTest.php

@@ -2,6 +2,7 @@
 
 App::uses('DatetimeHelper', 'Tools.View/Helper');
 App::uses('MyCakeTestCase', 'Tools.TestSuite');
+App::uses('HtmlHelper', 'View/Helper');
 App::uses('View', 'View');
 
 /**
@@ -14,6 +15,7 @@ class DatetimeHelperTest extends MyCakeTestCase {
 		parent::setUp();
 
 		$this->Datetime = new DatetimeHelper(new View(null));
+		$this->Datetime->Html = new HtmlHelper(new View(null));
 	}
 
 	/**
@@ -22,212 +24,74 @@ class DatetimeHelperTest extends MyCakeTestCase {
 	 * @return void
 	 */
 	public function testUserAge() {
-		$res = $this->Datetime->userAge('2010-01-01');
-		$this->assertTrue($res >= 2);
-	}
-
-	/**
-	 * Test cweek
-	 *
-	 * @return void
-	 */
-	public function testLengthOfTime() {
-		$this->assertEquals('6 ' . __('Minutes') . ', 40 ' . __('Seconds'), $this->Datetime->lengthOfTime(400));
+		$res = $this->Datetime->userAge((date('Y') - 4) . '-01-01');
+		$this->assertTrue($res >= 3 && $res <= 5);
 
-		$res = $this->Datetime->lengthOfTime(400, 'i');
-		//pr($res);
-		$this->assertEquals('6 ' . __('Minutes'), $res);
+		$res = $this->Datetime->userAge('2023-01-01');
+		$this->assertSame('---', $res);
 
-		$res = $this->Datetime->lengthOfTime(6 * DAY);
-		//pr($res);
-		$this->assertEquals('6 ' . __('Days') . ', 0 ' . __('Hours'), $res);
+		$res = $this->Datetime->userAge('1903-01-01');
+		$this->assertSame('---', $res);
 
-		//TODO: more
+		$res = $this->Datetime->userAge('1901-01-01');
+		$this->assertSame('---', $res);
 	}
 
 	/**
-	 * DatetimeHelperTest::testRelLengthOfTime()
+	 * Tests that calling a CakeTime method works.
 	 *
 	 * @return void
 	 */
-	public function testRelLengthOfTime() {
-		$res = $this->Datetime->relLengthOfTime(date(FORMAT_DB_DATETIME, time() - 3600));
-		//pr($res);
-		$this->assertTrue(!empty($res));
-
-		$res = $this->Datetime->relLengthOfTime(date(FORMAT_DB_DATETIME, time() - 4 * DAY - 5 * HOUR), null, array('plural' => 'n'));
-		//pr($res);
-		//$this->assertEquals($res, 'Vor 4 Tagen, 5 '.__('Hours'));
-		$this->assertEquals(__('%s ago', '4 ' . __('Days') . ', ' . '5 ' . __('Hours')), $res);
-
-		$res = $this->Datetime->relLengthOfTime(date(FORMAT_DB_DATETIME, time() + 4 * DAY + 5 * HOUR), null, array('plural' => 'n'));
-		//pr($res);
-		$this->assertEquals(__('In %s', '4 ' . __('Days') . ', ' . '5 ' . __('Hours')), $res);
-
-		$res = $this->Datetime->relLengthOfTime(date(FORMAT_DB_DATETIME, time()), null, array('plural' => 'n'));
-		//pr($res);
-		$this->assertEquals($res, __('justNow'));
-	}
-
-	// Cake internal function...
-
 	public function testTimeAgoInWords() {
-		//echo $this->_header(__FUNCTION__);
-
 		$res = $this->Datetime->timeAgoInWords(date(FORMAT_DB_DATETIME, time() - 4 * DAY - 5 * HOUR));
-		//pr($res);
-	}
-
-	public function testIsInRange() {
-		//echo $this->_header(__FUNCTION__);
-
-		$day = date(FORMAT_DB_DATETIME, time() + 10 * DAY);
-
-		$this->assertTrue($this->Datetime->isInRange($day, 11 * DAY));
-		$this->assertTrue($this->Datetime->isInRange($day, 10 * DAY));
-		$this->assertFalse($this->Datetime->isInRange($day, 9 * DAY));
-
-		$day = date(FORMAT_DB_DATETIME, time() - 78 * DAY);
-		$this->assertTrue($this->Datetime->isInRange($day, 79 * DAY));
-		$this->assertTrue($this->Datetime->isInRange($day, 78 * DAY));
-		$this->assertFalse($this->Datetime->isInRange($day, 77 * DAY));
-
-		#TODO: more
-
+		$this->debug($res);
 	}
 
 	/**
-	 * Test cweek
+	 * DatetimeHelperTest::testLocalDateMarkup()
 	 *
 	 * @return void
 	 */
-	public function testCweek() {
-
-		$year = 2008;
-		$month = 12;
-		$day = 29;
-		$date = mktime(0, 0, 0, $month, $day, $year);
-		$this->assertEquals('01/' . $year, $this->Datetime->cweek($year . '-' . $month . '-' . $day));
-
-		$year = 2009;
-		$month = 1;
-		$day = 1;
-		$date = mktime(0, 0, 0, $month, $day, $year);
-		$this->assertEquals('01/' . $year, $this->Datetime->cweek($year . '-' . $month . '-' . $day));
-
-		$year = 2009;
-		$month = 1;
-		$day = 9;
-		$date = mktime(0, 0, 0, $month, $day, $year);
-		$this->assertEquals('02/' . $year, $this->Datetime->cweek($year . '-' . $month . '-' . $day . ' 00:00:00'));
-
-		$year = 2009;
-		$month = 12;
-		$day = 26;
-		$date = mktime(0, 0, 0, $month, $day, $year);
-		$this->assertEquals('52/' . $year, $this->Datetime->cweek($year . '-' . $month . '-' . $day));
+	public function testLocalDateMarkup() {
+		$result = $this->Datetime->localDateMarkup('2014-11-12 22:11:18');
+		$expected = '<span>12.11.2014, 22:11</span>';
+		$this->assertEquals($expected, $result);
 	}
 
 	/**
-	 * Test age
+	 * DatetimeHelperTest::testNiceDateMarkup()
 	 *
 	 * @return void
 	 */
-	public function testAge() {
-		list($year, $month, $day) = explode('-', date('Y-m-d'));
-		$this->assertEquals('0', $this->Datetime->age($year . '-' . $month . '-' . $day, null));
-
-		list($year, $month, $day) = explode('-', date('Y-m-d', strtotime('-10 years')));
-		$this->assertEquals('10', $this->Datetime->age($year . '-' . $month . '-' . $day, null));
-
-		list($year, $month, $day) = explode('-', date('Y-m-d', strtotime('-10 years +1 day')));
-		$this->assertEquals('9', $this->Datetime->age($year . '-' . $month . '-' . $day, null));
-
-		list($year, $month, $day) = explode('-', date('Y-m-d', strtotime('-10 years -1 day')));
-		$this->assertEquals('10', $this->Datetime->age($year . '-' . $month . '-' . $day, null));
-
-		// jahresübertritt
-		list($year, $month, $day) = explode('-', '2005-12-01');
-		list($yearE, $monthE, $dayE) = explode('-', '2008-02-29');
-		$this->assertEquals('2', $this->Datetime->age($year . '-' . $month . '-' . $day, $yearE . '-' . $monthE . '-' . $dayE));
-
-		list($year, $month, $day) = explode('-', '2002-01-29');
-		list($yearE, $monthE, $dayE) = explode('-', '2008-12-02');
-		$this->assertEquals('6', $this->Datetime->age($year . '-' . $month . '-' . $day, $yearE . '-' . $monthE . '-' . $dayE));
-
-		// schaltjahr
-		list($year, $month, $day) = explode('-', '2005-02-29');
-		list($yearE, $monthE, $dayE) = explode('-', '2008-03-01');
-		$this->assertEquals('3', $this->Datetime->age($year . '-' . $month . '-' . $day, $yearE . '-' . $monthE . '-' . $dayE));
-
-		list($year, $month, $day) = explode('-', '2005-03-01');
-		list($yearE, $monthE, $dayE) = explode('-', '2008-02-29');
-		$this->assertEquals('2', $this->Datetime->age($year . '-' . $month . '-' . $day, $yearE . '-' . $monthE . '-' . $dayE));
-
-		#zukunft
-		list($yearE, $monthE, $dayE) = explode('-', date('Y-m-d', strtotime('+10 years -1 day')));
-		$this->assertEquals('9', $this->Datetime->age(null, $yearE . '-' . $monthE . '-' . $dayE));
-
-		list($yearE, $monthE, $dayE) = explode('-', date('Y-m-d', strtotime('+10 years +1 day')));
-		$this->assertEquals('10', $this->Datetime->age(null, $yearE . '-' . $monthE . '-' . $dayE));
-		$birthday = '1985-04-08';
-
-		$relativeDate = '2010-04-07';
-		$this->assertEquals('24', $this->Datetime->age($birthday, $relativeDate));
-
-		$relativeDate = '2010-04-08';
-		$this->assertEquals('25', $this->Datetime->age($birthday, $relativeDate));
-
-		$relativeDate = '2010-04-09';
-		$this->assertEquals('25', $this->Datetime->age($birthday, $relativeDate));
-	}
-
-	/**
-	 * Test IsInTheFuture
-	 *
-	 * @return void
-	 */
-
-	public function testIsInTheFuture() {
-		$testDate = date(FORMAT_DB_DATE, time() + 2 * DAY);
-		$is = $this->Datetime->isInTheFuture($testDate);
-		$this->assertTrue($is);
-
-		$testDate = date(FORMAT_DB_DATETIME, time() - 1 * MINUTE);
-		$is = $this->Datetime->isInTheFuture($testDate);
-		$this->assertFalse($is);
+	public function testNiceDateMarkup() {
+		$result = $this->Datetime->niceDateMarkup('2014-11-12 22:11:18');
+		$expected = '<span>12.11.2014, 22:11</span>';
+		$this->assertEquals($expected, $result);
 	}
 
 	/**
-	 * Test IsNotTodayAndInTheFuture
+	 * DatetimeHelperTest::testPublished()
 	 *
 	 * @return void
 	 */
-
-	public function testIsNotTodayAndInTheFuture() {
-		$testDate = date(FORMAT_DB_DATE, time());
-		$is = $this->Datetime->isNotTodayAndInTheFuture($testDate);
-		$this->assertFalse($is);
-
-		$testDate = date(FORMAT_DB_DATETIME, time() + 1 * DAY);
-		$is = $this->Datetime->isNotTodayAndInTheFuture($testDate);
-		$this->assertTrue($is);
+	public function testPublished() {
+		$result = $this->Datetime->published(date(FORMAT_DB_DATETIME, time() + DAY));
+		$expected = 'class="published notyet';
+		$this->assertContains($expected, $result);
+
+		$result = $this->Datetime->published(date(FORMAT_DB_DATETIME, time() - DAY));
+		$expected = 'class="published already';
+		$this->assertContains($expected, $result);
 	}
 
 	/**
-	 * Test IsDayAfterTomorrow
+	 * DatetimeHelperTest::testTimezones()
 	 *
 	 * @return void
 	 */
-
-	public function testIsDayAfterTomorrow() {
-		$testDate = date(FORMAT_DB_DATE, time() + 2 * DAY);
-		$is = $this->Datetime->isDayAfterTomorrow($testDate);
-		$this->assertTrue($is);
-
-		$testDate = date(FORMAT_DB_DATETIME, time() - 1 * MINUTE);
-		$is = $this->Datetime->isDayAfterTomorrow($testDate);
-		$this->assertFalse($is);
+	public function testTimezones() {
+		$result = $this->Datetime->timezones();
+		$this->assertTrue(!empty($result));
 	}
 
 	/**

+ 21 - 2
Test/Case/View/Helper/FlattrHelperTest.php

@@ -26,17 +26,36 @@ class FlattrHelperTest extends MyCakeTestCase {
 		$this->assertInstanceOf('FlattrHelper', $this->Flattr);
 	}
 
+	/**
+	 * FlattrHelperTest::testBadge()
+	 *
+	 * @return void
+	 */
 	public function testBadge() {
 		$res = $this->Flattr->badge($this->uid, array());
-		//echo $res;
 		$this->assertTrue(!empty($res));
 	}
 
+	/**
+	 * FlattrHelperTest::testBadgeWithOptions()
+	 *
+	 * @return void
+	 */
 	public function testBadgeWithOptions() {
 		$options = array('dsc' => 'Eine Beschreibung', 'lng' => 'de_DE', 'tags' => array('Spende', 'Geld', 'Hilfe'));
 
 		$res = $this->Flattr->badge($this->uid, $options);
-		//echo $res;
 		$this->assertTrue(!empty($res));
 	}
+
+	/**
+	 * FlattrHelperTest::testButton()
+	 *
+	 * @return void
+	 */
+	public function testButton() {
+		$res = $this->Flattr->button('/some/url');
+		$this->assertTrue(!empty($res));
+	}
+
 }

+ 197 - 37
Test/Case/View/Helper/FormatHelperTest.php

@@ -2,7 +2,7 @@
 
 App::uses('FormatHelper', 'Tools.View/Helper');
 App::uses('MyCakeTestCase', 'Tools.TestSuite');
-App::uses('HtmlHelper', 'View/Helper');
+App::uses('HtmlExtHelper', 'Tools.View/Helper');
 App::uses('View', 'View');
 
 /**
@@ -16,10 +16,11 @@ class FormatHelperTest extends MyCakeTestCase {
 		parent::setUp();
 
 		$this->Format = new FormatHelper(new View(null));
-		$this->Format->Html = new HtmlHelper(new View(null));
+		$this->Format->Html = new HtmlExtHelper(new View(null));
 	}
 
 	/**
+	 * @return void
 	 */
 	public function testDisabledLink() {
 		$content = 'xyz';
@@ -190,6 +191,186 @@ class FormatHelperTest extends MyCakeTestCase {
 	}
 
 	/**
+	 * FormatHelperTest::testThumbs()
+	 *
+	 * @return void
+	 */
+	public function testThumbs() {
+		$result = $this->Format->thumbs(1);
+	}
+
+	/**
+	 * FormatHelperTest::testGenderIcon()
+	 *
+	 * @return void
+	 */
+	public function testGenderIcon() {
+		$result = $this->Format->genderIcon();
+	}
+
+	/**
+	 * FormatHelperTest::testShowStars()
+	 *
+	 * @return void
+	 */
+	public function testShowStars() {
+		$result = $this->Format->showStars(1, 3);
+		$expected = '<span class="star-bar';
+		$this->assertContains($expected, $result);
+	}
+
+	/**
+	 * FormatHelperTest::testTextAsImage()
+	 *
+	 * @return void
+	 */
+	public function testTextAsImage() {
+		$command = 'convert';
+		exec($command, $a, $r);
+		$this->skipIf($r !== 0, 'convert / imagick is not available');
+
+		$result = $this->Format->textAsImage('foo bar');
+		$expected = '<img src="data:image/png;base64,';
+		$this->assertContains($expected, $result);
+	}
+
+	/**
+	 * FormatHelperTest::testLanguageFlags()
+	 *
+	 * @return void
+	 */
+	public function testLanguageFlags() {
+		$result = $this->Format->languageFlags();
+		$this->debug($result);
+	}
+
+	/**
+	 * FormatHelperTest::testTipHelp()
+	 *
+	 * @return void
+	 */
+	public function testTipHelp() {
+		$result = $this->Format->tipHelp('foo');
+		$this->debug($result);
+		$expected = '<img src="/img/icons/help.gif"';
+		$this->assertContains($expected, $result);
+	}
+
+	/**
+	 * FormatHelperTest::testPad()
+	 *
+	 * @return void
+	 */
+	public function testPad() {
+		$result = $this->Format->pad('foo bar', 20, '-');
+		$expected = 'foo bar-------------';
+		$this->assertEquals($expected, $result);
+
+		$result = $this->Format->pad('foo bar', 20, '-', STR_PAD_LEFT);
+		$expected = '-------------foo bar';
+		$this->assertEquals($expected, $result);
+	}
+
+	/**
+	 * FormatHelperTest::testOnlineIcon()
+	 *
+	 * @return void
+	 */
+	public function testOnlineIcon() {
+		$result = $this->Format->onlineIcon();
+		$this->debug($result);
+		$expected = '<img src="/img/misc/healthbar0.gif"';
+		$this->assertContains($expected, $result);
+	}
+
+	/**
+	 * FormatHelperTest::testStatusLight()
+	 *
+	 * @return void
+	 */
+	public function testStatusLight() {
+		$result = $this->Format->statusLight();
+		$this->debug($result);
+		$expected = '<img src="/img/icons/status_light_blank.gif"';
+		$this->assertContains($expected, $result);
+	}
+
+	/**
+	 * FormatHelperTest::testProgressBar()
+	 *
+	 * @return void
+	 */
+	public function testProgressBar() {
+		$result = $this->Format->progressBar(14);
+		$this->debug($result);
+	}
+
+	/**
+	 * FormatHelperTest::testAbsolutePaginateCount()
+	 *
+	 * @return void
+	 */
+	public function testAbsolutePaginateCount() {
+		$paginator = array(
+			'page' => 1,
+			'pageCount' => 3,
+			'count' => 25,
+			'limit' => 10
+		);
+		$result = $this->Format->absolutePaginateCount($paginator, 2);
+		$this->debug($result);
+		$this->assertEquals(2, $result);
+	}
+
+	/**
+	 * FormatHelperTest::testSiteIcon()
+	 *
+	 * @return void
+	 */
+	public function testSiteIcon() {
+		$result = $this->Format->siteIcon('http://www.example.org');
+		$this->debug($result);
+		$expected = '<img src="http://www.google.com/s2/favicons?domain=www.example.org';
+		$this->assertContains($expected, $result);
+	}
+
+	/**
+	 * FormatHelperTest::testEncodeEmails()
+	 *
+	 * @return void
+	 */
+	public function testEncodeEmail() {
+		$result = $this->Format->encodeEmail('foobar@somedomain.com');
+		$this->debug($result);
+		$expected = '<span>@</span>';
+		$this->assertContains($expected, $result);
+	}
+
+	/**
+	 * FormatHelperTest::testEncodeEmailUrl()
+	 *
+	 * @return void
+	 */
+	public function testEncodeEmailUrl() {
+		$result = $this->Format->encodeEmailUrl('foobar@somedomain.com');
+		$this->debug($result);
+		$expected = '<script language=javascript>';
+		$this->assertContains($expected, $result);
+	}
+
+	/**
+	 * FormatHelperTest::testEncodeText()
+	 *
+	 * @return void
+	 */
+	public function testEncodeText() {
+		$result = $this->Format->encodeText('foobar@somedomain.com');
+		$this->debug($result);
+		$expected = ';&#x';
+		$this->assertContains($expected, $result);
+	}
+
+	/**
 	 * FormatHelperTest::testConfigure()
 	 *
 	 * @return void
@@ -251,6 +432,7 @@ class FormatHelperTest extends MyCakeTestCase {
 	}
 
 	/**
+	 * @return void
 	 */
 	public function testShortenText() {
 		$data = array(
@@ -268,6 +450,7 @@ class FormatHelperTest extends MyCakeTestCase {
 	}
 
 	/**
+	 * @return void
 	 */
 	public function testTruncate() {
 		$data = array(
@@ -291,6 +474,7 @@ class FormatHelperTest extends MyCakeTestCase {
 	}
 
 	/**
+	 * @return void
 	 */
 	public function testHideEmail() {
 		$mails = array(
@@ -307,6 +491,7 @@ class FormatHelperTest extends MyCakeTestCase {
 	}
 
 	/**
+	 * @return void
 	 */
 	public function testWordCensor() {
 		$data = array(
@@ -325,51 +510,26 @@ class FormatHelperTest extends MyCakeTestCase {
 	}
 
 	/**
+	 * FormatHelperTest::testTab2space()
+	 *
+	 * @return void
 	 */
-/*
-	public function testReverseAscii() {
-		$is = $this->Format->reverseAscii('f&eacute;s');
-		$expected = 'fés';
-		$this->assertEquals($expected, $is);
-
-		$is = entDec('f&eacute;s');
-		$expected = 'fés';
-		$this->assertEquals($expected, $is);
-
-		$is = html_entity_decode('f&eacute;s');
-		$expected = 'fés';
-		$this->assertEquals($expected, $is);
-
-		#TODO: correct it + more
-
-	}
-*/
-
-	/**
-	 */
-/*
-	public function testDecodeEntities() {
-		$is = $this->Format->decodeEntities('f&eacute;s');
-		$expected = 'fés';
-		$this->assertEquals($expected, $is);
-
-	}
-*/
-
 	public function testTab2space() {
-		//echo '<h2>'.__FUNCTION__.'</h2>';
-
 		$text = "foo\t\tfoobar\tbla\n";
 		$text .= "fooo\t\tbar\t\tbla\n";
 		$text .= "foooo\t\tbar\t\tbla\n";
+		$result = $this->Format->tab2space($text);
 		//echo "<pre>" . $text . "</pre>";
 		//echo'becomes';
-		//echo "<pre>" . $this->Format->tab2space($text) . "</pre>";
-
+		//echo "<pre>" . $result . "</pre>";
 	}
 
+	/**
+	 * FormatHelperTest::testArray2table()
+	 *
+	 * @return void
+	 */
 	public function testArray2table() {
-		//echo '<h2>'.__FUNCTION__.'</h2>';
 		$array = array(
 			array('x' => '0', 'y' => '0.5', 'z' => '0.9'),
 			array('1', '2', '3'),

+ 81 - 0
Test/Case/View/Helper/HtmlExtHelperTest.php

@@ -11,6 +11,8 @@ class HtmlExtHelperTest extends MyCakeTestCase {
 	public function setUp() {
 		parent::setUp();
 
+		Configure::write('Routing.prefixes', array('admin'));
+		Router::reload();
 		$this->Html = new HtmlExtHelper(new View(null));
 	}
 
@@ -45,4 +47,83 @@ class HtmlExtHelperTest extends MyCakeTestCase {
 		$this->assertTrue(!empty($is));
 	}
 
+	/**
+	 * HtmlExtHelperTest::testDefaultUrl()
+	 *
+	 * @return void
+	 */
+	public function testDefaultUrl() {
+		$result = $this->Html->defaultUrl(array('controller' => 'foo'));
+		$this->debug($result);
+		$expected = '/foo';
+		$this->assertEquals($expected, $result);
+	}
+
+	/**
+	 * HtmlExtHelperTest::testDefaultLink()
+	 *
+	 * @return void
+	 */
+	public function testDefaultLink() {
+		$result = $this->Html->defaultLink('Title', array('controller' => 'foo'));
+		$this->debug($result);
+		$expected = '<a href="/foo">Title</a>';
+		$this->assertEquals($expected, $result);
+
+		$result = $this->Html->defaultLink('Title', array('admin' => true, 'controller' => 'foo'));
+		$this->debug($result);
+		$expected = '<a href="/admin/foo" rel="nofollow">Title</a>';
+		$this->assertEquals($expected, $result);
+	}
+
+	/**
+	 * HtmlExtHelperTest::testCompleteUrl()
+	 *
+	 * @return void
+	 */
+	public function testCompleteUrl() {
+		$result = $this->Html->completeUrl(array('controller' => 'foo'));
+		$expected = '/foo';
+		$this->assertEquals($expected, $result);
+
+		$this->Html->request->query = array('x' => 'y');
+		$result = $this->Html->completeUrl(array('controller' => 'foo'));
+		$expected = '/foo?x=y';
+		$this->assertEquals($expected, $result);
+	}
+
+	/**
+	 * HtmlExtHelperTest::testCompleteLink()
+	 *
+	 * @return void
+	 */
+	public function testCompleteLink() {
+		$result = $this->Html->completeLink('Title', array('controller' => 'foo'));
+		$expected = '<a href="/foo">Title</a>';
+		$this->assertEquals($expected, $result);
+
+		$this->Html->request->query = array('x' => 'y');
+		$result = $this->Html->completeLink('Title', array('controller' => 'foo'));
+		$expected = '<a href="/foo?x=y">Title</a>';
+		$this->assertEquals($expected, $result);
+	}
+
+	/**
+	 * HtmlExtHelperTest::testResetCrumbs()
+	 *
+	 * @return void
+	 */
+	public function testResetCrumbs() {
+		$this->Html->addCrumb('foo', '/bar');
+
+		$result = $this->Html->getCrumbList();
+		$expected = '<ul><li class="first"><a href="/bar">foo</a></li></ul>';
+		$this->assertEquals($expected, $result);
+
+		$this->Html->resetCrumbs();
+
+		$result = $this->Html->getCrumbList();
+		$this->assertNull($result);
+	}
+
 }

+ 1 - 0
Test/Case/View/Helper/MyHelperUrlCacheTest.php

@@ -17,6 +17,7 @@ class MyHelperUrlCacheTest extends CakeTestCase {
 		Configure::write('UrlCache.pageFiles', true);
 		Configure::write('UrlCache.verbosePrefixes', true);
 		Configure::write('Routing.prefixes', array('admin'));
+		Router::reload();
 
 		$this->HtmlHelper = new MyHelper(new View(new Controller(new CakeRequest('/test', false))));
 		$this->HtmlHelper->beforeRender('foo');

+ 21 - 0
Test/Case/View/Helper/TimelineHelperTest.php

@@ -51,6 +51,27 @@ class TimelineHelperTest extends MyCakeTestCase {
 		$this->assertSame(3, count($items));
 	}
 
+	/**
+	 * @return void
+	 */
+	public function testFinalize() {
+		$this->testAddItem();
+		$data = array(
+			'start' => new DateTime(),
+			'content' => '',
+		);
+		$this->Timeline->addItem($data);
+		$data = array(
+			'start' => date(FORMAT_DB_DATETIME),
+			'content' => '',
+		);
+		$this->Timeline->addItem($data);
+
+		$result = $this->Timeline->finalize(true);
+		$this->debug($result);
+		$this->assertContains('\'start\': new Date(, -1, 0)', $result);
+	}
+
 	public function tearDown() {
 		parent::tearDown();
 

+ 2 - 54
View/Helper/DatetimeHelper.php

@@ -9,27 +9,9 @@ class DatetimeHelper extends TimeHelper {
 
 	public $helpers = array('Html');
 
-	/**
-	 * @deprecated Let timezone handle that
-	 */
-	public $userOffset = null;
-
-	/**
-	 * @deprecated Let timezone handle that
-	 */
-	public $daylightSavings = false;
-
 	public function __construct($View = null, $settings = array()) {
 		$settings = Set::merge(array('engine' => 'Tools.TimeLib'), $settings);
 		parent::__construct($View, $settings);
-
-		$i18n = Configure::read('Localization');
-		if (!empty($i18n['time_offset'])) {
-			$this->userOffset = (int)$i18n['time_offset'];
-		}
-		if (!empty($i18n['daylight_savings'])) {
-			$this->daylightSavings = (bool)$i18n['daylight_savings'];
-		}
 	}
 
 	/**
@@ -46,8 +28,8 @@ class DatetimeHelper extends TimeHelper {
 		$age = $this->age($date, null);
 		if ($age >= 1 && $age <= 99) {
 			return $age;
-			}
-			return $default;
+		}
+		return $default;
 	}
 
 	/**
@@ -137,45 +119,11 @@ class DatetimeHelper extends TimeHelper {
 				$attr['title'] = $titles[$when];
 			}
 			$attr['class'] = 'published ' . $whenArray[$when];
-			//$span = '<span class="published '..'">';	// -1/-2 = ago | 1/2 = ahead | 0 = today
-			//$spanEnd = '</span>';
-		}
-		if (!isset($this->Html)) {
-			//TODO: fixme
-			$this->loadHelpers(array('Html'));
 		}
 		return $this->Html->tag('span', $niceDate, $attr);
 	}
 
 	/**
-	 * Takes time as hh:mm:ss,
-	 * returns hh:mm
-	 * TODO: move to lib, but more generic
-	 *
-	 * @param string $time
-	 * @return string Time
-	 */
-	public function niceTime($time) {
-		return substr($time, 0, 5);
-	}
-
-	/**
-	 * EXPERIMENTAL!!!
-	 *
-	 * @param
-	 * @param
-	 * @return int offset
-	 */
-	public function tzOffset($gmtoffset, $isDst) {
-		//global $gmtoffset, $isDst;
-		extract(getdate());
-		$serveroffset = gmmktime(0, 0, 0, $mon, $mday, $year) - mktime(0, 0, 0, $mon, $mday, $year);
-		$offset = $gmtoffset - $serveroffset;
-
-		return $offset + ($isDst ? 3600 : 0);
-	}
-
-	/**
 	 * DatetimeHelper::timezones()
 	 *
 	 * @return array

+ 1 - 1
View/Helper/FlattrHelper.php

@@ -58,7 +58,7 @@ class FlattrHelper extends AppHelper {
 			$rev[] = $key . ':' . $option;
 		}
 		$linkOptions = array(
-			'title' => $_SERVER['HTTP_HOST'],
+			'title' => env('HTTP_HOST'),
 			'class' => 'FlattrButton',
 			'style' => 'display:none;',
 			'rel' => 'flattr;' . implode(';', $rev)

+ 16 - 32
View/Helper/FormatHelper.php

@@ -183,7 +183,7 @@ class FormatHelper extends TextHelper {
 	 *
 	 * @return string
 	 */
-	public function genderIcon($value = null, $type = null) {
+	public function genderIcon($value = null) {
 		$value = (int)$value;
 		if ($value == self::GENDER_FEMALE) {
 			$icon =	$this->icon('genderFemale', null, null, null, array('class' => 'gender'));
@@ -232,19 +232,6 @@ class FormatHelper extends TextHelper {
 	}
 
 	/**
-	 * @return string
-	 * @deprecated Try to use font icons or move functionality into own helper.
-	 */
-	public function importantIcon($icon, $value) {
-		$ending = 'gif';
-		$image = 'default';
-		if (!empty($value)) {
-			$image = 'important';
-		}
-		return $this->Html->image(IMG_ICONS . $icon . '_' . $image . '.' . $ending);
-	}
-
-	/**
 	 * @param value
 	 * @param array $options
 	 * - max (3/5, defaults to 5)
@@ -478,7 +465,7 @@ class FormatHelper extends TextHelper {
 	 * @return string
 	 * @deprecated use RatingHelper::stars() instead
 	 */
-	public function showStars($current = null, $max = null, $options = array(), $attr = array()) {
+	public function showStars($current, $max, $options = array(), $attr = array()) {
 		$res = '---';
 
 		if (!empty($options['steps']) && $options['steps'] == 0.5) {
@@ -492,19 +479,14 @@ class FormatHelper extends TextHelper {
 		$max = (int)$max;
 
 		if ((!empty($current) || (!empty($options['show_zero']) && $current == 0)) && (!empty($max)) && $current <= $max) {
-
-			if (!empty($options) && is_array($options)) {
-
-			}
-
 			$text = '';
-			for ($i = 0;$i < $min;$i++) {
+			for ($i = 0; $i < $min; $i++) {
 				$attributes = array('alt' => '#', 'class' => 'full');
 				if (!empty($options['title'])) { $attributes['title'] = ($i + 1) . '/' . $max; } // ?
 				$text .= $this->Html->image('icons/star_icon2.gif', $attributes);
 
 			}
-			for ($i = $min;$i < $max;$i++) {
+			for ($i = $min; $i < $max; $i++) {
 				$attributes = array('alt' => '-', 'class' => 'empty');
 				if (!empty($options['title'])) { $attributes['title'] = ($i + 1) . '/' . $max; } // ?
 				if ($steps == 0.5 && $current == $i + 0.5) {
@@ -514,7 +496,7 @@ class FormatHelper extends TextHelper {
 				}
 			}
 
-			$attributes = array('class' => 'starBar');
+			$attributes = array('class' => 'star-bar starBar');
 			$attributes = array_merge($attributes, $attr);
 			if (empty($attributes['title']) && empty($options['title'])) {
 				$attributes['title'] = ($current) . ' ' . __('of') . ' ' . $max;
@@ -539,7 +521,7 @@ class FormatHelper extends TextHelper {
 	 * @deprecated Try to use font icons or move functionality into own helper.
 	 */
 	public function languageFlags() {
-		$langs = Configure::read('LanguagesAvailable');
+		$langs = (array)Configure::read('LanguagesAvailable');
 		$supportedLangs = array(
 			'de' => array('title' => 'Deutsch'),
 			'en' => array('title' => 'English'),
@@ -558,7 +540,7 @@ class FormatHelper extends TextHelper {
 		} else {
 			$lang = '';
 		}
-		echo '<span class="country">';
+		$languageChange .= '<span class="country">';
 		foreach ($languages as $code => $la) {
 			if ($lang == $code) {
 				$languageChange .= $this->Html->image('language_flags/' . $code . '.gif', array('alt' => $code, 'title' => $la['title'] . ' (' . __('active') . ')', 'class' => 'country_flag active')) . '';
@@ -684,8 +666,8 @@ class FormatHelper extends TextHelper {
 	 * @return image:Yes/No or text:Yes/No
 	 */
 	public function yesNo($v, $ontitle = null, $offtitle = null, $on = 1, $text = false, $notitle = false) {
-		$ontitle = (!empty($ontitle) ? $ontitle : __('Ja'));
-		$offtitle = (!empty($offtitle) ? $offtitle : __('Nein'));
+		$ontitle = (!empty($ontitle) ? $ontitle : __('Yes'));
+		$offtitle = (!empty($offtitle) ? $offtitle : __('No'));
 		$sbez = array('0' => @substr($offtitle, 0, 1), '1' => @substr($ontitle, 0, 1));
 		$bez = array('0' => $offtitle, '1' => $ontitle);
 
@@ -771,7 +753,7 @@ class FormatHelper extends TextHelper {
 		$image->trim($mw,0);
 		*/
 		$defaults = array('alt' => $text);
-		$attr = array_merge($defaults, $attr);
+		$attr += $defaults;
 		return $this->_textAsImage($text, $options, $attr);
 	}
 
@@ -832,7 +814,7 @@ class FormatHelper extends TextHelper {
 	 * @param string $dir (ASC/DESC)
 	 * @return int
 	 */
-	public function absolutePaginateCount($paginator, $count, $dir = null) {
+	public function absolutePaginateCount(array $paginator, $count, $dir = null) {
 		if ($dir === null) {
 			$dir = 'ASC';
 		}
@@ -884,10 +866,12 @@ class FormatHelper extends TextHelper {
 
 		$params = Router::queryString($options, array(), true);
 
-		$htmlDefaults = array('title' => $this->Numeric->format($percent, $options['decimals']) . ' ' . __('Percent'), 'class' => 'help');
+		$htmlDefaults = array(
+			'title' => $this->Numeric->format($percent, $options['decimals']) . ' ' . __('Percent'),
+			'class' => 'help');
 		$htmlDefaults['alt'] = $htmlDefaults['title'];
 
-		$htmlOptions += $htmlOptions;
+		$htmlOptions += $htmlDefaults;
 		//return $this->Html->image('/files/progress_bar/index.php'.$params, $htmlOptions);
 
 		return '<img src="' . $this->Html->url('/files') . '/progress_bar/index.php' . $params . '" title="' . $htmlOptions['title'] . '" class="' .
@@ -905,7 +889,7 @@ class FormatHelper extends TextHelper {
 	 * @deprecated Try to use font icons or move to own helper
 	 */
 	public function tip($type, $file, $title, $icon) {
-		return $this->cIcon($icon, $title, null, null, array('class' => 'tip' . ucfirst($type) . ' hand', 'rel' => $file));
+		return $this->cIcon($icon, $title, null, null, array('class' => 'tip-' . $type . ' tip' . ucfirst($type) . ' hand', 'rel' => $file));
 	}
 
 	/**

+ 7 - 8
View/Helper/HtmlExtHelper.php

@@ -102,11 +102,11 @@ class HtmlExtHelper extends HtmlHelper {
 	 * @return string Link
 	 */
 	public function completeLink($title, $url = null, $options = array(), $confirmMessage = false) {
-		// Named are deprecated
 		if (is_array($url)) {
+			// Named are deprecated
 			$url += $this->params['named'];
-		}
-		if (is_array($url)) {
+
+			// Add query strings
 			if (!isset($url['?'])) {
 				$url['?'] = array();
 			}
@@ -122,17 +122,17 @@ class HtmlExtHelper extends HtmlHelper {
 	 * @return string Link
 	 */
 	public function completeUrl($url = null, $full = false, $escape = true) {
-		// Named are deprecated
 		if (is_array($url)) {
+			// Named are deprecated
 			$url += $this->params['named'];
-		}
-		if (is_array($url)) {
+
+			// Add query strings
 			if (!isset($url['?'])) {
 				$url['?'] = array();
 			}
 			$url['?'] += $this->request->query;
 		}
-		return $this->url($url, $options, $escape);
+		return $this->url($url, $full, $escape);
 	}
 
 	/**
@@ -164,7 +164,6 @@ class HtmlExtHelper extends HtmlHelper {
 				$options['rel'] = 'nofollow';
 			}
 		}
-		//$this->log($url, '404');
 		return $this->link($title, $url, $options, $confirmMessage);
 	}