Merge branch 'master' into next
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / system / MetaTagHandler.class.php
1 <?php
2 declare(strict_types=1);
3 namespace wcf\system;
4 use wcf\util\StringUtil;
5
6 /**
7 * Handles meta tags.
8 *
9 * @author Alexander Ebert
10 * @copyright 2001-2018 WoltLab GmbH
11 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
12 * @package WoltLabSuite\Core\System\Message
13 */
14 class MetaTagHandler extends SingletonFactory implements \Countable, \Iterator {
15 /**
16 * current iterator index
17 * @var integer
18 */
19 protected $index = 0;
20
21 /**
22 * list of index to object relation
23 * @var integer[]
24 */
25 protected $indexToObject = [];
26
27 /**
28 * list of meta tags
29 * @var array
30 */
31 protected $objects = [];
32
33 /**
34 * @inheritDoc
35 */
36 protected function init() {
37 // set default tags
38 if ($value = WCF::getLanguage()->get(META_DESCRIPTION)) {
39 $this->addTag('description', 'description', $value);
40 }
41 if ($value = WCF::getLanguage()->get(META_KEYWORDS)) {
42 $this->addTag('keywords', 'keywords', $value);
43 }
44 if ($value = WCF::getLanguage()->get(PAGE_TITLE)) {
45 $this->addTag('og:site_name', 'og:site_name', $value, true);
46 }
47 if (OG_IMAGE) {
48 $this->addTag('og:image', 'og:image', (preg_match('~^https?://~', OG_IMAGE) ? OG_IMAGE : WCF::getPath() . OG_IMAGE), true);
49 }
50 if (FB_SHARE_APP_ID) {
51 $this->addTag('fb:app_id', 'fb:app_id', FB_SHARE_APP_ID, true);
52 }
53 }
54
55 /**
56 * Adds or replaces a meta tag.
57 *
58 * @param string $identifier
59 * @param string $name
60 * @param string $value
61 * @param boolean $isProperty
62 */
63 public function addTag($identifier, $name, $value, $isProperty = false) {
64 if (!isset($this->objects[$identifier])) {
65 $this->indexToObject[] = $identifier;
66 }
67
68 $this->objects[$identifier] = [
69 'isProperty' => $isProperty,
70 'name' => $name,
71 'value' => $value
72 ];
73
74 // replace description if Open Graph Protocol tag was given
75 if ($name == 'og:description' && $value) {
76 $this->addTag('description', 'description', $value);
77 }
78 }
79
80 /**
81 * Removes a meta tag.
82 *
83 * @param string $identifier
84 */
85 public function removeTag($identifier) {
86 if (isset($this->objects[$identifier])) {
87 unset($this->objects[$identifier]);
88
89 $this->indexToObject = array_keys($this->objects);
90 }
91 }
92
93 /**
94 * @inheritDoc
95 */
96 public function count() {
97 return count($this->objects);
98 }
99
100 /**
101 * @inheritDoc
102 */
103 public function current() {
104 $tag = $this->objects[$this->indexToObject[$this->index]];
105
106 return '<meta ' . ($tag['isProperty'] ? 'property' : 'name') . '="' . $tag['name'] . '" content="' . StringUtil::encodeHTML($tag['value']) . '">';
107 }
108
109 /**
110 * CAUTION: This methods does not return the current iterator index,
111 * rather than the object key which maps to that index.
112 *
113 * @see \Iterator::key()
114 */
115 public function key() {
116 return $this->indexToObject[$this->index];
117 }
118
119 /**
120 * @inheritDoc
121 */
122 public function next() {
123 ++$this->index;
124 }
125
126 /**
127 * @inheritDoc
128 */
129 public function rewind() {
130 $this->index = 0;
131 }
132
133 /**
134 * @inheritDoc
135 */
136 public function valid() {
137 return isset($this->indexToObject[$this->index]);
138 }
139 }