Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
24 / 24
HTML
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
4 / 4
16
100.00% covered (success)
100.00%
24 / 24
 tag
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 attr_tag
100.00% covered (success)
100.00%
1 / 1
5
100.00% covered (success)
100.00%
6 / 6
 attr
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
3 / 3
 html
100.00% covered (success)
100.00%
1 / 1
9
100.00% covered (success)
100.00%
14 / 14
1<?php
2
3// {{{ License
4// This file is part of GNU social - https://www.gnu.org/software/social
5//
6// GNU social is free software: you can redistribute it and/or modify
7// it under the terms of the GNU Affero General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10//
11// GNU social is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14// GNU Affero General Public License for more details.
15//
16// You should have received a copy of the GNU Affero General Public License
17// along with GNU social.  If not, see <http://www.gnu.org/licenses/>.
18// }}}
19
20/**
21 * HTML Abstraction
22 *
23 * @author    Hugo Sales <hugo@hsal.es>
24 * @copyright 2020-2021 Free Software Foundation, Inc http://www.fsf.org
25 * @license   https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
26 */
27
28namespace App\Util;
29
30use Functional as F;
31use InvalidArgumentException;
32
33abstract class HTML
34{
35    /**
36     * Creates an HTML tag without attributes
37     *
38     * @param string       $tag
39     * @param array|string $content
40     * @param bool         $empty_tag
41     * @param null|mixed   $attrs
42     *
43     * @return array
44     */
45    public static function tag(string $tag, $attrs = null,  $content = null, bool $empty_tag = false): array
46    {
47        return self::attr_tag($tag, $attrs ?? '', $content ?? '', $empty_tag);
48    }
49
50    /**
51     * Create tag, possibly with attributes and indentation
52     *
53     * @param string       $tag
54     * @param array|string $attrs     - element attributes
55     * @param array|string $content   - what goes inside the tag
56     * @param bool         $empty_tag
57     *
58     * @return array
59     */
60    private static function attr_tag(string $tag, $attrs, $content = '', bool $empty_tag = false): array
61    {
62        $html = '<' . $tag . (is_string($attrs) ? ($attrs ? ' ' : '') . $attrs : self::attr($attrs));
63        if ($empty_tag) {
64            $html .= '/>';
65        } else {
66            $inner = Formatting::indent($content);
67            $html .= ">\n" . ($inner == '' ? '' : $inner . "\n") . "</{$tag}>";
68        }
69        return explode("\n", $html);
70    }
71
72    /**
73     * Attribute with given optional value
74     *
75     * @param array $attrs
76     *
77     * @return string
78     */
79    private static function attr(array $attrs): string
80    {
81        return ' ' . implode(' ', F\map($attrs, function ($val, $key, $_) {
82            return "{$key}=\"{$val}\"";
83        }));
84    }
85
86    /**
87     * @param $html
88     *
89     * @return string
90     */
91    public static function html($html): string
92    {
93        if (is_string($html)) {
94            return $html;
95        } elseif (is_array($html)) {
96            $out = '';
97            foreach ($html as $tag => $contents) {
98                if ($contents == 'empty' || isset($contents['empty'])) {
99                    $out .= "<{$tag}/>";
100                } else {
101                    $attrs  = isset($contents['attrs']) ? self::attr(array_shift($contents)) : '';
102                    $is_tag = preg_match('/[A-Za-z][A-Za-z0-9]*/', $tag);
103                    $inner  = self::html($contents);
104                    $inner  = $is_tag ? Formatting::indent($inner) : $inner;
105                    $out .= $is_tag ? "<{$tag}{$attrs}>\n{$inner}\n</{$tag}>\n" : $inner;
106                }
107            }
108            return $out;
109        } else {
110            throw new InvalidArgumentException('HTML::html argument must be of type string or array');
111        }
112    }
113}