Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions features/dist-archive.feature
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,30 @@ Feature: Generate a distribution archive of a project
And the wp-content/plugins/hello-world/.circleci/config.yml file should not exist
And the wp-content/plugins/hello-world/bin directory should not exist

Scenario: Uses plugin Version header, not PHPdoc @version tag, for archive name
Given an empty directory
And a my-plugin/my-plugin.php file:
"""
<?php
/**
* Plugin Name: My Plugin
* Version: 7.6.0
*/
"""
And a my-plugin/class-my-plugin.php file:
"""
<?php
/**
* Main class file.
*
* @version 7.2.0
*/
"""

When I try `wp dist-archive my-plugin`
Then the my-plugin.7.6.0.zip file should exist
And the my-plugin.7.2.0.zip file should not exist

# This test does not work with SQLite because it wipes wp-content
# but SQLite requires an integration plugin & drop-in to work.
@require-mysql
Expand Down
83 changes: 4 additions & 79 deletions src/Dist_Archive_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -296,9 +296,10 @@ private function get_version( $source_dir_path ) {
continue;
}
$contents = (string) file_get_contents( $php_file, false, null, 0, 5000 );
$ver = $this->get_version_in_code( $contents );
if ( ! empty( $ver ) ) {
$version = trim( $ver );
$contents = str_replace( "\r", "\n", $contents );
$pattern = '/^[ \t\/*#@]*Version:(.*)$/mi';
if ( preg_match( $pattern, $contents, $match ) && $match[1] ) {
$version = trim( (string) preg_replace( '/\s*(?:\*\/|\?>).*/', '', $match[1] ) );
break;
}
}
Expand Down Expand Up @@ -340,82 +341,6 @@ private function maybe_create_directory( $destination_dir_path ) {
}
}

/**
* Gets the content of a version tag in any doc block in the given source code string.
*
* The version tag might be specified as "@version x.y.z" or "Version: x.y.z" and it can
* be preceded by an asterisk (*).
*
* @param string $code_str The source code string to look into.
* @return null|string The detected version string.
*/
private function get_version_in_code( $code_str ) {
$tokens = array_values(
array_filter(
token_get_all( $code_str ),
function ( $token ) {
return ! is_array( $token ) || T_WHITESPACE !== $token[0];
}
)
);
foreach ( $tokens as $token ) {
if ( T_DOC_COMMENT === $token[0] ) {
$version = $this->get_version_in_docblock( $token[1] );
if ( null !== $version ) {
return $version;
}
}
}
return null;
}

/**
* Gets the content of a version tag in a docblock.
*
* @param string $docblock Docblock to parse.
* @return null|string The content of the version tag.
*/
private function get_version_in_docblock( $docblock ) {
$docblocktags = $this->parse_doc_block( $docblock );
if ( isset( $docblocktags['version'] ) ) {
return $docblocktags['version'];
}
return null;
}

/**
* Parses a docblock and gets an array of tags with their values.
*
* The tags might be specified as "@version x.y.z" or "Version: x.y.z" and they can
* be preceded by an asterisk (*).
*
* This code is based on the 'phpactor' package.
* @see https://github.com/phpactor/docblock/blob/master/lib/Parser.php
*
* @param string $docblock Docblock to parse.
* @return array<string, string> Associative array of parsed data.
*/
private function parse_doc_block( $docblock ) {
$tag_documentor = '{@([a-zA-Z0-9-_\\\]+)\s*?(.*)?}';
$tag_property = '{\s*\*?\s*(.*?):(.*)}';
$lines = explode( PHP_EOL, $docblock );
$tags = [];

foreach ( $lines as $line ) {
if ( 0 === preg_match( $tag_documentor, $line, $matches ) ) {
if ( 0 === preg_match( $tag_property, $line, $matches ) ) {
continue;
}
}

$tag_name = trim( isset( $matches[1] ) ? strtolower( $matches[1] ) : '' );
$metadata = trim( isset( $matches[2] ) ? $matches[2] : '' );

$tags[ $tag_name ] = $metadata;
}
return $tags;
}

/**
* Run PHP's escapeshellcmd() then undo escaping known intentional characters.
*
Expand Down
Loading