- Sponsor
-
Notifications
You must be signed in to change notification settings - Fork 57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Classmap implementation #4
Changes from 5 commits
4a4b5e1
f7ef397
38969f7
31d0a22
f8ea2cd
e206a50
a35ee8c
44ac13c
05fea7d
c91d232
c8542f7
dd3333f
a27c4a6
05f9900
03d830f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,5 +4,5 @@ | |
|
||
interface Autoloader | ||
{ | ||
|
||
public function processConfig( $config ); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<?php | ||
|
||
namespace CoenJacobs\Mozart\Composer\Autoload; | ||
|
||
class Classmap implements Autoloader | ||
{ | ||
/** @var array */ | ||
public $paths = []; | ||
|
||
public function processConfig($config) | ||
{ | ||
foreach( $config as $value) { | ||
array_push( $this->paths, $value); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<?php | ||
|
||
namespace CoenJacobs\Mozart\Composer\Autoload; | ||
|
||
abstract class NamespaceAutoloader implements Autoloader | ||
{ | ||
/** @var string */ | ||
public $namespace = ''; | ||
|
||
/** @var array */ | ||
public $paths = []; | ||
|
||
public function processConfig($config) | ||
{ | ||
foreach( $config as $key => $value) { | ||
$this->namespace = $key; | ||
array_push( $this->paths, $value); | ||
} | ||
} | ||
|
||
public function getSearchNamespace() | ||
{ | ||
return $this->namespace; | ||
} | ||
|
||
public function getNamespacePath() | ||
{ | ||
return ''; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,9 +2,10 @@ | |
|
||
namespace CoenJacobs\Mozart; | ||
|
||
use CoenJacobs\Mozart\Composer\Autoload\Psr0; | ||
use CoenJacobs\Mozart\Composer\Autoload\Psr4; | ||
use CoenJacobs\Mozart\Composer\Autoload\NamespaceAutoloader; | ||
use CoenJacobs\Mozart\Composer\Package; | ||
use CoenJacobs\Mozart\Replace\ClassmapReplacer; | ||
use CoenJacobs\Mozart\Replace\NamespaceReplacer; | ||
use League\Flysystem\Adapter\Local; | ||
use League\Flysystem\Filesystem; | ||
use Symfony\Component\Finder\Finder; | ||
|
@@ -20,17 +21,21 @@ class Mover | |
/** @var \stdClass */ | ||
protected $config; | ||
|
||
/** @var array */ | ||
protected $replacedClasses = []; | ||
|
||
public function __construct( $workingDir, $config ) | ||
{ | ||
$this->workingDir = $workingDir; | ||
$this->targetDir = $config->dep_directory; | ||
$this->config = $config; | ||
} | ||
|
||
public function deleteTargetDir() | ||
public function deleteTargetDirs() | ||
{ | ||
$filesystem = new Filesystem(new Local($this->workingDir)); | ||
$filesystem->deleteDir($this->targetDir); | ||
$filesystem->deleteDir($this->config->dep_directory); | ||
$filesystem->deleteDir($this->config->classmap_directory); | ||
} | ||
|
||
public function movePackage(Package $package) | ||
|
@@ -39,23 +44,17 @@ public function movePackage(Package $package) | |
$filesystem = new Filesystem(new Local($this->workingDir)); | ||
|
||
foreach( $package->autoloaders as $autoloader ) { | ||
foreach( $autoloader->paths as $path ) { | ||
foreach ($autoloader->paths as $path) { | ||
$source_path = $this->workingDir . '/vendor/' . $package->config->name . '/' . $path; | ||
|
||
$finder->files()->in($source_path); | ||
|
||
$searchNamespace = $autoloader->namespace; | ||
|
||
if ( is_a($autoloader, Psr4::class)) { | ||
$searchNamespace = trim($autoloader->namespace, '\\'); | ||
} | ||
|
||
foreach ($finder as $file) { | ||
if ( is_a($autoloader, Psr0::class)) { | ||
$targetFile = str_replace($this->workingDir, $this->config->dep_directory, $file->getRealPath()); | ||
} else { | ||
$namespacePath = str_replace('\\', '/', $autoloader->namespace); | ||
if (is_a($autoloader, NamespaceAutoloader::class)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should prefer There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks, fixed: 05fea7d |
||
$namespacePath = $autoloader->getNamespacePath(); | ||
$targetFile = str_replace($this->workingDir, $this->config->dep_directory . $namespacePath, $file->getRealPath()); | ||
} else { | ||
$targetFile = str_replace($this->workingDir, $this->config->classmap_directory, $file->getRealPath()); | ||
} | ||
|
||
$targetFile = str_replace('/vendor/' . $package->config->name . '/' . $path, '', $targetFile); | ||
|
@@ -65,22 +64,53 @@ public function movePackage(Package $package) | |
$targetFile | ||
); | ||
|
||
if ( '.php' == substr($targetFile, '-4', 4 ) ) { | ||
if ('.php' == substr($targetFile, '-4', 4)) { | ||
$contents = $filesystem->read($targetFile); | ||
|
||
$contents = preg_replace_callback( | ||
'/'.addslashes($searchNamespace).'([\\\|;])/U', | ||
function($matches) { | ||
$replace = trim($matches[0], $matches[1]); | ||
return $this->config->dep_namespace . $replace . $matches[1]; | ||
}, | ||
$contents | ||
); | ||
if (is_a($autoloader, NamespaceAutoloader::class)) { | ||
$replacer = new NamespaceReplacer(); | ||
$replacer->dep_namespace = $this->config->dep_namespace; | ||
} else { | ||
$replacer = new ClassmapReplacer(); | ||
} | ||
|
||
$replacer->setAutoloader($autoloader); | ||
$contents = $replacer->replace($contents); | ||
|
||
if ( is_a($replacer, ClassmapReplacer::class)) { | ||
$this->replacedClasses = array_merge($this->replacedClasses, $replacer->replacedClasses); | ||
} | ||
|
||
$filesystem->put($targetFile, $contents); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
public function replaceClassmapNames() | ||
{ | ||
$classmap_path = $this->workingDir . $this->config->classmap_directory; | ||
$finder = new Finder(); | ||
$finder->files()->in($classmap_path); | ||
|
||
$filesystem = new Filesystem(new Local($this->workingDir)); | ||
|
||
foreach ($finder as $file) { | ||
$file_path = str_replace($this->workingDir, '', $file->getRealPath()); | ||
$contents = $filesystem->read($file_path); | ||
|
||
foreach( $this->replacedClasses as $original => $replacement ) { | ||
$contents = preg_replace_callback( | ||
'/\W('.$original.')(?:\(|\:\:)/U', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will miss a couple of scenarios. The ones I can think of right now:
It will also probably break when using relative namespaces, like the following:
I'm not really sure how you can add cases like these without getting false positives as well, though. I don't think this can properly be handled by regexes, you should look into using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks @schlessera, I would love to make this as bullet proof as I can, but don't want this to distract too much from actually implementing the classmap handler. Improving the replacing logic can obviously be an ongoing process. Can you please post this as an issue, so I can handle it accordingly ( - it would be amazing if the GitHub UI allowed me to promote this comment to an issue, directly from here)? |
||
function ($matches) use ($replacement) { | ||
return str_replace($matches[1], $replacement, $matches[0]); | ||
}, | ||
$contents | ||
); | ||
} | ||
|
||
$filesystem->put($file_path, $contents); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<?php | ||
|
||
namespace CoenJacobs\Mozart\Replace; | ||
|
||
use CoenJacobs\Mozart\Composer\Autoload\Autoloader; | ||
|
||
abstract class BaseReplacer implements Replacer | ||
{ | ||
/** @var Autoloader */ | ||
public $autoloader; | ||
|
||
public function setAutoloader( $autoloader ) | ||
{ | ||
$this->autoloader = $autoloader; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<?php | ||
|
||
namespace CoenJacobs\Mozart\Replace; | ||
|
||
class ClassmapReplacer extends BaseReplacer | ||
{ | ||
/** @var array */ | ||
public $replacedClasses = []; | ||
|
||
public function replace( $contents ) | ||
{ | ||
return preg_replace_callback( | ||
'/(?:\W[abstract]*class |interface )([a-zA-Z\_]+)[ ]*{/U', | ||
function ($matches) { | ||
$replace = 'CJDT_' . $matches[1]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed: a35ee8c |
||
$this->saveReplacedClass($matches[1], $replace); | ||
return str_replace($matches[1], $replace, $matches[0]); | ||
}, | ||
$contents | ||
); | ||
} | ||
|
||
public function saveReplacedClass($classname, $replacedName) | ||
{ | ||
$this->replacedClasses[ $classname ] = $replacedName; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<?php | ||
|
||
namespace CoenJacobs\Mozart\Replace; | ||
|
||
class NamespaceReplacer extends BaseReplacer | ||
{ | ||
/** @var string */ | ||
public $dep_namespace = ''; | ||
|
||
public function replace($contents) | ||
{ | ||
$searchNamespace = $this->autoloader->getSearchNamespace(); | ||
|
||
return preg_replace_callback( | ||
'/' . addslashes($searchNamespace) . '([\\\|;])/U', | ||
function ($matches) { | ||
$replace = trim($matches[0], $matches[1]); | ||
return $this->dep_namespace . $replace . $matches[1]; | ||
}, | ||
$contents | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<?php | ||
|
||
namespace CoenJacobs\Mozart\Replace; | ||
|
||
interface Replacer | ||
{ | ||
public function setAutoloader($autoloader); | ||
public function replace($contents); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Classmap autoloader should support having files in the array, not just directories. Potentially look into splitting the
$paths
variable up in$directories
and$files
.