mozart
mozart copied to clipboard
classmap_prefix duplication and other issues with classmaps
{
"name": "ethereumico/ether-and-erc20-tokens-woocommerce-payment-gateway",
"description": "Ether and ERC20 tokens WooCommerce Payment Gateway enables customers to pay with Ether or any ERC20 or ERC223 token on your WooCommerce store.",
"type": "project",
"repositories": [
{
"type": "vcs",
"url": "https://github.com/olegabr/web3.php"
},
{
"type": "vcs",
"url": "https://github.com/olegabr/php-keccak"
}
],
"require": {
"olegabr/web3.php": "~0.1",
"freemius/wordpress-sdk": "^2.4",
"woocommerce/action-scheduler": "dev-master"
},
"license": "GPLv3",
"authors": [
{
"name": "EthereumICO",
"email": "[email protected]"
}
],
"minimum-stability": "dev",
"require-dev": {
"coenjacobs/mozart": "dev-master"
},
"extra": {
"mozart": {
"dep_namespace": "\\Ethereumico\\Epg\\Dependencies\\",
"dep_directory": "/vendor-epg/",
"classmap_directory": "/vendor-epg/classes/",
"classmap_prefix": "ether_and_erc20_tokens_woocommerce_payment_gateway_",
"packages": [
"freemius/wordpress-sdk",
"guzzlehttp/guzzle",
"guzzlehttp/promises",
"guzzlehttp/psr7",
"olegabr/keccak",
"olegabr/web3.php",
"paragonie/constant_time_encoding",
"paragonie/random_compat",
"phpseclib/phpseclib",
"psr/http-message",
"ralouphie/getallheaders",
"symfony/polyfill-intl-idn",
"symfony/polyfill-intl-normalizer",
"symfony/polyfill-mbstring",
"symfony/polyfill-php72",
"woocommerce/action-scheduler"
],
"delete_vendor_directories": true
}
},
"scripts": {
"post-install-cmd": [
"\"vendor/bin/mozart\" compose",
"composer dump-autoload"
],
"post-update-cmd": [
"\"vendor/bin/mozart\" compose",
"composer dump-autoload"
]
}
}
It created file /home/USER/PROJECT/vendor-epg/classes/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php
with contents:
<?php
class ether_and_erc20_tokens_woocommerce_payment_gateway_ether_and_erc20_tokens_woocommerce_payment_gateway_ether_and_erc20_tokens_woocommerce_payment_gateway_ether_and_erc20_tokens_woocommerce_payment_gateway_Normalizer extends Symfony\Polyfill\Intl\ether_and_erc20_tokens_woocommerce_payment_gateway_ether_and_erc20_tokens_woocommerce_payment_gateway_ether_and_erc20_tokens_woocommerce_payment_gateway_ether_and_erc20_tokens_woocommerce_payment_gateway_Normalizer\Normalizer
{
Three issues here:
- class prefix added 4 times
-
Symfony\Polyfill\Intl\
namespace is not prefixed withEthereumico\Epg\Dependencies\
- The last namespace before class name is prefixed with class name prefix (4 times of course):
ether_and_erc20_tokens_woocommerce_payment_gateway_ether_and_erc20_tokens_woocommerce_payment_gateway_ether_and_erc20_tokens_woocommerce_payment_gateway_ether_and_erc20_tokens_woocommerce_payment_gateway_Normalizer
The /home/USER/PROJECT/vendor-epg/Symfony/Polyfill/Intl/Normalizer/Normalizer.php
file is defined correctly as:
<?php
namespace \Ethereumico\Epg\Dependencies\Symfony\Polyfill\Intl\Normalizer;
class Normalizer
The following ClassmapReplacer.php
will skip classnames that already begin with the prefix.
<?php
/**
* The purpose of this file is to find and update classnames (and interfaces...) in their declarations.
* Those replaced are recorded and their uses elsewhere are updated in a later step.
*/
namespace CoenJacobs\Mozart\Replace;
class ClassmapReplacer extends BaseReplacer
{
/** @var string[] */
public $replacedClasses = [];
/** @var string */
public $classmap_prefix;
public function replace($contents)
{
return preg_replace_callback(
"
/ # Start the pattern
namespace\s+[a-zA-Z0-9_\x7f-\xff\\\\]+[;{\s\n]{1}.*?(?=namespace|$)
# Look for a preceeding namespace declaration, up until
# a potential second namespace declaration
| # if found, match that much before repeating the search
# on the remainder of the string
[^a-zA-Z0-9_\x7f-\xff]+ # After a non-class character,
{$this->classmap_prefix} # match an already prefixed classname
[a-zA-Z0-9_\x7f-\xff]+ # before continuing on the remainder of the string
|
(?:abstract\sclass|class|interface)\s+ # Look behind for class, abstract class, interface
([a-zA-Z0-9_\x7f-\xff]+) # Match the word until the first
# non-classname-valid character
\s? # Allow a space after
(?:{|extends|implements|\n) # Class declaration can be followed by {, extends,
# implements, or a new line
/sx", // # dot matches newline, ignore whitespace in regex.
function ($matches) use ($contents) {
// If we're inside a namespace other than the global namesspace, just return.
if (preg_match('/^namespace\s+[a-zA-Z0-9_\x7f-\xff\\\\]+[;{\s\n]{1}.*/', $matches[0])) {
return $matches[0];
}
if (preg_match("/[^a-zA-Z0-9_\x7f-\xff]+{$this->classmap_prefix}[a-zA-Z0-9_\x7f-\xff]+/", $matches[0])) {
return $matches[0];
}
// The prepended class name.
$replace = $this->classmap_prefix . $matches[1];
$this->saveReplacedClass($matches[1], $replace);
return str_replace($matches[1], $replace, $matches[0]);
},
$contents
);
}
public function saveReplacedClass($classname, $replacedName)
{
$this->replacedClasses[ $classname ] = $replacedName;
}
}
It is PR #101 with this added:
[^a-zA-Z0-9_\x7f-\xff]+ # After a non-class character,
{$this->classmap_prefix} # match an already prefixed classname
[a-zA-Z0-9_\x7f-\xff]+ # before continuing on the remainder of the string
|
Updating Replacer.php:125
to :
'/(.*)([^a-zA-Z0-9_\x7f-\xff\\\\])'. $original . '([^a-zA-Z0-9_\x7f-\xff])/U',
fixes the extends
incorrect replacement but needs a bit more thought and testing before making a PR.
PhpStorm was highlighting the namespace in Symphony/Polyfill/Intl/Normalizer/Normalizer.php
with "undefined namespace Intl" and "undefined constant Normalizer". I changed composer.json
's "dep_namespace": "\\Ethereumico\\Epg\\Dependencies\\",
to "dep_namespace": "Ethereumico\\Epg\\Dependencies\\",
and the message went away.
That PR that was referred above is now released as part of Mozart 0.6.0. @olegabr can you confirm this is now resolved?