Verzeichnisstruktur phpBB-3.1.0


Veröffentlicht
27.10.2014

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

php_exporter.php

Zuletzt modifiziert: 09.10.2024, 12:51 - Dateigröße: 16.72 KiB


 001  <?php
 002  /**
 003  *
 004  * This file is part of the phpBB Forum Software package.
 005  *
 006  * @copyright (c) phpBB Limited <https://www.phpbb.com>
 007  * @license GNU General Public License, version 2 (GPL-2.0)
 008  *
 009  * For full copyright and license information, please see
 010  * the docs/CREDITS.txt file.
 011  *
 012  */
 013   
 014  namespace phpbb\event;
 015   
 016  /**
 017  * Class php_exporter
 018  * Crawls through a list of files and grabs all php-events
 019  */
 020  class php_exporter
 021  {
 022      /** @var string Path where we look for files*/
 023      protected $path;
 024   
 025      /** @var string phpBB Root Path */
 026      protected $root_path;
 027   
 028      /** @var string */
 029      protected $current_file;
 030   
 031      /** @var string */
 032      protected $current_event;
 033   
 034      /** @var int */
 035      protected $current_event_line;
 036   
 037      /** @var array */
 038      protected $events;
 039   
 040      /** @var array */
 041      protected $file_lines;
 042   
 043      /**
 044      * @param string $phpbb_root_path
 045      * @param mixed $extension    String 'vendor/ext' to filter, null for phpBB core
 046      */
 047      public function __construct($phpbb_root_path, $extension = null)
 048      {
 049          $this->root_path = $phpbb_root_path;
 050          $this->path = $phpbb_root_path;
 051          $this->events = $this->file_lines = array();
 052          $this->current_file = $this->current_event = '';
 053          $this->current_event_line = 0;
 054   
 055          $this->path = $this->root_path;
 056          if ($extension)
 057          {
 058              $this->path .= 'ext/' . $extension . '/';
 059          }
 060      }
 061   
 062      /**
 063      * Get the list of all events
 064      *
 065      * @return array        Array with events: name => details
 066      */
 067      public function get_events()
 068      {
 069          return $this->events;
 070      }
 071   
 072      /**
 073      * Set current event data
 074      *
 075      * @param string    $name    Name of the current event (used for error messages)
 076      * @param int    $line    Line where the current event is placed in
 077      * @return null
 078      */
 079      public function set_current_event($name, $line)
 080      {
 081          $this->current_event = $name;
 082          $this->current_event_line = $line;
 083      }
 084   
 085      /**
 086      * Set the content of this file
 087      *
 088      * @param array $content        Array with the lines of the file
 089      * @return null
 090      */
 091      public function set_content($content)
 092      {
 093          $this->file_lines = $content;
 094      }
 095   
 096      /**
 097      * Crawl the phpBB/ directory for php events
 098      * @return int    The number of events found
 099      */
 100      public function crawl_phpbb_directory_php()
 101      {
 102          $files = $this->get_recursive_file_list();
 103          $this->events = array();
 104          foreach ($files as $file)
 105          {
 106              $this->crawl_php_file($file);
 107          }
 108          ksort($this->events);
 109   
 110          return sizeof($this->events);
 111      }
 112   
 113      /**
 114      * Returns a list of files in $dir
 115      *
 116      * @return    array    List of files (including the path)
 117      */
 118      public function get_recursive_file_list()
 119      {
 120          try
 121          {
 122              $iterator = new \RecursiveIteratorIterator(
 123                  new \phpbb\event\recursive_event_filter_iterator(
 124                      new \RecursiveDirectoryIterator(
 125                          $this->path,
 126                          \FilesystemIterator::SKIP_DOTS
 127                      ),
 128                      $this->path
 129                  ),
 130                  \RecursiveIteratorIterator::LEAVES_ONLY
 131              );
 132          }
 133          catch (\Exception $e)
 134          {
 135              return array();
 136          }
 137   
 138          $files = array();
 139          foreach ($iterator as $file_info)
 140          {
 141              /** @var \RecursiveDirectoryIterator $file_info */
 142              $relative_path = $iterator->getInnerIterator()->getSubPathname();
 143              $files[] = str_replace(DIRECTORY_SEPARATOR, '/', $relative_path);
 144          }
 145   
 146          return $files;
 147      }
 148   
 149      /**
 150      * Format the php events as a wiki table
 151      * @return string
 152      */
 153      public function export_events_for_wiki()
 154      {
 155          $wiki_page = '= PHP Events (Hook Locations) =' . "\n";
 156          $wiki_page .= '{| class="sortable zebra" cellspacing="0" cellpadding="5"' . "\n";
 157          $wiki_page .= '! Identifier !! Placement !! Arguments !! Added in Release !! Explanation' . "\n";
 158          foreach ($this->events as $event)
 159          {
 160              $wiki_page .= '|- id="' . $event['event'] . '"' . "\n";
 161              $wiki_page .= '| [[#' . $event['event'] . '|' . $event['event'] . ']] || ' . $event['file'] . ' || ' . implode(', ', $event['arguments']) . ' || ' . $event['since'] . ' || ' . $event['description'] . "\n";
 162          }
 163          $wiki_page .= '|}' . "\n";
 164   
 165          return $wiki_page;
 166      }
 167   
 168      /**
 169      * @param string $file
 170      * @return int Number of events found in this file
 171      * @throws \LogicException
 172      */
 173      public function crawl_php_file($file)
 174      {
 175          $this->current_file = $file;
 176          $this->file_lines = array();
 177          $content = file_get_contents($this->path . $this->current_file);
 178          $num_events_found = 0;
 179   
 180          if (strpos($content, "dispatcher->trigger_event('") || strpos($content, "dispatcher->dispatch('"))
 181          {
 182              $this->set_content(explode("\n", $content));
 183              for ($i = 0, $num_lines = sizeof($this->file_lines); $i < $num_lines; $i++)
 184              {
 185                  $event_line = false;
 186                  $found_trigger_event = strpos($this->file_lines[$i], "dispatcher->trigger_event('");
 187                  $arguments = array();
 188                  if ($found_trigger_event !== false)
 189                  {
 190                      $event_line = $i;
 191                      $this->set_current_event($this->get_event_name($event_line, false), $event_line);
 192   
 193                      // Find variables of the event
 194                      $arguments = $this->get_vars_from_array();
 195                      $doc_vars = $this->get_vars_from_docblock();
 196                      $this->validate_vars_docblock_array($arguments, $doc_vars);
 197                  }
 198                  else
 199                  {
 200                      $found_dispatch = strpos($this->file_lines[$i], "dispatcher->dispatch('");
 201                      if ($found_dispatch !== false)
 202                      {
 203                          $event_line = $i;
 204                          $this->set_current_event($this->get_event_name($event_line, true), $event_line);
 205                      }
 206                  }
 207   
 208                  if ($event_line)
 209                  {
 210                      // Validate @event
 211                      $event_line_num = $this->find_event();
 212                      $this->validate_event($this->current_event, $this->file_lines[$event_line_num]);
 213   
 214                      // Validate @since
 215                      $since_line_num = $this->find_since();
 216                      $since = $this->validate_since($this->file_lines[$since_line_num]);
 217   
 218                      // Find event description line
 219                      $description_line_num = $this->find_description();
 220                      $description = substr(trim($this->file_lines[$description_line_num]), strlen('* '));
 221   
 222                      if (isset($this->events[$this->current_event]))
 223                      {
 224                          throw new \LogicException("The event '{$this->current_event}' from file "
 225                              . "'{$this->current_file}:{$event_line_num}' already exists in file "
 226                              . "'{$this->events[$this->current_event]['file']}'", 10);
 227                      }
 228   
 229                      sort($arguments);
 230                      $this->events[$this->current_event] = array(
 231                          'event'            => $this->current_event,
 232                          'file'            => $this->current_file,
 233                          'arguments'        => $arguments,
 234                          'since'            => $since,
 235                          'description'    => $description,
 236                      );
 237                      $num_events_found++;
 238                  }
 239              }
 240          }
 241   
 242          return $num_events_found;
 243      }
 244   
 245      /**
 246      * Find the name of the event inside the dispatch() line
 247      *
 248      * @param int $event_line
 249      * @param bool $is_dispatch Do we look for dispatch() or trigger_event() ?
 250      * @return string    Name of the event
 251      * @throws \LogicException
 252      */
 253      public function get_event_name($event_line, $is_dispatch)
 254      {
 255          $event_text_line = $this->file_lines[$event_line];
 256          $event_text_line = ltrim($event_text_line, "\t ");
 257   
 258          if ($is_dispatch)
 259          {
 260              $regex = '#\$([a-z](?:[a-z0-9_]|->)*)';
 261              $regex .= '->dispatch\(';
 262              $regex .= '\'' . $this->preg_match_event_name() . '\'';
 263              $regex .= '\);#';
 264          }
 265          else
 266          {
 267              $regex = '#extract\(\$([a-z](?:[a-z0-9_]|->)*)';
 268              $regex .= '->trigger_event\(';
 269              $regex .= '\'' . $this->preg_match_event_name() . '\'';
 270              $regex .= ', compact\(\$vars\)\)\);#';
 271          }
 272   
 273          $match = array();
 274          preg_match($regex, $event_text_line, $match);
 275          if (!isset($match[2]))
 276          {
 277              throw new \LogicException("Can not find event name in line '{$event_text_line}' "
 278                  . "in file '{$this->current_file}:{$event_line}'", 1);
 279          }
 280   
 281          return $match[2];
 282      }
 283   
 284      /**
 285      * Returns a regex match for the event name
 286      *
 287      * @return string
 288      */
 289      protected function preg_match_event_name()
 290      {
 291          return '([a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*)+)';
 292      }
 293   
 294      /**
 295      * Find the $vars array
 296      *
 297      * @return array        List of variables
 298      * @throws \LogicException
 299      */
 300      public function get_vars_from_array()
 301      {
 302          $line = ltrim($this->file_lines[$this->current_event_line - 1], "\t");
 303          if ($line === ');')
 304          {
 305              $vars_array = $this->get_vars_from_multi_line_array();
 306          }
 307          else
 308          {
 309              $vars_array = $this->get_vars_from_single_line_array($line);
 310          }
 311   
 312          foreach ($vars_array as $var)
 313          {
 314              if (!preg_match('#^([a-zA-Z_][a-zA-Z0-9_]*)$#', $var))
 315              {
 316                  throw new \LogicException("Found invalid var '{$var}' in array for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 3);
 317              }
 318          }
 319   
 320          sort($vars_array);
 321          return $vars_array;
 322      }
 323   
 324      /**
 325      * Find the variables in single line array
 326      *
 327      * @param    string    $line
 328      * @param    bool    $throw_multiline    Throw an exception when there are too
 329      *                                        many arguments in one line.
 330      * @return array        List of variables
 331      * @throws \LogicException
 332      */
 333      public function get_vars_from_single_line_array($line, $throw_multiline = true)
 334      {
 335          $match = array();
 336          preg_match('#^\$vars = array\(\'([a-zA-Z0-9_\' ,]+)\'\);$#', $line, $match);
 337   
 338          if (isset($match[1]))
 339          {
 340              $vars_array = explode("', '", $match[1]);
 341              if ($throw_multiline && sizeof($vars_array) > 6)
 342              {
 343                  throw new \LogicException('Should use multiple lines for $vars definition '
 344                      . "for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 2);
 345              }
 346              return $vars_array;
 347          }
 348          else
 349          {
 350              throw new \LogicException("Can not find '\$vars = array();'-line for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 1);
 351          }
 352      }
 353   
 354      /**
 355      * Find the variables in single line array
 356      *
 357      * @return array        List of variables
 358      * @throws \LogicException
 359      */
 360      public function get_vars_from_multi_line_array()
 361      {
 362          $current_vars_line = 2;
 363          $var_lines = array();
 364          while (ltrim($this->file_lines[$this->current_event_line - $current_vars_line], "\t") !== '$vars = array(')
 365          {
 366              $var_lines[] = substr(trim($this->file_lines[$this->current_event_line - $current_vars_line]), 0, -1);
 367   
 368              $current_vars_line++;
 369              if ($current_vars_line > $this->current_event_line)
 370              {
 371                  // Reached the start of the file
 372                  throw new \LogicException("Can not find end of \$vars array for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 2);
 373              }
 374          }
 375   
 376          return $this->get_vars_from_single_line_array('$vars = array(' . implode(", ", $var_lines) . ');', false);
 377      }
 378   
 379      /**
 380      * Find the $vars array
 381      *
 382      * @return array        List of variables
 383      * @throws \LogicException
 384      */
 385      public function get_vars_from_docblock()
 386      {
 387          $doc_vars = array();
 388          $current_doc_line = 1;
 389          $found_comment_end = false;
 390          while (ltrim($this->file_lines[$this->current_event_line - $current_doc_line], "\t") !== '/**')
 391          {
 392              if (ltrim($this->file_lines[$this->current_event_line - $current_doc_line], "\t ") === '*/')
 393              {
 394                  $found_comment_end = true;
 395              }
 396   
 397              if ($found_comment_end)
 398              {
 399                  $var_line = trim($this->file_lines[$this->current_event_line - $current_doc_line]);
 400                  $var_line = preg_replace('!\s+!', ' ', $var_line);
 401                  if (strpos($var_line, '* @var ') === 0)
 402                  {
 403                      $doc_line = explode(' ', $var_line, 5);
 404                      if (sizeof($doc_line) !== 5)
 405                      {
 406                          throw new \LogicException("Found invalid line '{$this->file_lines[$this->current_event_line - $current_doc_line]}' "
 407                          . "for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 1);
 408                      }
 409                      $doc_vars[] = $doc_line[3];
 410                  }
 411              }
 412   
 413              $current_doc_line++;
 414              if ($current_doc_line > $this->current_event_line)
 415              {
 416                  // Reached the start of the file
 417                  throw new \LogicException("Can not find end of docblock for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 2);
 418              }
 419          }
 420   
 421          if (empty($doc_vars))
 422          {
 423              // Reached the start of the file
 424              throw new \LogicException("Can not find @var lines for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 3);
 425          }
 426   
 427          foreach ($doc_vars as $var)
 428          {
 429              if (!preg_match('#^([a-zA-Z_][a-zA-Z0-9_]*)$#', $var))
 430              {
 431                  throw new \LogicException("Found invalid @var '{$var}' in docblock for event "
 432                      . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 4);
 433              }
 434          }
 435   
 436          sort($doc_vars);
 437          return $doc_vars;
 438      }
 439   
 440      /**
 441      * Find the "@since" Information line
 442      *
 443      * @return int Absolute line number
 444      * @throws \LogicException
 445      */
 446      public function find_since()
 447      {
 448          return $this->find_tag('since', array('event', 'var'));
 449      }
 450   
 451      /**
 452      * Find the "@event" Information line
 453      *
 454      * @return int Absolute line number
 455      */
 456      public function find_event()
 457      {
 458          return $this->find_tag('event', array());
 459      }
 460   
 461      /**
 462      * Find a "@*" Information line
 463      *
 464      * @param string $find_tag        Name of the tag we are trying to find
 465      * @param array $disallowed_tags        List of tags that must not appear between
 466      *                                    the tag and the actual event
 467      * @return int Absolute line number
 468      * @throws \LogicException
 469      */
 470      public function find_tag($find_tag, $disallowed_tags)
 471      {
 472          $find_tag_line = 0;
 473          $found_comment_end = false;
 474          while (strpos(ltrim($this->file_lines[$this->current_event_line - $find_tag_line], "\t "), '* @' . $find_tag . ' ') !== 0)
 475          {
 476              if ($found_comment_end && ltrim($this->file_lines[$this->current_event_line - $find_tag_line], "\t") === '/**')
 477              {
 478                  // Reached the start of this doc block
 479                  throw new \LogicException("Can not find '@{$find_tag}' information for event "
 480                      . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 1);
 481              }
 482   
 483              foreach ($disallowed_tags as $disallowed_tag)
 484              {
 485                  if ($found_comment_end && strpos(ltrim($this->file_lines[$this->current_event_line - $find_tag_line], "\t "), '* @' . $disallowed_tag) === 0)
 486                  {
 487                      // Found @var after the @since
 488                      throw new \LogicException("Found '@{$disallowed_tag}' information after '@{$find_tag}' for event "
 489                          . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 3);
 490                  }
 491              }
 492   
 493              if (ltrim($this->file_lines[$this->current_event_line - $find_tag_line], "\t ") === '*/')
 494              {
 495                  $found_comment_end = true;
 496              }
 497   
 498              $find_tag_line++;
 499              if ($find_tag_line >= $this->current_event_line)
 500              {
 501                  // Reached the start of the file
 502                  throw new \LogicException("Can not find '@{$find_tag}' information for event "
 503                      . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 2);
 504              }
 505          }
 506   
 507          return $this->current_event_line - $find_tag_line;
 508      }
 509   
 510      /**
 511      * Find a "@*" Information line
 512      *
 513      * @return int Absolute line number
 514      * @throws \LogicException
 515      */
 516      public function find_description()
 517      {
 518          $find_desc_line = 0;
 519          while (ltrim($this->file_lines[$this->current_event_line - $find_desc_line], "\t") !== '/**')
 520          {
 521              $find_desc_line++;
 522              if ($find_desc_line > $this->current_event_line)
 523              {
 524                  // Reached the start of the file
 525                  throw new \LogicException("Can not find a description for event "
 526                      . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 1);
 527              }
 528          }
 529   
 530          $find_desc_line = $this->current_event_line - $find_desc_line + 1;
 531   
 532          $desc = trim($this->file_lines[$find_desc_line]);
 533          if (strpos($desc, '* @') === 0 || $desc[0] !== '*' || substr($desc, 1) == '')
 534          {
 535              // First line of the doc block is a @-line, empty or only contains "*"
 536              throw new \LogicException("Can not find a description for event "
 537                  . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 2);
 538          }
 539   
 540          return $find_desc_line;
 541      }
 542   
 543      /**
 544      * Validate "@since" Information
 545      *
 546      * @param string $line
 547      * @return string
 548      * @throws \LogicException
 549      */
 550      public function validate_since($line)
 551      {
 552          $match = array();
 553          preg_match('#^\* @since (\d+\.\d+\.\d+(?:-(?:a|b|RC|pl)\d+)?)$#', ltrim($line, "\t "), $match);
 554          if (!isset($match[1]))
 555          {
 556              throw new \LogicException("Invalid '@since' information for event "
 557                  . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'");
 558          }
 559   
 560          return $match[1];
 561      }
 562   
 563      /**
 564      * Validate "@event" Information
 565      *
 566      * @param string $event_name
 567      * @param string $line
 568      * @return string
 569      * @throws \LogicException
 570      */
 571      public function validate_event($event_name, $line)
 572      {
 573          $event = substr(ltrim($line, "\t "), strlen('* @event '));
 574   
 575          if ($event !== trim($event))
 576          {
 577              throw new \LogicException("Invalid '@event' information for event "
 578                  . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 1);
 579          }
 580   
 581          if ($event !== $event_name)
 582          {
 583              throw new \LogicException("Event name does not match '@event' tag for event "
 584                  . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 2);
 585          }
 586   
 587          return $event;
 588      }
 589   
 590      /**
 591      * Validates that two arrays contain the same strings
 592      *
 593      * @param array $vars_array        Variables found in the array line
 594      * @param array $vars_docblock    Variables found in the doc block
 595      * @return null
 596      * @throws \LogicException
 597      */
 598      public function validate_vars_docblock_array($vars_array, $vars_docblock)
 599      {
 600          $vars_array = array_unique($vars_array);
 601          $vars_docblock = array_unique($vars_docblock);
 602          $sizeof_vars_array = sizeof($vars_array);
 603   
 604          if ($sizeof_vars_array !== sizeof($vars_docblock) || $sizeof_vars_array !== sizeof(array_intersect($vars_array, $vars_docblock)))
 605          {
 606              throw new \LogicException("\$vars array does not match the list of '@var' tags for event "
 607                  . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'");
 608          }
 609      }
 610  }
 611