From bcc75099ab496fc276557c426459d04063cffdcc Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 7 Apr 2021 22:20:23 +0200 Subject: [PATCH 1/3] [ticket/16752] Add first version of exporter to restructured text (rst) PHPBB3-16752 --- phpBB/phpbb/event/rst_exporter.php | 183 +++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 phpBB/phpbb/event/rst_exporter.php diff --git a/phpBB/phpbb/event/rst_exporter.php b/phpBB/phpbb/event/rst_exporter.php new file mode 100644 index 0000000000..1b8376c814 --- /dev/null +++ b/phpBB/phpbb/event/rst_exporter.php @@ -0,0 +1,183 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\event; + +class rst_exporter +{ + /** @var array Column keys */ + private $columns = []; + + /** @var array Column headers map */ + private $column_headers = []; + + /** @var array Maximum lengths of columns */ + private $max_lengths = []; + + /** @var string rst data */ + private $rst_data = ''; + + /** + * Set columns with array where key is column name and value is title of column in table + * + * @param array $column_data + */ + public function set_columns(array $column_data): void + { + foreach ($column_data as $column_key => $column_header) + { + $this->columns[] = $column_key; + $this->column_headers[$column_key] = $column_header; + } + } + + /** + * Add header to rst page + * + * @param string $type Type of header; allowed are h2, h3, h4 corresponding to HTML + * @param string $header_text Text of header + */ + public function add_section_header(string $type, string $header_text): void + { + $this->rst_data .= $header_text . "\n"; + + switch ($type) + { + case 'h2': + $header_character = '='; + break; + + default: + case 'h3': + $header_character = '-'; + break; + + case 'h4': + $header_character = '~'; + break; + } + + $this->rst_data .= str_repeat($header_character, strlen($header_text)) . "\n\n"; + } + + /** + * Fill table with event data + * + * @param array $event_data + */ + public function generate_events_table(array $event_data): void + { + $this->rst_data .= ".. table::\n"; + $this->rst_data .= " :class: events-list\n\n"; + + $this->set_max_lengths($event_data); + + // Create table header + $this->rst_data .= $this->get_separator_line(); + $this->rst_data .= " |"; + foreach ($this->columns as $column) + { + $this->rst_data .= $this->get_column($column, $this->column_headers[$column]); + } + + $this->rst_data .= "\n" . $this->get_separator_line('='); + + foreach ($event_data as $event) + { + $event_data = []; + $max_column_rows = 1; + foreach ($event as $key => $value) + { + $column_rows = !is_array($value) ? substr_count($value, '
') + 1 : 1; + $max_column_rows = max($max_column_rows, $column_rows); + $event_data[$key] = $column_rows > 1 ? explode('
', $value) : [is_array($value) ? implode(', ', $value) : $value]; + } + + for ($i = 0; $i < $max_column_rows; $i++) + { + $this->rst_data .= ' |'; + + foreach ($this->columns as $column) + { + $this->rst_data .= $this->get_column($column, $event_data[$column][$i] ?? ''); + } + $this->rst_data .= "\n"; + } + $this->rst_data .= $this->get_separator_line(); + } + } + + /** + * Get rst output + * + * @return string + */ + public function get_rst_output(): string + { + return $this->rst_data; + } + + /** + * Set maximum lengths array + * + * @param array $event_data + */ + private function set_max_lengths(array $event_data): void + { + $this->max_lengths = []; + + foreach ($this->columns as $column) + { + $this->max_lengths[$column] = strlen($this->column_headers[$column]); + } + + foreach ($event_data as $event) + { + foreach ($this->columns as $column) + { + $event_column = is_array($event[$column]) ? implode(', ', $event[$column]) : $event[$column]; + $this->max_lengths[$column] = max($this->max_lengths[$column], strlen($event_column)); + } + } + } + + /** + * Get separator line + * + * @param string $separator_character + * @return string + */ + private function get_separator_line(string $separator_character = '-'): string + { + $line = " +"; + + foreach ($this->columns as $column) + { + $line .= str_repeat($separator_character, $this->max_lengths[$column] + 2) . '+'; + } + + return $line . "\n"; + } + + /** + * Get table data column + * + * @param string $type Column type + * @param string $content Column content + * @return string + */ + private function get_column(string $type, string $content): string + { + return ' ' . $content . str_repeat(' ' , $this->max_lengths[$type] - strlen($content) + 1) . '|'; + } +} From 1ecc2e042b74af75192819b3d14039b258471938 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 8 Apr 2021 20:14:18 +0200 Subject: [PATCH 2/3] [ticket/16752] Add methods for exporting events to rst by script PHPBB3-16752 --- phpBB/develop/export_events_for_rst.php | 140 ++++++++++++++++++++++++ phpBB/phpbb/event/md_exporter.php | 67 +++++++++++- phpBB/phpbb/event/php_exporter.php | 58 +++++++--- phpBB/phpbb/event/rst_exporter.php | 1 + 4 files changed, 251 insertions(+), 15 deletions(-) create mode 100644 phpBB/develop/export_events_for_rst.php diff --git a/phpBB/develop/export_events_for_rst.php b/phpBB/develop/export_events_for_rst.php new file mode 100644 index 0000000000..d8cef7bf9f --- /dev/null +++ b/phpBB/develop/export_events_for_rst.php @@ -0,0 +1,140 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +if (php_sapi_name() != 'cli') +{ + die("This program must be run from the command line.\n"); +} + +$phpEx = substr(strrchr(__FILE__, '.'), 1); +$phpbb_root_path = __DIR__ . '/../'; +define('IN_PHPBB', true); + +function usage() +{ + echo "Usage: export_events_for_rst.php COMMAND [VERSION] [EXTENSION]\n"; + echo "\n"; + echo "COMMAND:\n"; + echo " all:\n"; + echo " Generate the complete rst for the Event List\n"; + echo "\n"; + echo " diff:\n"; + echo " Generate the Event Diff for the release highlights\n"; + echo "\n"; + echo " php:\n"; + echo " Generate the PHP event section of Event_List\n"; + echo "\n"; + echo " adm:\n"; + echo " Generate the ACP Template event section of Event_List\n"; + echo "\n"; + echo " styles:\n"; + echo " Generate the Styles Template event section of Event_List\n"; + echo "\n"; + echo "VERSION (diff only):\n"; + echo " Filter events (minimum version)\n"; + echo "\n"; + echo "EXTENSION (Optional):\n"; + echo " If not given, only core events will be exported.\n"; + echo " Otherwise only events from the extension will be exported.\n"; + echo "\n"; + exit(2); +} + +function validate_argument_count($arguments, $count) +{ + if ($arguments <= $count) + { + usage(); + } +} + +validate_argument_count($argc, 1); + +$action = $argv[1]; +$extension = isset($argv[2]) ? $argv[2] : null; +$min_version = null; +require __DIR__ . '/../phpbb/event/php_exporter.' . $phpEx; +require __DIR__ . '/../phpbb/event/md_exporter.' . $phpEx; +require __DIR__ . '/../phpbb/event/rst_exporter.' . $phpEx; +require __DIR__ . '/../includes/functions.' . $phpEx; +require __DIR__ . '/../phpbb/event/recursive_event_filter_iterator.' . $phpEx; +require __DIR__ . '/../phpbb/recursive_dot_prefix_filter_iterator.' . $phpEx; + +switch ($action) +{ + + case 'diff': + echo '== Event changes ==' . "\n"; + echo "Event changes\n"; + echo "=============\n\n"; + $min_version = $extension; + $extension = isset($argv[3]) ? $argv[3] : null; + + case 'all': + if ($action === 'all') + { + echo "==========================\n"; + echo "Events List\n"; + echo "==========================\n\n"; + } + + + case 'php': + $exporter = new \phpbb\event\php_exporter($phpbb_root_path, $extension, $min_version); + $exporter->crawl_phpbb_directory_php(); + echo $exporter->export_events_for_rst($action); + + if ($action === 'php') + { + break; + } + echo "\n\n"; + // no break; + + case 'styles': + $exporter = new \phpbb\event\md_exporter($phpbb_root_path, $extension, $min_version); + if ($min_version && $action === 'diff') + { + $exporter->crawl_eventsmd('docs/events.md', 'styles'); + } + else + { + $exporter->crawl_phpbb_directory_styles('docs/events.md'); + } + echo $exporter->export_events_for_rst($action); + + if ($action === 'styles') + { + break; + } + echo "\n\n"; + // no break; + + case 'adm': + $exporter = new \phpbb\event\md_exporter($phpbb_root_path, $extension, $min_version); + if ($min_version && $action === 'diff') + { + $exporter->crawl_eventsmd('docs/events.md', 'adm'); + } + else + { + $exporter->crawl_phpbb_directory_adm('docs/events.md'); + } + echo $exporter->export_events_for_rst($action); + + echo "\n"; + break; + + default: + usage(); +} diff --git a/phpBB/phpbb/event/md_exporter.php b/phpBB/phpbb/event/md_exporter.php index 1a2d7c989e..6ff7295886 100644 --- a/phpBB/phpbb/event/md_exporter.php +++ b/phpBB/phpbb/event/md_exporter.php @@ -243,7 +243,7 @@ class md_exporter } /** - * Format the php events as a wiki table + * Format the md events as a wiki table * * @param string $action * @return string Number of events found @@ -298,6 +298,71 @@ class md_exporter return $wiki_page; } + /** + * Format the md events as a rst table + * + * @param string $action + * @return string Number of events found + */ + public function export_events_for_rst(string $action = ''): string + { + $rst_exporter = new rst_exporter(); + + if ($this->filter === 'adm') + { + if ($action === 'diff') + { + $rst_exporter->add_section_header('h3', 'ACP Template Events'); + } + else + { + $rst_exporter->add_section_header('h2', 'ACP Template Events'); + } + + $rst_exporter->set_columns([ + 'event' => 'Identifier', + 'files' => 'Placement', + 'since' => 'Added in Release', + 'description' => 'Explanation', + ]); + } + else + { + if ($action === 'diff') + { + $rst_exporter->add_section_header('h3', 'Template Events'); + } + else + { + $rst_exporter->add_section_header('h2', 'Template Events'); + } + + $rst_exporter->set_columns([ + 'event' => 'Identifier', + 'files' => 'Prosilver Placement (If applicable)', + 'since' => 'Added in Release', + 'description' => 'Explanation', + ]); + } + + $events = []; + foreach ($this->events as $event_name => $event) + { + $files = $this->filter === 'adm' ? implode(', ', $event['files']['adm']) : implode(', ', $event['files']['prosilver']); + + $events[] = [ + 'event' => $event_name, + 'files' => $files, + 'since' => $event['since'], + 'description' => str_replace("\n", '
', rtrim($event['description'])), + ]; + } + + $rst_exporter->generate_events_table($events); + + return $rst_exporter->get_rst_output(); + } + /** * Validates a template event name * diff --git a/phpBB/phpbb/event/php_exporter.php b/phpBB/phpbb/event/php_exporter.php index 71c94a681d..921fe36498 100644 --- a/phpBB/phpbb/event/php_exporter.php +++ b/phpBB/phpbb/event/php_exporter.php @@ -184,6 +184,28 @@ class php_exporter return $wiki_page; } + /** + * Format the PHP events as a rst table + * + * @param string $action + * @return string + */ + public function export_events_for_rst(string $action = ''): string + { + $rst_exporter = new rst_exporter(); + $rst_exporter->add_section_header($action === 'diff' ? 'h3' : 'h2', 'PHP Events'); + $rst_exporter->set_columns([ + 'event' => 'Identifier', + 'file' => 'Placement', + 'arguments' => 'Arguments', + 'since' => 'Added in Release', + 'description' => 'Explanation', + ]); + $rst_exporter->generate_events_table($this->events); + + return $rst_exporter->get_rst_output(); + } + /** * @param string $file * @return int Number of events found in this file @@ -287,24 +309,32 @@ class php_exporter array_pop($description_lines); } - $description = trim(implode('
', $description_lines)); + $description = trim(implode('
', $description_lines)); + sort($arguments); if (isset($this->events[$this->current_event])) { - throw new \LogicException("The event '{$this->current_event}' from file " - . "'{$this->current_file}:{$event_line_num}' already exists in file " - . "'{$this->events[$this->current_event]['file']}'", 10); - } + if ($this->events[$this->current_event]['arguments'] != $arguments || + $this->events[$this->current_event]['since'] != $since) + { + throw new \LogicException("The event '{$this->current_event}' from file " + . "'{$this->current_file}:{$event_line_num}' already exists in file " + . "'{$this->events[$this->current_event]['file']}'", 10); + } - sort($arguments); - $this->events[$this->current_event] = array( - 'event' => $this->current_event, - 'file' => $this->current_file, - 'arguments' => $arguments, - 'since' => $since, - 'description' => $description, - ); - $num_events_found++; + $this->events[$this->current_event]['file'] .= '
' . $this->current_file; + } + else + { + $this->events[$this->current_event] = array( + 'event' => $this->current_event, + 'file' => $this->current_file, + 'arguments' => $arguments, + 'since' => $since, + 'description' => $description, + ); + $num_events_found++; + } } } } diff --git a/phpBB/phpbb/event/rst_exporter.php b/phpBB/phpbb/event/rst_exporter.php index 1b8376c814..90a79e932d 100644 --- a/phpBB/phpbb/event/rst_exporter.php +++ b/phpBB/phpbb/event/rst_exporter.php @@ -178,6 +178,7 @@ class rst_exporter */ private function get_column(string $type, string $content): string { + $content = rtrim($content); return ' ' . $content . str_repeat(' ' , $this->max_lengths[$type] - strlen($content) + 1) . '|'; } } From 70337e99fa9e5fa097134a3bad46c51f8639d4fd Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 8 Apr 2021 21:18:35 +0200 Subject: [PATCH 3/3] [ticket/16752] Add deprecation notices and fix tests PHPBB3-16752 --- phpBB/phpbb/event/md_exporter.php | 3 ++- phpBB/phpbb/event/php_exporter.php | 1 + tests/event/php_exporter_test.php | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/event/md_exporter.php b/phpBB/phpbb/event/md_exporter.php index 6ff7295886..0f672f0f36 100644 --- a/phpBB/phpbb/event/md_exporter.php +++ b/phpBB/phpbb/event/md_exporter.php @@ -246,7 +246,8 @@ class md_exporter * Format the md events as a wiki table * * @param string $action - * @return string Number of events found + * @return string Number of events found * @deprecated since 3.2 + * @deprecated 3.3.5-RC1 (To be removed: 4.0.0-a1) */ public function export_events_for_wiki($action = '') { diff --git a/phpBB/phpbb/event/php_exporter.php b/phpBB/phpbb/event/php_exporter.php index 921fe36498..85627c9dff 100644 --- a/phpBB/phpbb/event/php_exporter.php +++ b/phpBB/phpbb/event/php_exporter.php @@ -161,6 +161,7 @@ class php_exporter * * @param string $action * @return string + * @deprecated 3.3.5-RC1 (To be removed: 4.0.0-a1) */ public function export_events_for_wiki($action = '') { diff --git a/tests/event/php_exporter_test.php b/tests/event/php_exporter_test.php index 0effa9d181..3911f46ddd 100644 --- a/tests/event/php_exporter_test.php +++ b/tests/event/php_exporter_test.php @@ -57,7 +57,7 @@ class phpbb_event_php_exporter_test extends phpbb_test_case 'file' => 'extra_description.test', 'arguments' => array(), 'since' => '3.1.0-b2', - 'description' => 'Description

NOTE: This will also be exported', + 'description' => 'Description

NOTE: This will also be exported', ), ), ),