5
votes

I would like to copy some file located inside a package after I installed this package from Composer.

Actually, I would like that, after I install or update a package from Composer, copy some file which might be inside the downloaded package to another directory. I use scripts, with the post-package-install and post-package-update command, but I do not find how to get the install path.

This is my current script :

use Composer\Script\PackageEvent;

class MyScript {

public static function copyFiles(PackageEvent $event)
{
    $package = $event->getOperation()->getPackage();

    $originDir = $package->someFunctionToFind(); #Here, I should retrieve the install dir

    if (file_exists($originDir) && is_dir($originDir)) {
        //copy files from $originDir to a new location
    } 

}
}

Does anybody knows how to get the install dir of the installed/updated package from the PackageEvent class (which is provided in parameter) ?

NOTE :

I tryed $event->getOperation()->getPackage->targetDir() but this does not provide the install path, but the targetDir of the package, defined in composer.json

1

1 Answers

8
votes

I could get the install path with the Composer\Installation\InstallationManager::getInstallPath method.

Theoric answer :

use Composer\Script\PackageEvent;

class MyScript {

public static function copyFiles(PackageEvent $event)
{
    $package = $event->getOperation()->getPackage();
    $installationManager = $event->getComposer()->getInstallationManager();

    $originDir = $installationManager->getInstallPath($package);

    if (file_exists($originDir) && is_dir($originDir)) {
        //copy files from $originDir to a new location
    } 

}
}

But this answer is theoric because I could not find a soluce to debug my code without really installing a package (which was painful: I should have to remove a package, and reinstall it to check my code).

So I switch to post-install-cmd and post-update-cmd, and my come became :

use Composer\Script\CommandEvent; #the event is different !

class MyScript {

public static function copyFiles(CommandEvent $event)
{
    // wet get ALL installed packages
    $packages = $event->getComposer()->getRepositoryManager()
          ->getLocalRepository()->getPackages();
    $installationManager = $event->getComposer()->getInstallationManager();

    foreach ($packages as $package) {
         $installPath = $installationManager->getInstallPath($package);
         //do my process here
    }
}
}

Do not forget to add the command to composer.json :

"scripts": {

        "post-install-cmd": [
            "MyScript::copyFiles"
        ],
        "post-update-cmd": [
            "MyScript::copyFiles"
        ]
}

To debug the code, I had to run composer.phar run-script post-install-cmd.

NOTE : this code should work with psr4. For psr0, it might be necessary to add a $package->targetDir() to get the correct install path. Feel free to comment or improve my answer.