[ Index ] |
PHP Cross Reference of phpBB-3.3.14-deutsch |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * @package s9e\TextFormatter 5 * @copyright Copyright (c) 2010-2022 The s9e authors 6 * @license http://www.opensource.org/licenses/mit-license.php The MIT License 7 */ 8 namespace s9e\TextFormatter\Plugins\MediaEmbed; 9 10 use InvalidArgumentException; 11 use RuntimeException; 12 use s9e\TextFormatter\Configurator\Helpers\FilterHelper; 13 use s9e\TextFormatter\Configurator\Items\Regexp; 14 use s9e\TextFormatter\Configurator\Items\Tag; 15 use s9e\TextFormatter\Configurator\JavaScript\Dictionary; 16 use s9e\TextFormatter\Plugins\ConfiguratorBase; 17 use s9e\TextFormatter\Plugins\MediaEmbed\Configurator\Collections\CachedDefinitionCollection; 18 use s9e\TextFormatter\Plugins\MediaEmbed\Configurator\TemplateBuilder; 19 20 class Configurator extends ConfiguratorBase 21 { 22 /** 23 * @var array List of filters that are explicitly allowed in attribute definitions 24 */ 25 public $allowedFilters = ['htmlspecialchars_decode', 'stripslashes', 'urldecode']; 26 27 /** 28 * @var bool Whether to create the MEDIA BBCode 29 */ 30 protected $createMediaBBCode = true; 31 32 /** 33 * @var Configurator\Collections\SiteDefinitionCollection Default sites 34 */ 35 public $defaultSites; 36 37 /** 38 * {@inheritdoc} 39 */ 40 protected $quickMatch = '://'; 41 42 /** 43 * {@inheritdoc} 44 */ 45 protected $regexp = '/\\bhttps?:\\/\\/[^["\'\\s]+/Si'; 46 47 /** 48 * @var array Configured sites 49 */ 50 protected $sites = []; 51 52 /** 53 * @var string Name of the tag used to handle embeddable URLs 54 */ 55 protected $tagName = 'MEDIA'; 56 57 /** 58 * @var TemplateBuilder 59 */ 60 protected $templateBuilder; 61 62 /** 63 * {@inheritdoc} 64 */ 65 protected function setUp() 66 { 67 $this->defaultSites = new CachedDefinitionCollection; 68 $this->templateBuilder = new TemplateBuilder; 69 70 $this->configurator->registeredVars['MediaEmbed.hosts'] = new Dictionary; 71 $this->configurator->registeredVars['MediaEmbed.sites'] = new Dictionary; 72 73 // Create a MEDIA tag 74 $this->createMediaTag(); 75 76 // Create a [MEDIA] BBCode if applicable 77 if ($this->createMediaBBCode) 78 { 79 $this->configurator->BBCodes->set($this->tagName, ['contentAttributes' => ['url']]); 80 } 81 } 82 83 /** 84 * {@inheritdoc} 85 */ 86 public function asConfig() 87 { 88 if (empty($this->sites)) 89 { 90 return; 91 } 92 93 return [ 94 'quickMatch' => $this->quickMatch, 95 'regexp' => $this->regexp, 96 'tagName' => $this->tagName 97 ]; 98 } 99 100 /** 101 * Add a media site 102 * 103 * @param string $siteId Site's ID 104 * @param array $siteConfig Site's config 105 * @return Tag Tag created for this site 106 */ 107 public function add($siteId, array $siteConfig = null) 108 { 109 // Normalize or retrieve the site definition 110 $siteId = $this->normalizeId($siteId); 111 if (isset($siteConfig)) 112 { 113 $siteConfig = $this->defaultSites->normalizeValue($siteConfig); 114 } 115 else 116 { 117 $siteConfig = $this->defaultSites->get($siteId); 118 } 119 $siteConfig['extract'] = $this->convertRegexps($siteConfig['extract']); 120 $siteConfig['scrape'] = $this->convertScrapes($siteConfig['scrape']); 121 122 // Check the safety of attribute filters 123 $this->checkAttributeFilters($siteConfig['attributes']); 124 125 // Create the tag for this site 126 $tag = $this->addTag($siteId, $siteConfig); 127 128 // Update the configurator's data 129 $this->sites[$siteId] = $siteConfig; 130 foreach ($siteConfig['host'] as $host) 131 { 132 $this->configurator->registeredVars['MediaEmbed.hosts'][$host] = $siteId; 133 } 134 $this->configurator->registeredVars['MediaEmbed.sites'][$siteId] = [$siteConfig['extract'], $siteConfig['scrape']]; 135 136 return $tag; 137 } 138 139 /** 140 * Return the list of configured sites 141 * 142 * @return array Site's ID as keys, site's config as values 143 */ 144 public function getSites() 145 { 146 return $this->sites; 147 } 148 149 /** 150 * Create and return a tag that handles given media site 151 * 152 * @param string $siteId 153 * @param array $siteConfig 154 * @return Tag 155 */ 156 protected function addTag($siteId, array $siteConfig) 157 { 158 $tag = new Tag([ 159 'attributes' => $this->getAttributesConfig($siteConfig), 160 'rules' => [ 161 'allowChild' => 'URL', 162 'autoClose' => true, 163 'denyChild' => [$siteId, $this->tagName] 164 ], 165 'template' => $this->templateBuilder->build($siteId, $siteConfig) 166 ]); 167 168 $this->configurator->templateNormalizer->normalizeTag($tag); 169 $this->configurator->templateChecker->checkTag($tag); 170 $this->configurator->tags->add($siteId, $tag); 171 172 return $tag; 173 } 174 175 /** 176 * Check the safety of given attributes 177 * 178 * @param array $attributes 179 * @return void 180 */ 181 protected function checkAttributeFilters(array $attributes) 182 { 183 foreach ($attributes as $attrConfig) 184 { 185 if (empty($attrConfig['filterChain'])) 186 { 187 continue; 188 } 189 foreach ($attrConfig['filterChain'] as $filter) 190 { 191 if (!FilterHelper::isAllowed($filter, $this->allowedFilters)) 192 { 193 throw new RuntimeException("Filter '$filter' is not allowed in media sites"); 194 } 195 } 196 } 197 } 198 199 /** 200 * Convert given regexp to a [regexp, map] pair 201 * 202 * @param string $regexp Original regexp 203 * @return array [regexp, [list of captures' names]] 204 */ 205 protected function convertRegexp($regexp) 206 { 207 $regexp = new Regexp($regexp); 208 209 return [$regexp, $regexp->getCaptureNames()]; 210 } 211 212 /** 213 * Convert a list of regexps 214 * 215 * @param string[] $regexps Original list 216 * @return array[] Converted list 217 */ 218 protected function convertRegexps(array $regexps) 219 { 220 return array_map([$this, 'convertRegexp'], $regexps); 221 } 222 223 /** 224 * Convert all regexps in a scraping config 225 * 226 * @param array $config Original config 227 * @return array Converted config 228 */ 229 protected function convertScrapeConfig(array $config) 230 { 231 $config['extract'] = $this->convertRegexps($config['extract']); 232 $config['match'] = $this->convertRegexps($config['match']); 233 234 return $config; 235 } 236 237 /** 238 * Convert all regexps in a list of scraping configs 239 * 240 * @param array[] $scrapes Original config 241 * @return array[] Converted config 242 */ 243 protected function convertScrapes(array $scrapes) 244 { 245 return array_map([$this, 'convertScrapeConfig'], $scrapes); 246 } 247 248 /** 249 * Create the default MEDIA tag 250 * 251 * @return void 252 */ 253 protected function createMediaTag() 254 { 255 $tag = $this->configurator->tags->add($this->tagName); 256 257 // This tag should not need to be closed and should not contain itself 258 $tag->rules->autoClose(); 259 $tag->rules->denyChild($this->tagName); 260 261 // Empty this tag's filter chain and add our tag filter 262 $tag->filterChain->clear(); 263 $tag->filterChain 264 ->append(__NAMESPACE__ . '\\Parser::filterTag') 265 ->resetParameters() 266 ->addParameterByName('tag') 267 ->addParameterByName('parser') 268 ->addParameterByName('MediaEmbed.hosts') 269 ->addParameterByName('MediaEmbed.sites') 270 ->addParameterByName('cacheDir') 271 ->setJS(file_get_contents(__DIR__ . '/Parser/tagFilter.js')); 272 } 273 274 /** 275 * Return the list of named captures from a list of [regexp, map] pairs 276 * 277 * @param array[] $regexps List of [regexp, map] pairs 278 * @return string[] 279 */ 280 protected function getAttributeNamesFromRegexps(array $regexps) 281 { 282 $attrNames = []; 283 foreach ($regexps as list($regexp, $map)) 284 { 285 $attrNames += array_flip(array_filter($map)); 286 } 287 288 return $attrNames; 289 } 290 291 /** 292 * Get the attributes config for given site config 293 * 294 * @param array $siteConfig Site's config 295 * @return array Map of [attrName => attrConfig] 296 */ 297 protected function getAttributesConfig(array $siteConfig) 298 { 299 $attrNames = $this->getAttributeNamesFromRegexps($siteConfig['extract']); 300 foreach ($siteConfig['scrape'] as $scrapeConfig) 301 { 302 $attrNames += $this->getAttributeNamesFromRegexps($scrapeConfig['extract']); 303 } 304 305 $attributes = $siteConfig['attributes'] + array_fill_keys(array_keys($attrNames), []); 306 foreach ($attributes as &$attrConfig) 307 { 308 $attrConfig += ['required' => false]; 309 } 310 unset($attrConfig); 311 312 return $attributes; 313 } 314 315 /** 316 * Validate and normalize a site ID 317 * 318 * @param string $siteId 319 * @return string 320 */ 321 protected function normalizeId($siteId) 322 { 323 $siteId = strtolower($siteId); 324 325 if (!preg_match('(^[a-z0-9]+$)', $siteId)) 326 { 327 throw new InvalidArgumentException('Invalid site ID'); 328 } 329 330 return $siteId; 331 } 332 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Nov 25 19:05:08 2024 | Cross-referenced by PHPXref 0.7.1 |