Verzeichnisstruktur phpBB-3.3.16


Veröffentlicht
27.04.2026

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.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

RulesHelper.php

Zuletzt modifiziert: 01.05.2026, 11:28 - Dateigröße: 6.84 KiB


 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\Configurator\Helpers;
 009   
 010  use s9e\TextFormatter\Configurator\Collections\Ruleset;
 011  use s9e\TextFormatter\Configurator\Collections\TagCollection;
 012   
 013  abstract class RulesHelper
 014  {
 015      /**
 016      * Generate the allowedChildren and allowedDescendants bitfields for every tag and for the root context
 017      *
 018      * @param  TagCollection $tags
 019      * @param  Ruleset       $rootRules
 020      * @return array
 021      */
 022      public static function getBitfields(TagCollection $tags, Ruleset $rootRules)
 023      {
 024          $rules = ['*root*' => iterator_to_array($rootRules)];
 025          foreach ($tags as $tagName => $tag)
 026          {
 027              $rules[$tagName] = iterator_to_array($tag->rules);
 028          }
 029   
 030          // Create a matrix that contains all of the tags and whether every other tag is allowed as
 031          // a child and as a descendant
 032          $matrix = self::unrollRules($rules);
 033   
 034          // Remove unusable tags from the matrix
 035          self::pruneMatrix($matrix);
 036   
 037          // Group together tags are allowed in the exact same contexts
 038          $groupedTags = [];
 039          foreach (array_keys($matrix) as $tagName)
 040          {
 041              if ($tagName === '*root*')
 042              {
 043                  continue;
 044              }
 045   
 046              $k = '';
 047              foreach ($matrix as $tagMatrix)
 048              {
 049                  $k .= $tagMatrix['allowedChildren'][$tagName];
 050                  $k .= $tagMatrix['allowedDescendants'][$tagName];
 051              }
 052   
 053              $groupedTags[$k][] = $tagName;
 054          }
 055   
 056          // Record the bit number of each tag, and the name of a tag for each bit
 057          $bitTag     = [];
 058          $bitNumber  = 0;
 059          $tagsConfig = [];
 060          foreach ($groupedTags as $tagNames)
 061          {
 062              foreach ($tagNames as $tagName)
 063              {
 064                  $tagsConfig[$tagName]['bitNumber'] = $bitNumber;
 065                  $bitTag[$bitNumber] = $tagName;
 066              }
 067   
 068              ++$bitNumber;
 069          }
 070   
 071          // Build the bitfields of each tag, including the *root* pseudo-tag
 072          foreach ($matrix as $tagName => $tagMatrix)
 073          {
 074              $allowedChildren    = '';
 075              $allowedDescendants = '';
 076              foreach ($bitTag as $targetName)
 077              {
 078                  $allowedChildren    .= $tagMatrix['allowedChildren'][$targetName];
 079                  $allowedDescendants .= $tagMatrix['allowedDescendants'][$targetName];
 080              }
 081   
 082              $tagsConfig[$tagName]['allowed'] = self::pack($allowedChildren, $allowedDescendants);
 083          }
 084   
 085          // Prepare the return value
 086          $return = [
 087              'root' => $tagsConfig['*root*'],
 088              'tags' => $tagsConfig
 089          ];
 090          unset($return['tags']['*root*']);
 091   
 092          return $return;
 093      }
 094   
 095      /**
 096      * Initialize a matrix of settings
 097      *
 098      * @param  array $rules Rules for each tag
 099      * @return array        Multidimensional array of [tagName => [scope => [targetName => setting]]]
 100      */
 101      protected static function initMatrix(array $rules)
 102      {
 103          $matrix   = [];
 104          $tagNames = array_keys($rules);
 105   
 106          foreach ($rules as $tagName => $tagRules)
 107          {
 108              $matrix[$tagName]['allowedChildren']    = array_fill_keys($tagNames, 0);
 109              $matrix[$tagName]['allowedDescendants'] = array_fill_keys($tagNames, 0);
 110          }
 111   
 112          return $matrix;
 113      }
 114   
 115      /**
 116      * Apply given rule from each applicable tag
 117      *
 118      * For each tag, if the rule has any target we set the corresponding value for each target in the
 119      * matrix
 120      *
 121      * @param  array  &$matrix   Settings matrix
 122      * @param  array   $rules    Rules for each tag
 123      * @param  string  $ruleName Rule name
 124      * @param  string  $key      Key in the matrix
 125      * @param  integer $value    Value to be set
 126      * @return void
 127      */
 128      protected static function applyTargetedRule(array &$matrix, $rules, $ruleName, $key, $value)
 129      {
 130          foreach ($rules as $tagName => $tagRules)
 131          {
 132              if (!isset($tagRules[$ruleName]))
 133              {
 134                  continue;
 135              }
 136   
 137              foreach ($tagRules[$ruleName] as $targetName)
 138              {
 139                  $matrix[$tagName][$key][$targetName] = $value;
 140              }
 141          }
 142      }
 143   
 144      /**
 145      * @param  array $rules
 146      * @return array
 147      */
 148      protected static function unrollRules(array $rules)
 149      {
 150          // Initialize the matrix with default values
 151          $matrix = self::initMatrix($rules);
 152   
 153          // Convert ignoreTags and requireParent to denyDescendant and denyChild rules
 154          $tagNames = array_keys($rules);
 155          foreach ($rules as $tagName => $tagRules)
 156          {
 157              if (!empty($tagRules['ignoreTags']))
 158              {
 159                  $rules[$tagName]['denyChild']      = $tagNames;
 160                  $rules[$tagName]['denyDescendant'] = $tagNames;
 161              }
 162   
 163              if (!empty($tagRules['requireParent']))
 164              {
 165                  $denyParents = array_diff($tagNames, $tagRules['requireParent']);
 166                  foreach ($denyParents as $parentName)
 167                  {
 168                      $rules[$parentName]['denyChild'][] = $tagName;
 169                  }
 170              }
 171          }
 172   
 173          // Apply "allow" rules to grant usage, overwriting the default settings
 174          self::applyTargetedRule($matrix, $rules, 'allowChild',      'allowedChildren',    1);
 175          self::applyTargetedRule($matrix, $rules, 'allowDescendant', 'allowedDescendants', 1);
 176   
 177          // Apply "deny" rules to remove usage
 178          self::applyTargetedRule($matrix, $rules, 'denyChild',      'allowedChildren',    0);
 179          self::applyTargetedRule($matrix, $rules, 'denyDescendant', 'allowedDescendants', 0);
 180   
 181          return $matrix;
 182      }
 183   
 184      /**
 185      * Remove unusable tags from the matrix
 186      *
 187      * @param  array &$matrix
 188      * @return void
 189      */
 190      protected static function pruneMatrix(array &$matrix)
 191      {
 192          $usableTags = ['*root*' => 1];
 193   
 194          // Start from the root and keep digging
 195          $parentTags = $usableTags;
 196          do
 197          {
 198              $nextTags = [];
 199              foreach (array_keys($parentTags) as $tagName)
 200              {
 201                  // Accumulate the names of tags that are allowed as children of our parent tags
 202                  $nextTags += array_filter($matrix[$tagName]['allowedChildren']);
 203              }
 204   
 205              // Keep only the tags that are in the matrix but aren't in the usable array yet, then
 206              // add them to the array
 207              $parentTags  = array_diff_key($nextTags, $usableTags);
 208              $parentTags  = array_intersect_key($parentTags, $matrix);
 209              $usableTags += $parentTags;
 210          }
 211          while (!empty($parentTags));
 212   
 213          // Remove unusable tags from the matrix
 214          $matrix = array_intersect_key($matrix, $usableTags);
 215          unset($usableTags['*root*']);
 216   
 217          // Remove unusable tags from the targets
 218          foreach ($matrix as $tagName => &$tagMatrix)
 219          {
 220              $tagMatrix['allowedChildren']
 221                  = array_intersect_key($tagMatrix['allowedChildren'], $usableTags);
 222   
 223              $tagMatrix['allowedDescendants']
 224                  = array_intersect_key($tagMatrix['allowedDescendants'], $usableTags);
 225          }
 226          unset($tagMatrix);
 227      }
 228   
 229      /**
 230      * Convert a binary representation such as "101011" to an array of integer
 231      *
 232      * Each bitfield is split in groups of 8 bits, then converted to a 16-bit integer where the
 233      * allowedChildren bitfield occupies the least significant bits and the allowedDescendants
 234      * bitfield occupies the most significant bits
 235      *
 236      * @param  string    $allowedChildren
 237      * @param  string    $allowedDescendants
 238      * @return integer[]
 239      */
 240      protected static function pack($allowedChildren, $allowedDescendants)
 241      {
 242          $allowedChildren    = str_split($allowedChildren,    8);
 243          $allowedDescendants = str_split($allowedDescendants, 8);
 244   
 245          $allowed = [];
 246          foreach (array_keys($allowedChildren) as $k)
 247          {
 248              $allowed[] = bindec(sprintf(
 249                  '%1$08s%2$08s',
 250                  strrev($allowedDescendants[$k]),
 251                  strrev($allowedChildren[$k])
 252              ));
 253          }
 254   
 255          return $allowed;
 256      }
 257  }