Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
61.54% |
16 / 26 |
CRAP | |
77.70% |
209 / 269 |
php_exporter | |
0.00% |
0 / 1 |
|
61.54% |
16 / 26 |
214.20 | |
77.70% |
209 / 269 |
__construct | |
0.00% |
0 / 1 |
2.00 | |
90.91% |
10 / 11 |
|||
get_events | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
set_current_event | |
100.00% |
1 / 1 |
1 | |
100.00% |
3 / 3 |
|||
set_content | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
crawl_phpbb_directory_php | |
0.00% |
0 / 1 |
6.00 | |
0.00% |
0 / 6 |
|||
get_recursive_file_list | |
0.00% |
0 / 1 |
12.00 | |
0.00% |
0 / 14 |
|||
export_events_for_wiki | |
0.00% |
0 / 1 |
12.00 | |
0.00% |
0 / 10 |
|||
export_events_for_rst | |
0.00% |
0 / 1 |
6.00 | |
0.00% |
0 / 6 |
|||
export_events_for_bbcode | |
0.00% |
0 / 1 |
12.00 | |
0.00% |
0 / 12 |
|||
crawl_php_file | |
0.00% |
0 / 1 |
21.33 | |
90.91% |
60 / 66 |
|||
version_is_filtered | |
100.00% |
1 / 1 |
4 | |
100.00% |
2 / 2 |
|||
get_event_name | |
100.00% |
1 / 1 |
3 | |
100.00% |
17 / 17 |
|||
preg_match_event_name | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
get_vars_from_array | |
100.00% |
1 / 1 |
5 | |
100.00% |
9 / 9 |
|||
get_vars_from_single_line_array | |
100.00% |
1 / 1 |
4 | |
100.00% |
9 / 9 |
|||
get_vars_from_multi_line_array | |
0.00% |
0 / 1 |
3.02 | |
87.50% |
7 / 8 |
|||
get_vars_from_docblock | |
100.00% |
1 / 1 |
10 | |
100.00% |
26 / 26 |
|||
find_since | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
find_changed | |
100.00% |
1 / 1 |
3 | |
100.00% |
7 / 7 |
|||
find_event | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
find_tag | |
100.00% |
1 / 1 |
11 | |
100.00% |
17 / 17 |
|||
find_description | |
100.00% |
1 / 1 |
6 | |
100.00% |
12 / 12 |
|||
validate_since | |
100.00% |
1 / 1 |
2 | |
100.00% |
6 / 6 |
|||
validate_changed | |
0.00% |
0 / 1 |
2.09 | |
71.43% |
5 / 7 |
|||
validate_event | |
0.00% |
0 / 1 |
3.14 | |
75.00% |
6 / 8 |
|||
validate_vars_docblock_array | |
100.00% |
1 / 1 |
3 | |
100.00% |
7 / 7 |
<?php | |
/** | |
* | |
* This file is part of the phpBB Forum Software package. | |
* | |
* @copyright (c) phpBB Limited <https://www.phpbb.com> | |
* @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 php_exporter | |
* Crawls through a list of files and grabs all php-events | |
*/ | |
class php_exporter | |
{ | |
/** @var string Path where we look for files*/ | |
protected $path; | |
/** @var string phpBB Root Path */ | |
protected $root_path; | |
/** @var string The minimum version for the events to return */ | |
protected $min_version; | |
/** @var string The maximum version for the events to return */ | |
protected $max_version; | |
/** @var string */ | |
protected $current_file; | |
/** @var string */ | |
protected $current_event; | |
/** @var int */ | |
protected $current_event_line; | |
/** @var array */ | |
protected $events; | |
/** @var array */ | |
protected $file_lines; | |
/** | |
* @param string $phpbb_root_path | |
* @param mixed $extension String 'vendor/ext' to filter, null for phpBB core | |
* @param string $min_version | |
* @param string $max_version | |
*/ | |
public function __construct($phpbb_root_path, $extension = null, $min_version = null, $max_version = null) | |
{ | |
$this->root_path = $phpbb_root_path; | |
$this->path = $phpbb_root_path; | |
$this->events = $this->file_lines = array(); | |
$this->current_file = $this->current_event = ''; | |
$this->current_event_line = 0; | |
$this->min_version = $min_version; | |
$this->max_version = $max_version; | |
$this->path = $this->root_path; | |
if ($extension) | |
{ | |
$this->path .= 'ext/' . $extension . '/'; | |
} | |
} | |
/** | |
* Get the list of all events | |
* | |
* @return array Array with events: name => details | |
*/ | |
public function get_events() | |
{ | |
return $this->events; | |
} | |
/** | |
* Set current event data | |
* | |
* @param string $name Name of the current event (used for error messages) | |
* @param int $line Line where the current event is placed in | |
* @return null | |
*/ | |
public function set_current_event($name, $line) | |
{ | |
$this->current_event = $name; | |
$this->current_event_line = $line; | |
} | |
/** | |
* Set the content of this file | |
* | |
* @param array $content Array with the lines of the file | |
* @return null | |
*/ | |
public function set_content($content) | |
{ | |
$this->file_lines = $content; | |
} | |
/** | |
* Crawl the phpBB/ directory for php events | |
* @return int The number of events found | |
*/ | |
public function crawl_phpbb_directory_php() | |
{ | |
$files = $this->get_recursive_file_list(); | |
$this->events = array(); | |
foreach ($files as $file) | |
{ | |
$this->crawl_php_file($file); | |
} | |
ksort($this->events); | |
return count($this->events); | |
} | |
/** | |
* Returns a list of files in $dir | |
* | |
* @return array List of files (including the path) | |
*/ | |
public function get_recursive_file_list() | |
{ | |
try | |
{ | |
$iterator = new \RecursiveIteratorIterator( | |
new \phpbb\event\recursive_event_filter_iterator( | |
new \RecursiveDirectoryIterator( | |
$this->path, | |
\FilesystemIterator::SKIP_DOTS | |
), | |
$this->path | |
), | |
\RecursiveIteratorIterator::LEAVES_ONLY | |
); | |
} | |
catch (\Exception $e) | |
{ | |
return array(); | |
} | |
$files = array(); | |
foreach ($iterator as $file_info) | |
{ | |
/** @var \RecursiveDirectoryIterator $file_info */ | |
$relative_path = $iterator->getInnerIterator()->getSubPathname(); | |
$files[] = str_replace(DIRECTORY_SEPARATOR, '/', $relative_path); | |
} | |
return $files; | |
} | |
/** | |
* Format the php events as a wiki table | |
* | |
* @param string $action | |
* @return string | |
* @deprecated 3.3.5-RC1 (To be removed: 4.0.0-a1) | |
*/ | |
public function export_events_for_wiki($action = '') | |
{ | |
if ($action === 'diff') | |
{ | |
$wiki_page = '=== PHP Events (Hook Locations) ===' . "\n"; | |
} | |
else | |
{ | |
$wiki_page = '= PHP Events (Hook Locations) =' . "\n"; | |
} | |
$wiki_page .= '{| class="sortable zebra" cellspacing="0" cellpadding="5"' . "\n"; | |
$wiki_page .= '! Identifier !! Placement !! Arguments !! Added in Release !! Explanation' . "\n"; | |
foreach ($this->events as $event) | |
{ | |
$wiki_page .= '|- id="' . $event['event'] . '"' . "\n"; | |
$wiki_page .= '| [[#' . $event['event'] . '|' . $event['event'] . ']] || ' . $event['file'] . ' || ' . implode(', ', $event['arguments']) . ' || ' . $event['since'] . ' || ' . $event['description'] . "\n"; | |
} | |
$wiki_page .= '|}' . "\n"; | |
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(); | |
} | |
/** | |
* Format the PHP events as a BBCode list | |
* | |
* @param string $action | |
* @return string | |
*/ | |
public function export_events_for_bbcode(string $action = ''): string | |
{ | |
if ($action === 'diff') | |
{ | |
$bbcode_text = '[size=150]PHP Events[/size]' . "\n"; | |
} | |
else | |
{ | |
$bbcode_text = '[size=200]PHP Events[/size]' . "\n"; | |
} | |
foreach ($this->events as $event) | |
{ | |
$bbcode_text .= "[list]\n"; | |
$bbcode_text .= "[*][b]{$event['event']}[/b]\n"; | |
$bbcode_text .= "Placement: {$event['file']}\n"; | |
$bbcode_text .= 'Arguments: ' . implode(', ', $event['arguments']) . "\n"; | |
$bbcode_text .= "Added in Release: {$event['since']}\n"; | |
$bbcode_text .= "Explanation: {$event['description']}\n"; | |
$bbcode_text .= "[/list]\n"; | |
} | |
return $bbcode_text; | |
} | |
/** | |
* @param string $file | |
* @return int Number of events found in this file | |
* @throws \LogicException | |
*/ | |
public function crawl_php_file($file) | |
{ | |
$this->current_file = $file; | |
$this->file_lines = array(); | |
$content = file_get_contents($this->path . $this->current_file); | |
$num_events_found = 0; | |
if (strpos($content, 'dispatcher->trigger_event(') || strpos($content, 'dispatcher->dispatch(')) | |
{ | |
$this->set_content(explode("\n", $content)); | |
for ($i = 0, $num_lines = count($this->file_lines); $i < $num_lines; $i++) | |
{ | |
$event_line = false; | |
$found_trigger_event = strpos($this->file_lines[$i], 'dispatcher->trigger_event('); | |
$arguments = array(); | |
if ($found_trigger_event !== false) | |
{ | |
$event_line = $i; | |
$this->set_current_event($this->get_event_name($event_line, false), $event_line); | |
// Find variables of the event | |
$arguments = $this->get_vars_from_array(); | |
$doc_vars = $this->get_vars_from_docblock(); | |
$this->validate_vars_docblock_array($arguments, $doc_vars); | |
} | |
else | |
{ | |
$found_dispatch = strpos($this->file_lines[$i], 'dispatcher->dispatch('); | |
if ($found_dispatch !== false) | |
{ | |
$event_line = $i; | |
$this->set_current_event($this->get_event_name($event_line, true), $event_line); | |
} | |
} | |
if ($event_line) | |
{ | |
// Validate @event | |
$event_line_num = $this->find_event(); | |
$this->validate_event($this->current_event, $this->file_lines[$event_line_num]); | |
// Validate @since | |
$since_line_num = $this->find_since(); | |
$since = $this->validate_since($this->file_lines[$since_line_num]); | |
$changed_line_nums = $this->find_changed('changed'); | |
if (empty($changed_line_nums)) | |
{ | |
$changed_line_nums = $this->find_changed('change'); | |
} | |
$changed_versions = array(); | |
if (!empty($changed_line_nums)) | |
{ | |
foreach ($changed_line_nums as $changed_line_num) | |
{ | |
$changed_versions[] = $this->validate_changed($this->file_lines[$changed_line_num]); | |
} | |
} | |
if (!$this->version_is_filtered($since)) | |
{ | |
$valid_version = false; | |
foreach ($changed_versions as $changed) | |
{ | |
$valid_version = $valid_version || $this->version_is_filtered($changed); | |
} | |
if (!$valid_version) | |
{ | |
continue; | |
} | |
} | |
// Find event description line | |
$description_line_num = $this->find_description(); | |
$description_lines = array(); | |
while (true) | |
{ | |
$description_line = substr(trim($this->file_lines[$description_line_num]), strlen('*')); | |
$description_line = trim(str_replace("\t", " ", $description_line)); | |
// Reached end of description if line is a tag | |
if (strlen($description_line) && $description_line[0] == '@') | |
{ | |
break; | |
} | |
$description_lines[] = $description_line; | |
$description_line_num++; | |
} | |
// If there is an empty line between description and first tag, remove it | |
if (!strlen(end($description_lines))) | |
{ | |
array_pop($description_lines); | |
} | |
$description = trim(implode('<br>', $description_lines)); | |
sort($arguments); | |
if (isset($this->events[$this->current_event])) | |
{ | |
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); | |
} | |
$this->events[$this->current_event]['file'] .= '<br>' . $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++; | |
} | |
} | |
} | |
} | |
return $num_events_found; | |
} | |
/** | |
* The version to check | |
* | |
* @param string $version | |
* @return bool | |
*/ | |
protected function version_is_filtered($version) | |
{ | |
return (!$this->min_version || phpbb_version_compare($this->min_version, $version, '<=')) | |
&& (!$this->max_version || phpbb_version_compare($this->max_version, $version, '>=')); | |
} | |
/** | |
* Find the name of the event inside the dispatch() line | |
* | |
* @param int $event_line | |
* @param bool $is_dispatch Do we look for dispatch() or trigger_event() ? | |
* @return string Name of the event | |
* @throws \LogicException | |
*/ | |
public function get_event_name($event_line, $is_dispatch) | |
{ | |
$event_text_line = $this->file_lines[$event_line]; | |
$event_text_line = ltrim($event_text_line, "\t "); | |
if ($is_dispatch) | |
{ | |
$regex = '#\$[a-z](?:[a-z0-9_]|->)*'; | |
$regex .= '->dispatch\((\[)?'; | |
$regex .= '\'' . $this->preg_match_event_name() . '(?(1)\', \'(?2))+\''; | |
$regex .= '(?(1)\])\);#'; | |
} | |
else | |
{ | |
$regex = '#extract\(\$[a-z](?:[a-z0-9_]|->)*'; | |
$regex .= '->trigger_event\((\[)?'; | |
$regex .= '\'' . $this->preg_match_event_name() . '(?(1)\', \'(?2))+\''; | |
$regex .= '(?(1)\]), compact\(\$vars\)\)\);#'; | |
} | |
$match = array(); | |
preg_match($regex, $event_text_line, $match); | |
if (!isset($match[2])) | |
{ | |
throw new \LogicException("Can not find event name in line '{$event_text_line}' " | |
. "in file '{$this->current_file}:{$event_line}'", 1); | |
} | |
return $match[2]; | |
} | |
/** | |
* Returns a regex match for the event name | |
* | |
* @return string | |
*/ | |
protected function preg_match_event_name() | |
{ | |
return '([a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*)+)'; | |
} | |
/** | |
* Find the $vars array | |
* | |
* @return array List of variables | |
* @throws \LogicException | |
*/ | |
public function get_vars_from_array() | |
{ | |
$line = ltrim($this->file_lines[$this->current_event_line - 1], "\t"); | |
if ($line === ');' || $line === '];') | |
{ | |
$vars_array = $this->get_vars_from_multi_line_array(); | |
} | |
else | |
{ | |
$vars_array = $this->get_vars_from_single_line_array($line); | |
} | |
foreach ($vars_array as $var) | |
{ | |
if (!preg_match('#^[a-z_][a-z0-9_]*$#i', $var)) | |
{ | |
throw new \LogicException("Found invalid var '{$var}' in array for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 3); | |
} | |
} | |
sort($vars_array); | |
return $vars_array; | |
} | |
/** | |
* Find the variables in single line array | |
* | |
* @param string $line | |
* @param bool $throw_multiline Throw an exception when there are too | |
* many arguments in one line. | |
* @return array List of variables | |
* @throws \LogicException | |
*/ | |
public function get_vars_from_single_line_array($line, $throw_multiline = true) | |
{ | |
$match = array(); | |
preg_match('#^\$vars = (?:(\[)|array\()\'([a-z0-9_\' ,]+)\'(?(1)\]|\));$#i', $line, $match); | |
if (isset($match[2])) | |
{ | |
$vars_array = explode("', '", $match[2]); | |
if ($throw_multiline && count($vars_array) > 6) | |
{ | |
throw new \LogicException('Should use multiple lines for $vars definition ' | |
. "for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 2); | |
} | |
return $vars_array; | |
} | |
else | |
{ | |
throw new \LogicException("Can not find '\$vars = array();'-line for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 1); | |
} | |
} | |
/** | |
* Find the variables in single line array | |
* | |
* @return array List of variables | |
* @throws \LogicException | |
*/ | |
public function get_vars_from_multi_line_array() | |
{ | |
$current_vars_line = 2; | |
$var_lines = array(); | |
while (!in_array(ltrim($this->file_lines[$this->current_event_line - $current_vars_line], "\t"), ['$vars = array(', '$vars = ['])) | |
{ | |
$var_lines[] = substr(trim($this->file_lines[$this->current_event_line - $current_vars_line]), 0, -1); | |
$current_vars_line++; | |
if ($current_vars_line > $this->current_event_line) | |
{ | |
// Reached the start of the file | |
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); | |
} | |
} | |
return $this->get_vars_from_single_line_array('$vars = array(' . implode(", ", $var_lines) . ');', false); | |
} | |
/** | |
* Find the $vars array | |
* | |
* @return array List of variables | |
* @throws \LogicException | |
*/ | |
public function get_vars_from_docblock() | |
{ | |
$doc_vars = array(); | |
$current_doc_line = 1; | |
$found_comment_end = false; | |
while (ltrim($this->file_lines[$this->current_event_line - $current_doc_line], "\t") !== '/**') | |
{ | |
if (ltrim($this->file_lines[$this->current_event_line - $current_doc_line], "\t ") === '*/') | |
{ | |
$found_comment_end = true; | |
} | |
if ($found_comment_end) | |
{ | |
$var_line = trim($this->file_lines[$this->current_event_line - $current_doc_line]); | |
$var_line = preg_replace('!\s+!', ' ', $var_line); | |
if (strpos($var_line, '* @var ') === 0) | |
{ | |
$doc_line = explode(' ', $var_line, 5); | |
if (count($doc_line) !== 5) | |
{ | |
throw new \LogicException("Found invalid line '{$this->file_lines[$this->current_event_line - $current_doc_line]}' " | |
. "for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 1); | |
} | |
$doc_vars[] = $doc_line[3]; | |
} | |
} | |
$current_doc_line++; | |
if ($current_doc_line > $this->current_event_line) | |
{ | |
// Reached the start of the file | |
throw new \LogicException("Can not find end of docblock for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 2); | |
} | |
} | |
if (empty($doc_vars)) | |
{ | |
// Reached the start of the file | |
throw new \LogicException("Can not find @var lines for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 3); | |
} | |
foreach ($doc_vars as $var) | |
{ | |
if (!preg_match('#^[a-z_][a-z0-9_]*$#i', $var)) | |
{ | |
throw new \LogicException("Found invalid @var '{$var}' in docblock for event " | |
. "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 4); | |
} | |
} | |
sort($doc_vars); | |
return $doc_vars; | |
} | |
/** | |
* Find the "@since" Information line | |
* | |
* @return int Absolute line number | |
* @throws \LogicException | |
*/ | |
public function find_since() | |
{ | |
return $this->find_tag('since', array('event', 'var')); | |
} | |
/** | |
* Find the "@changed" Information lines | |
* | |
* @param string $tag_name Should be 'change', not 'changed' | |
* @return array Absolute line numbers | |
* @throws \LogicException | |
*/ | |
public function find_changed($tag_name) | |
{ | |
$lines = array(); | |
$last_line = 0; | |
try | |
{ | |
while ($line = $this->find_tag($tag_name, array('since'), $last_line)) | |
{ | |
$lines[] = $line; | |
$last_line = $line; | |
} | |
} | |
catch (\LogicException $e) | |
{ | |
// Not changed? No problem! | |
} | |
return $lines; | |
} | |
/** | |
* Find the "@event" Information line | |
* | |
* @return int Absolute line number | |
*/ | |
public function find_event() | |
{ | |
return $this->find_tag('event', array()); | |
} | |
/** | |
* Find a "@*" Information line | |
* | |
* @param string $find_tag Name of the tag we are trying to find | |
* @param array $disallowed_tags List of tags that must not appear between | |
* the tag and the actual event | |
* @param int $skip_to_line Skip lines until this one | |
* @return int Absolute line number | |
* @throws \LogicException | |
*/ | |
public function find_tag($find_tag, $disallowed_tags, $skip_to_line = 0) | |
{ | |
$find_tag_line = $skip_to_line ? $this->current_event_line - $skip_to_line + 1 : 0; | |
$found_comment_end = ($skip_to_line) ? true : false; | |
while (strpos(ltrim($this->file_lines[$this->current_event_line - $find_tag_line], "\t "), '* @' . $find_tag . ' ') !== 0) | |
{ | |
if ($found_comment_end && ltrim($this->file_lines[$this->current_event_line - $find_tag_line], "\t") === '/**') | |
{ | |
// Reached the start of this doc block | |
throw new \LogicException("Can not find '@{$find_tag}' information for event " | |
. "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 1); | |
} | |
foreach ($disallowed_tags as $disallowed_tag) | |
{ | |
if ($found_comment_end && strpos(ltrim($this->file_lines[$this->current_event_line - $find_tag_line], "\t "), '* @' . $disallowed_tag) === 0) | |
{ | |
// Found @var after the @since | |
throw new \LogicException("Found '@{$disallowed_tag}' information after '@{$find_tag}' for event " | |
. "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 3); | |
} | |
} | |
if (ltrim($this->file_lines[$this->current_event_line - $find_tag_line], "\t ") === '*/') | |
{ | |
$found_comment_end = true; | |
} | |
$find_tag_line++; | |
if ($find_tag_line >= $this->current_event_line) | |
{ | |
// Reached the start of the file | |
throw new \LogicException("Can not find '@{$find_tag}' information for event " | |
. "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 2); | |
} | |
} | |
return $this->current_event_line - $find_tag_line; | |
} | |
/** | |
* Find a "@*" Information line | |
* | |
* @return int Absolute line number | |
* @throws \LogicException | |
*/ | |
public function find_description() | |
{ | |
$find_desc_line = 0; | |
while (ltrim($this->file_lines[$this->current_event_line - $find_desc_line], "\t") !== '/**') | |
{ | |
$find_desc_line++; | |
if ($find_desc_line > $this->current_event_line) | |
{ | |
// Reached the start of the file | |
throw new \LogicException("Can not find a description for event " | |
. "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 1); | |
} | |
} | |
$find_desc_line = $this->current_event_line - $find_desc_line + 1; | |
$desc = trim($this->file_lines[$find_desc_line]); | |
if (strpos($desc, '* @') === 0 || $desc[0] !== '*' || substr($desc, 1) == '') | |
{ | |
// First line of the doc block is a @-line, empty or only contains "*" | |
throw new \LogicException("Can not find a description for event " | |
. "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 2); | |
} | |
return $find_desc_line; | |
} | |
/** | |
* Validate "@since" Information | |
* | |
* @param string $line | |
* @return string | |
* @throws \LogicException | |
*/ | |
public function validate_since($line) | |
{ | |
$match = array(); | |
preg_match('#^\* @since (\d+\.\d+\.\d+(?:-(?:a|b|RC|pl)\d+)?)$#', ltrim($line, "\t "), $match); | |
if (!isset($match[1])) | |
{ | |
throw new \LogicException("Invalid '@since' information for event " | |
. "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'"); | |
} | |
return $match[1]; | |
} | |
/** | |
* Validate "@changed" Information | |
* | |
* @param string $line | |
* @return string | |
* @throws \LogicException | |
*/ | |
public function validate_changed($line) | |
{ | |
$match = array(); | |
$line = str_replace("\t", ' ', ltrim($line, "\t ")); | |
preg_match('#^\* @changed (\d+\.\d+\.\d+(?:-(?:a|b|RC|pl)\d+)?)( (?:.*))?$#', $line, $match); | |
if (!isset($match[2])) | |
{ | |
throw new \LogicException("Invalid '@changed' information for event " | |
. "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'"); | |
} | |
return $match[2]; | |
} | |
/** | |
* Validate "@event" Information | |
* | |
* @param string $event_name | |
* @param string $line | |
* @return string | |
* @throws \LogicException | |
*/ | |
public function validate_event($event_name, $line) | |
{ | |
$event = substr(ltrim($line, "\t "), strlen('* @event ')); | |
if ($event !== trim($event)) | |
{ | |
throw new \LogicException("Invalid '@event' information for event " | |
. "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 1); | |
} | |
if ($event !== $event_name) | |
{ | |
throw new \LogicException("Event name does not match '@event' tag for event " | |
. "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 2); | |
} | |
return $event; | |
} | |
/** | |
* Validates that two arrays contain the same strings | |
* | |
* @param array $vars_array Variables found in the array line | |
* @param array $vars_docblock Variables found in the doc block | |
* @return null | |
* @throws \LogicException | |
*/ | |
public function validate_vars_docblock_array($vars_array, $vars_docblock) | |
{ | |
$vars_array = array_unique($vars_array); | |
$vars_docblock = array_unique($vars_docblock); | |
$sizeof_vars_array = count($vars_array); | |
if ($sizeof_vars_array !== count($vars_docblock) || $sizeof_vars_array !== count(array_intersect($vars_array, $vars_docblock))) | |
{ | |
throw new \LogicException("\$vars array does not match the list of '@var' tags for event " | |
. "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'"); | |
} | |
} | |
} |