Verzeichnisstruktur phpBB-3.3.15
- Veröffentlicht
- 28.08.2024
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
Configurator.php
001 <?php
002
003 /**
004 * @package s9e\TextFormatter
005 * @copyright Copyright (c) 2010-2022 The s9e authors
006 * @license http://www.opensource.org/licenses/mit-license.php The MIT License
007 */
008 namespace s9e\TextFormatter\Plugins\Emoticons;
009
010 use ArrayAccess;
011 use Countable;
012 use Iterator;
013 use s9e\TextFormatter\Configurator\Helpers\ConfigHelper;
014 use s9e\TextFormatter\Configurator\Helpers\RegexpBuilder;
015 use s9e\TextFormatter\Configurator\Items\Regexp;
016 use s9e\TextFormatter\Configurator\JavaScript\RegexpConvertor;
017 use s9e\TextFormatter\Configurator\Traits\CollectionProxy;
018 use s9e\TextFormatter\Plugins\ConfiguratorBase;
019 use s9e\TextFormatter\Plugins\Emoticons\Configurator\EmoticonCollection;
020 use s9e\TextFormatter\Utils\XPath;
021
022 /**
023 * @method mixed add(string $key, mixed $value) Add an item to this collection
024 * @method array asConfig()
025 * @method void clear() Empty this collection
026 * @method bool contains(mixed $value) Test whether a given value is present in this collection
027 * @method integer count()
028 * @method mixed current()
029 * @method void delete(string $key) Delete an item from this collection
030 * @method bool exists(string $key) Test whether an item of given key exists
031 * @method mixed get(string $key) Return a value from this collection
032 * @method mixed indexOf(mixed $value) Find the index of a given value
033 * @method integer|string key()
034 * @method mixed next()
035 * @method string normalizeKey(string $key) Normalize an item's key
036 * @method string normalizeValue(string $value) Normalize an emoticon's template
037 * @method bool offsetExists(string|integer $offset)
038 * @method mixed offsetGet(string|integer $offset)
039 * @method void offsetSet(string|integer $offset, mixed $value)
040 * @method void offsetUnset(string|integer $offset)
041 * @method string onDuplicate(string|null $action) Query and set the action to take when add() is called with a key that already exists
042 * @method void rewind()
043 * @method mixed set(string $key, mixed $value) Set and overwrite a value in this collection
044 * @method bool valid()
045 */
046 class Configurator extends ConfiguratorBase implements ArrayAccess, Countable, Iterator
047 {
048 use CollectionProxy;
049
050 /**
051 * @var EmoticonCollection
052 */
053 protected $collection;
054
055 /**
056 * @var string PCRE subpattern used in a negative lookbehind assertion before the emoticons
057 */
058 public $notAfter = '';
059
060 /**
061 * @var string PCRE subpattern used in a negative lookahead assertion after the emoticons
062 */
063 public $notBefore = '';
064
065 /**
066 * @var string XPath expression that, if true, forces emoticons to be rendered as text
067 */
068 public $notIfCondition;
069
070 /**
071 * {@inheritdoc}
072 */
073 protected $onDuplicateAction = 'replace';
074
075 /**
076 * @var string Name of the tag used by this plugin
077 */
078 protected $tagName = 'E';
079
080 /**
081 * Plugin's setup
082 *
083 * Will create the tag used by this plugin
084 */
085 protected function setUp()
086 {
087 $this->collection = new EmoticonCollection;
088
089 if (!$this->configurator->tags->exists($this->tagName))
090 {
091 $this->configurator->tags->add($this->tagName);
092 }
093 }
094
095 /**
096 * Create the template used for emoticons
097 *
098 * @return void
099 */
100 public function finalize()
101 {
102 $tag = $this->getTag();
103
104 if (!isset($tag->template))
105 {
106 $tag->template = $this->getTemplate();
107 }
108 }
109
110 /**
111 * @return array
112 */
113 public function asConfig()
114 {
115 if (!count($this->collection))
116 {
117 return;
118 }
119
120 // Grab the emoticons from the collection
121 $codes = array_keys(iterator_to_array($this->collection));
122
123 // Build the regexp used to match emoticons
124 $regexp = '/';
125
126 if ($this->notAfter !== '')
127 {
128 $regexp .= '(?<!' . $this->notAfter . ')';
129 }
130
131 $regexp .= RegexpBuilder::fromList($codes);
132
133 if ($this->notBefore !== '')
134 {
135 $regexp .= '(?!' . $this->notBefore . ')';
136 }
137
138 $regexp .= '/S';
139
140 // Set the Unicode mode if Unicode properties are used
141 if (preg_match('/\\\\[pP](?>\\{\\^?\\w+\\}|\\w\\w?)/', $regexp))
142 {
143 $regexp .= 'u';
144 }
145
146 // Force the regexp to use atomic grouping for performance
147 $regexp = preg_replace('/(?<!\\\\)((?>\\\\\\\\)*)\\(\\?:/', '$1(?>', $regexp);
148
149 // Prepare the config array
150 $config = [
151 'quickMatch' => $this->quickMatch,
152 'regexp' => $regexp,
153 'tagName' => $this->tagName
154 ];
155
156 // If notAfter is used, we need to create a JavaScript-specific regexp that does not use a
157 // lookbehind assertion, and we add the notAfter subpattern to the config as a variant
158 if ($this->notAfter !== '')
159 {
160 // Skip the first assertion by skipping the first N characters, where N equals the
161 // length of $this->notAfter plus 1 for the first "/" and 5 for "(?<!)"
162 $lpos = 6 + strlen($this->notAfter);
163 $rpos = strrpos($regexp, '/');
164 $jsRegexp = RegexpConvertor::toJS('/' . substr($regexp, $lpos, $rpos - $lpos) . '/', true);
165
166 $config['regexp'] = new Regexp($regexp);
167 $config['regexp']->setJS($jsRegexp);
168
169 $config['notAfter'] = new Regexp('/' . $this->notAfter . '/');
170 }
171
172 // Try to find a quickMatch if none is set
173 if ($this->quickMatch === false)
174 {
175 $config['quickMatch'] = ConfigHelper::generateQuickMatchFromList($codes);
176 }
177
178 return $config;
179 }
180
181 /**
182 * {@inheritdoc}
183 */
184 public function getJSHints()
185 {
186 return ['EMOTICONS_NOT_AFTER' => (int) !empty($this->notAfter)];
187 }
188
189 /**
190 * Generate the dynamic template that renders all emoticons
191 *
192 * @return string
193 */
194 public function getTemplate()
195 {
196 // Build the <xsl:choose> node
197 $xsl = '<xsl:choose>';
198
199 // First, test whether the emoticon should be rendered as text if applicable
200 if (!empty($this->notIfCondition))
201 {
202 $xsl .= '<xsl:when test="' . htmlspecialchars($this->notIfCondition, ENT_COMPAT) . '">'
203 . '<xsl:value-of select="."/>'
204 . '</xsl:when>'
205 . '<xsl:otherwise>'
206 . '<xsl:choose>';
207 }
208
209 // Iterate over codes, create an <xsl:when> for each emote
210 foreach ($this->collection as $code => $template)
211 {
212 $xsl .= '<xsl:when test=".=' . htmlspecialchars(XPath::export($code), ENT_COMPAT) . '">'
213 . $template
214 . '</xsl:when>';
215 }
216
217 // Finish it with an <xsl:otherwise> that displays the unknown codes as text
218 $xsl .= '<xsl:otherwise><xsl:value-of select="."/></xsl:otherwise>';
219
220 // Close the emote switch
221 $xsl .= '</xsl:choose>';
222
223 // Close the "notIf" condition if applicable
224 if (!empty($this->notIfCondition))
225 {
226 $xsl .= '</xsl:otherwise></xsl:choose>';
227 }
228
229 return $xsl;
230 }
231 }