Browse Source

added HtmlHelper::time() supporting string, DateTime & DateInterval instances

Fabian Peter Hammerle 7 years ago
parent
commit
de4bd66538
4 changed files with 246 additions and 0 deletions
  1. 35 0
      DateTimeHelper.php
  2. 22 0
      HtmlHelper.php
  3. 142 0
      tests/DateTimeHelperTest.php
  4. 47 0
      tests/HtmlHelperTest.php

+ 35 - 0
DateTimeHelper.php

@@ -72,4 +72,39 @@ class DateTimeHelper
             return null;
         }
     }
+
+    public static function deinvertInterval(\DateInterval $source = null)
+    {
+        // \DateInterval does not implement clone.
+        // @see https://bugs.php.net/bug.php?id=50559
+        $result = unserialize(serialize($source));
+        if($result->invert) {
+            $result->y *= -1;
+            $result->m *= -1;
+            $result->d *= -1;
+            $result->h *= -1;
+            $result->i *= -1;
+            $result->s *= -1;
+            $result->invert = 0;
+        }
+        return $result;
+    }
+
+    /**
+     * @param \DateInterval|null $i
+     * @return string|null
+     */
+    public static function intervalToIso(\DateInterval $i = null)
+    {
+        if(is_null($i)) {
+            return null;
+        } else {
+            $i = self::deinvertInterval($i);
+            if($i->y < 0 || $i->m < 0 || $i->d < 0 || $i->h < 0 || $i->i < 0 || $i->s < 0) {
+                throw new \Exception('negative intervals are not supported');
+            } else {
+                return $i->format('P%yY%mM%dDT%hH%iM%sS');
+            }
+        }
+    }
 }

+ 22 - 0
HtmlHelper.php

@@ -81,4 +81,26 @@ class HtmlHelper
             self::endTag($tag_name)
             );
     }
+
+    public static function time($dt, $content, array $attributes = [])
+    {
+        if($dt instanceof \DateTime) {
+            $attr = $dt->format(\DateTime::W3C);
+        } elseif($dt instanceof \DateInterval) {
+            $attr = DateTimeHelper::intervalToIso($dt);
+        } else {
+            $attr = $dt;
+        }
+
+        return self::nonVoidTag(
+            'time',
+            is_callable($content) ? $content($dt) : $content,
+            array_merge(
+                ['datetime' => $attr],
+                ArrayHelper::map($attributes, function($v) use ($dt) {
+                    return is_callable($v) ? $v($dt) : $v;
+                    })
+                )
+            );
+    }
 }

+ 142 - 0
tests/DateTimeHelperTest.php

@@ -166,4 +166,146 @@ class DateTimeHelperTest extends \PHPUnit_Framework_TestCase
     {
         DateTimeHelper::parseGetStart($text);
     }
+
+    public function deinvertIntervalProvider()
+    {
+        return [
+            [
+                \DateInterval::createFromDateString('-2 years'),
+                ['y' => -2, 'm' => 0, 'd' => 0, 'h' => 0, 'i' => 0, 's' => 0],
+                ],
+            [
+                \DateInterval::createFromDateString('-2 months'),
+                ['y' => 0, 'm' => -2, 'd' => 0, 'h' => 0, 'i' => 0, 's' => 0],
+                ],
+            [
+                \DateInterval::createFromDateString('-2 days'),
+                ['y' => 0, 'm' => 0, 'd' => -2, 'h' => 0, 'i' => 0, 's' => 0],
+                ],
+            [
+                \DateInterval::createFromDateString('-2 hours'),
+                ['y' => 0, 'm' => 0, 'd' => 0, 'h' => -2, 'i' => 0, 's' => 0],
+                ],
+            [
+                \DateInterval::createFromDateString('-2 minutes'),
+                ['y' => 0, 'm' => 0, 'd' => 0, 'h' => 0, 'i' => -2, 's' => 0],
+                ],
+            [
+                \DateInterval::createFromDateString('-2 seconds'),
+                ['y' => 0, 'm' => 0, 'd' => 0, 'h' => 0, 'i' => 0, 's' => -2],
+                ],
+            [
+                (new \DateTime('2016-08'))->diff(new \DateTime('2016-07')),
+                ['y' => 0, 'm' => -1, 'd' => 0, 'h' => 0, 'i' => 0, 's' => 0],
+                ],
+            [
+                (new \DateTime('2016-08-03'))->diff(new \DateTime('2016-07-03')),
+                ['y' => 0, 'm' => -1, 'd' => 0, 'h' => 0, 'i' => 0, 's' => 0],
+                ],
+            [
+                (new \DateTime('2016-07-03'))->diff(new \DateTime('2016-08-03')),
+                ['y' => 0, 'm' => 1, 'd' => 0, 'h' => 0, 'i' => 0, 's' => 0],
+                ],
+            [
+                (new \DateTime('2016-08-04'))->diff(new \DateTime('2016-07-03')),
+                ['y' => 0, 'm' => -1, 'd' => -1, 'h' => 0, 'i' => 0, 's' => 0],
+                ],
+            [
+                (new \DateTime('2016-07-03'))->diff(new \DateTime('2016-08-04')),
+                ['y' => 0, 'm' => 1, 'd' => 1, 'h' => 0, 'i' => 0, 's' => 0],
+                ],
+            [
+                (new \DateTime('2016-08-02'))->diff(new \DateTime('2016-07-03')),
+                ['y' => 0, 'm' => 0, 'd' => -30, 'h' => 0, 'i' => 0, 's' => 0],
+                ],
+            [
+                (new \DateTime('2016-07-03'))->diff(new \DateTime('2016-08-02')),
+                ['y' => 0, 'm' => 0, 'd' => 30, 'h' => 0, 'i' => 0, 's' => 0],
+                ],
+            [
+                (new \DateTime('2016-08-04 18:10:02'))->diff(new \DateTime('2016-07-03 14:13:03')),
+                ['y' => 0, 'm' => -1, 'd' => -1, 'h' => -3, 'i' => -56, 's' => -59],
+                ],
+            [
+                (new \DateTime('2016-07-03 14:13:03'))->diff(new \DateTime('2016-08-04 18:10:02')),
+                ['y' => 0, 'm' => 1, 'd' => 1, 'h' => 3, 'i' => 56, 's' => 59],
+                ],
+            ];
+    }
+
+    /**
+     * @dataProvider deinvertIntervalProvider
+     */
+    public function testDeinvertInterval($source, $expected_attr)
+    {
+        // \DateInterval does not implement clone.
+        // @see https://bugs.php.net/bug.php?id=50559
+        $source_copy = unserialize(serialize($source));
+        $deinverted = DateTimeHelper::deinvertInterval($source_copy);
+        $this->assertEquals($source, $source_copy);
+        $this->assertEquals(0, $deinverted->invert);
+        foreach($expected_attr as $k => $v) {
+            $this->assertSame($v, $deinverted->$k);
+        }
+    }
+
+    public function intervalToIsoProvider()
+    {
+        return [
+            [null, null],
+            ];
+    }
+
+    /**
+     * @dataProvider intervalToIsoProvider
+     */
+    public function testIntervalToIso($interval, $iso)
+    {
+        $this->assertSame($iso, DateTimeHelper::intervalToIso($interval));
+    }
+
+    public function intervalToIsoReinitProvider()
+    {
+        return [
+            [new \DateInterval('P1Y')],
+            [new \DateInterval('P1M')],
+            [new \DateInterval('P1D')],
+            [new \DateInterval('PT1H')],
+            [new \DateInterval('PT1M')],
+            [new \DateInterval('PT1S')],
+            [new \DateInterval('P1Y2M3DT4H5M6S')],
+            ];
+    }
+
+    /**
+     * @dataProvider intervalToIsoReinitProvider
+     */
+    public function testIntervalToIsoReinit($interval)
+    {
+        $iso = DateTimeHelper::intervalToIso($interval);
+        $this->assertEquals($interval, new \DateInterval($iso));
+    }
+
+    public function intervalToIsoReinitUnsupportedProvider()
+    {
+        return [
+            [\DateInterval::createFromDateString('-2 years')],
+            [\DateInterval::createFromDateString('-2 months')],
+            [\DateInterval::createFromDateString('-2 days')],
+            [\DateInterval::createFromDateString('-2 hours')],
+            [\DateInterval::createFromDateString('-2 minutes')],
+            [\DateInterval::createFromDateString('-2 seconds')],
+            [(new \DateTime('2016-08-03'))->diff(new \DateTime('2016-07-03'))],
+            [(new \DateTime('2016-08-03 10:00:01'))->diff(new \DateTime('2016-08-03 10:00:00'))],
+            ];
+    }
+
+    /**
+     * @dataProvider intervalToIsoReinitUnsupportedProvider
+     * @expectedException \Exception
+     */
+    public function testIntervalToIsoReinitUnsupported($interval)
+    {
+        DateTimeHelper::intervalToIso($interval);
+    }
 }

+ 47 - 0
tests/HtmlHelperTest.php

@@ -196,4 +196,51 @@ class HtmlHelperTest extends \PHPUnit_Framework_TestCase
     {
         $this->assertSame($expected_tag, HtmlHelper::nonVoidTag($name, $content, $attributes));
     }
+
+    public function timeProvider()
+    {
+        return [
+            [null, null, [], null],
+            [null, '04.08.2016', [], '<time>04.08.2016</time>'],
+            [null, function($y) { return is_null($y) ? '2016' : ''; }, [], '<time>2016</time>'],
+            ['2016-08-04', '04.08.2016', [], '<time datetime="2016-08-04">04.08.2016</time>'],
+            ['2016-08-04', '', [], '<time datetime="2016-08-04"></time>'],
+            ['2016', '2016', ['title' => 'year'], '<time datetime="2016" title="year">2016</time>'],
+            ['2016', '2016', ['datetime' => '2014'], '<time datetime="2014">2016</time>'],
+            ['2016', function($y) { return strrev($y); }, [], '<time datetime="2016">6102</time>'],
+            ['2016', function() { return 'year'; }, [], '<time datetime="2016">year</time>'],
+            [
+                new \DateTime('2016-08-04 13:54+08:00'),
+                '2016',
+                [],
+                '<time datetime="2016-08-04T13:54:00+08:00">2016</time>',
+                ],
+            [
+                new \DateTime('2016-08-04 13:54:13Z'),
+                function($dt) { return $dt->format('m.d.Y'); },
+                [],
+                '<time datetime="2016-08-04T13:54:13+00:00">08.04.2016</time>',
+                ],
+            [
+                new \DateTime('2016-08-04 13:54:13Z'),
+                function($dt) { return $dt->format('m.d.Y'); },
+                ['title' => function($dt) { return $dt->format('H:i'); }],
+                '<time datetime="2016-08-04T13:54:13+00:00" title="13:54">08.04.2016</time>',
+                ],
+            [
+                new \DateInterval('P1YT15S'),
+                function($i) { return $i->format('%yy, %ss'); },
+                ['title' => function($i) { return $i->format('%mm'); }],
+                '<time datetime="P1Y0M0DT0H0M15S" title="0m">1y, 15s</time>',
+                ],
+            ];
+    }
+
+    /**
+     * @dataProvider timeProvider
+     */
+    public function testTime($dt, $content, $attributes, $expected_tag)
+    {
+        $this->assertSame($expected_tag, HtmlHelper::time($dt, $content, $attributes));
+    }
 }