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

md_exporter.php

Zuletzt modifiziert: 09.10.2024, 12:51 - Dateigröße: 10.79 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  * Crawls through a markdown file and grabs all events
 018  */
 019  class md_exporter
 020  {
 021      /** @var string Path where we look for files*/
 022      protected $path;
 023   
 024      /** @var string phpBB Root Path */
 025      protected $root_path;
 026   
 027      /** @var string */
 028      protected $filter;
 029   
 030      /** @var string */
 031      protected $current_event;
 032   
 033      /** @var array */
 034      protected $events;
 035   
 036      /**
 037      * @param string $phpbb_root_path
 038      * @param mixed $extension    String 'vendor/ext' to filter, null for phpBB core
 039      */
 040      public function __construct($phpbb_root_path, $extension = null)
 041      {
 042          $this->root_path = $phpbb_root_path;
 043          $this->path = $this->root_path;
 044          if ($extension)
 045          {
 046              $this->path .= 'ext/' . $extension . '/';
 047          }
 048   
 049          $this->events = array();
 050          $this->events_by_file = array();
 051          $this->filter = $this->current_event = '';
 052      }
 053   
 054      /**
 055      * Get the list of all events
 056      *
 057      * @return array        Array with events: name => details
 058      */
 059      public function get_events()
 060      {
 061          return $this->events;
 062      }
 063   
 064      /**
 065      * @param string $md_file    Relative from phpBB root
 066      * @return int        Number of events found
 067      * @throws \LogicException
 068      */
 069      public function crawl_phpbb_directory_adm($md_file)
 070      {
 071          $this->crawl_eventsmd($md_file, 'adm');
 072   
 073          $file_list = $this->get_recursive_file_list($this->path  . 'adm/style/');
 074          foreach ($file_list as $file)
 075          {
 076              $file_name = 'adm/style/' . $file;
 077              $this->validate_events_from_file($file_name, $this->crawl_file_for_events($file_name));
 078          }
 079   
 080          return sizeof($this->events);
 081      }
 082   
 083      /**
 084      * @param string $md_file    Relative from phpBB root
 085      * @return int        Number of events found
 086      * @throws \LogicException
 087      */
 088      public function crawl_phpbb_directory_styles($md_file)
 089      {
 090          $this->crawl_eventsmd($md_file, 'styles');
 091   
 092          $styles = array('prosilver', 'subsilver2');
 093          foreach ($styles as $style)
 094          {
 095              $file_list = $this->get_recursive_file_list(
 096                  $this->path . 'styles/' . $style . '/template/'
 097              );
 098   
 099              foreach ($file_list as $file)
 100              {
 101                  $file_name = 'styles/' . $style . '/template/' . $file;
 102                  $this->validate_events_from_file($file_name, $this->crawl_file_for_events($file_name));
 103              }
 104          }
 105   
 106          return sizeof($this->events);
 107      }
 108   
 109      /**
 110      * @param string $md_file    Relative from phpBB root
 111      * @param string $filter        Should be 'styles' or 'adm'
 112      * @return int        Number of events found
 113      * @throws \LogicException
 114      */
 115      public function crawl_eventsmd($md_file, $filter)
 116      {
 117          if (!file_exists($this->path . $md_file))
 118          {
 119              throw new \LogicException("The event docs file '{$md_file}' could not be found");
 120          }
 121   
 122          $file_content = file_get_contents($this->path . $md_file);
 123          $this->filter = $filter;
 124   
 125          $events = explode("\n\n", $file_content);
 126          foreach ($events as $event)
 127          {
 128              // Last row of the file
 129              if (strpos($event, "\n===\n") === false)
 130              {
 131                  continue;
 132              }
 133   
 134              list($event_name, $details) = explode("\n===\n", $event, 2);
 135              $this->validate_event_name($event_name);
 136              $this->current_event = $event_name;
 137   
 138              if (isset($this->events[$this->current_event]))
 139              {
 140                  throw new \LogicException("The event '{$this->current_event}' is defined multiple times");
 141              }
 142   
 143              if (($this->filter == 'adm' && strpos($this->current_event, 'acp_') !== 0)
 144                  || ($this->filter == 'styles' && strpos($this->current_event, 'acp_') === 0))
 145              {
 146                  continue;
 147              }
 148   
 149              list($file_details, $details) = explode("\n* Since: ", $details, 2);
 150              list($since, $description) = explode("\n* Purpose: ", $details, 2);
 151   
 152              $files = $this->validate_file_list($file_details);
 153              $since = $this->validate_since($since);
 154   
 155              $this->events[$event_name] = array(
 156                  'event'            => $this->current_event,
 157                  'files'            => $files,
 158                  'since'            => $since,
 159                  'description'    => $description,
 160              );
 161          }
 162   
 163          return sizeof($this->events);
 164      }
 165   
 166      /**
 167      * Format the php events as a wiki table
 168      * @return string        Number of events found
 169      */
 170      public function export_events_for_wiki()
 171      {
 172          if ($this->filter === 'adm')
 173          {
 174              $wiki_page = '= ACP Template Events =' . "\n";
 175              $wiki_page .= '{| class="zebra sortable" cellspacing="0" cellpadding="5"' . "\n";
 176              $wiki_page .= '! Identifier !! Placement !! Added in Release !! Explanation' . "\n";
 177          }
 178          else
 179          {
 180              $wiki_page = '= Template Events =' . "\n";
 181              $wiki_page .= '{| class="zebra sortable" cellspacing="0" cellpadding="5"' . "\n";
 182              $wiki_page .= '! Identifier !! Prosilver Placement (If applicable) !! Subsilver Placement (If applicable) !! Added in Release !! Explanation' . "\n";
 183          }
 184   
 185          foreach ($this->events as $event_name => $event)
 186          {
 187              $wiki_page .= "|- id=\"{$event_name}\"\n";
 188              $wiki_page .= "| [[#{$event_name}|{$event_name}]] || ";
 189   
 190              if ($this->filter === 'adm')
 191              {
 192                  $wiki_page .= implode(', ', $event['files']['adm']);
 193              }
 194              else
 195              {
 196                  $wiki_page .= implode(', ', $event['files']['prosilver']) . ' || ' . implode(', ', $event['files']['subsilver2']);
 197              }
 198   
 199              $wiki_page .= " || {$event['since']} || " . str_replace("\n", ' ', $event['description']) . "\n";
 200          }
 201          $wiki_page .= '|}' . "\n";
 202   
 203          return $wiki_page;
 204      }
 205   
 206      /**
 207      * Validates a template event name
 208      *
 209      * @param $event_name
 210      * @return null
 211      * @throws \LogicException
 212      */
 213      public function validate_event_name($event_name)
 214      {
 215          if (!preg_match('#^([a-z][a-z0-9]*(?:_[a-z][a-z0-9]*)+)$#', $event_name))
 216          {
 217              throw new \LogicException("Invalid event name '{$event_name}'");
 218          }
 219      }
 220   
 221      /**
 222      * Validate "Since" Information
 223      *
 224      * @param string $since
 225      * @return string
 226      * @throws \LogicException
 227      */
 228      public function validate_since($since)
 229      {
 230          if (!preg_match('#^\d+\.\d+\.\d+(?:-(?:a|b|RC|pl)\d+)?$#', $since))
 231          {
 232              throw new \LogicException("Invalid since information found for event '{$this->current_event}'");
 233          }
 234   
 235          return $since;
 236      }
 237   
 238      /**
 239      * Validate the files list
 240      *
 241      * @param string $file_details
 242      * @return array
 243      * @throws \LogicException
 244      */
 245      public function validate_file_list($file_details)
 246      {
 247          $files_list = array(
 248              'prosilver'        => array(),
 249              'subsilver2'    => array(),
 250              'adm'            => array(),
 251          );
 252   
 253          // Multi file list
 254          if (strpos($file_details, "* Locations:\n    + ") === 0)
 255          {
 256              $file_details = substr($file_details, strlen("* Locations:\n    + "));
 257              $files = explode("\n    + ", $file_details);
 258              foreach ($files as $file)
 259              {
 260                  if (!file_exists($this->path . $file) || substr($file, -5) !== '.html')
 261                  {
 262                      throw new \LogicException("Invalid file '{$file}' not found for event '{$this->current_event}'", 1);
 263                  }
 264   
 265                  if (($this->filter !== 'adm') && strpos($file, 'styles/prosilver/template/') === 0)
 266                  {
 267                      $files_list['prosilver'][] = substr($file, strlen('styles/prosilver/template/'));
 268                  }
 269                  else if (($this->filter !== 'adm') && strpos($file, 'styles/subsilver2/template/') === 0)
 270                  {
 271                      $files_list['subsilver2'][] = substr($file, strlen('styles/subsilver2/template/'));
 272                  }
 273                  else if (($this->filter === 'adm') && strpos($file, 'adm/style/') === 0)
 274                  {
 275                      $files_list['adm'][] = substr($file, strlen('adm/style/'));
 276                  }
 277                  else
 278                  {
 279                      throw new \LogicException("Invalid file '{$file}' not found for event '{$this->current_event}'", 2);
 280                  }
 281   
 282                  $this->events_by_file[$file][] = $this->current_event;
 283              }
 284          }
 285          else if ($this->filter == 'adm')
 286          {
 287              $file = substr($file_details, strlen('* Location: '));
 288              if (!file_exists($this->path . $file) || substr($file, -5) !== '.html')
 289              {
 290                  throw new \LogicException("Invalid file '{$file}' not found for event '{$this->current_event}'", 1);
 291              }
 292   
 293              $files_list['adm'][] =  substr($file, strlen('adm/style/'));
 294   
 295              $this->events_by_file[$file][] = $this->current_event;
 296          }
 297          else
 298          {
 299              throw new \LogicException("Invalid file list found for event '{$this->current_event}'", 2);
 300          }
 301   
 302          return $files_list;
 303      }
 304   
 305      /**
 306      * Get all template events in a template file
 307      *
 308      * @param string $file
 309      * @return array
 310      * @throws \LogicException
 311      */
 312      public function crawl_file_for_events($file)
 313      {
 314          if (!file_exists($this->path . $file))
 315          {
 316              throw new \LogicException("File '{$file}' does not exist", 1);
 317          }
 318   
 319          $event_list = array();
 320          $file_content = file_get_contents($this->path . $file);
 321   
 322          $events = explode('<!-- EVENT ', $file_content);
 323          // Remove the code before the first event
 324          array_shift($events);
 325          foreach ($events as $event)
 326          {
 327              $event = explode(' -->', $event, 2);
 328              $event_list[] = array_shift($event);
 329          }
 330   
 331          return $event_list;
 332      }
 333   
 334      /**
 335      * Validates whether all events from $file are in the md file and vice-versa
 336      *
 337      * @param string $file
 338      * @param array $events
 339      * @return true
 340      * @throws \LogicException
 341      */
 342      public function validate_events_from_file($file, array $events)
 343      {
 344          if (empty($this->events_by_file[$file]) && empty($events))
 345          {
 346              return true;
 347          }
 348          else if (empty($this->events_by_file[$file]))
 349          {
 350              $event_list = implode("', '", $events);
 351              throw new \LogicException("File '{$file}' should not contain events, but contains: "
 352                  . "'{$event_list}'", 1);
 353          }
 354          else if (empty($events))
 355          {
 356              $event_list = implode("', '", $this->events_by_file[$file]);
 357              throw new \LogicException("File '{$file}' contains no events, but should contain: "
 358                  . "'{$event_list}'", 1);
 359          }
 360   
 361          $missing_events_from_file = array();
 362          foreach ($this->events_by_file[$file] as $event)
 363          {
 364              if (!in_array($event, $events))
 365              {
 366                  $missing_events_from_file[] = $event;
 367              }
 368          }
 369   
 370          if (!empty($missing_events_from_file))
 371          {
 372              $event_list = implode("', '", $missing_events_from_file);
 373              throw new \LogicException("File '{$file}' does not contain events: '{$event_list}'", 2);
 374          }
 375   
 376          $missing_events_from_md = array();
 377          foreach ($events as $event)
 378          {
 379              if (!in_array($event, $this->events_by_file[$file]))
 380              {
 381                  $missing_events_from_md[] = $event;
 382              }
 383          }
 384   
 385          if (!empty($missing_events_from_md))
 386          {
 387              $event_list = implode("', '", $missing_events_from_md);
 388              throw new \LogicException("File '{$file}' contains additional events: '{$event_list}'", 3);
 389          }
 390   
 391          return true;
 392      }
 393   
 394      /**
 395      * Returns a list of files in $dir
 396      *
 397      * Works recursive with any depth
 398      *
 399      * @param    string    $dir    Directory to go through
 400      * @return    array    List of files (including directories)
 401      */
 402      public function get_recursive_file_list($dir)
 403      {
 404          try
 405          {
 406              $iterator = new \RecursiveIteratorIterator(
 407                  new \phpbb\recursive_dot_prefix_filter_iterator(
 408                      new \RecursiveDirectoryIterator(
 409                          $dir,
 410                          \FilesystemIterator::SKIP_DOTS
 411                      )
 412                  ),
 413                  \RecursiveIteratorIterator::SELF_FIRST
 414              );
 415          }
 416          catch (\Exception $e)
 417          {
 418              return array();
 419          }
 420   
 421          $files = array();
 422          foreach ($iterator as $file_info)
 423          {
 424              /** @var \RecursiveDirectoryIterator $file_info */
 425              if ($file_info->isDir())
 426              {
 427                  continue;
 428              }
 429   
 430              $relative_path = $iterator->getInnerIterator()->getSubPathname();
 431   
 432              if (substr($relative_path, -5) == '.html')
 433              {
 434                  $files[] = str_replace(DIRECTORY_SEPARATOR, '/', $relative_path);
 435              }
 436          }
 437   
 438          return $files;
 439      }
 440  }
 441