Path-problems with kirby-plugin-path by composer install to custom dir?

Hi,

i would like to install kirby and some plugins by composer to a custom directory ‘src’ with a public folder setup. i achive that by the following config in composer.json

{
  "require": {
    "php": ">=7.4.0 <8.2.0",
    "getkirby/cms": "^3.6"
  },
  "config": {
    "vendor-dir": "src/vendor",
    "optimize-autoloader": true,
    "allow-plugins": {
      "getkirby/composer-installer": true
    }
  },
  "extra": {
    "kirby-cms-path": false,
    "kirby-plugin-path": "src/site/plugins"
  }
}

so far so good. kirby is running.

grafik


unfortenetly i get some really bad path-problems, after requiring plugins, which stops kirby
composer require beebmx/kirby-env

the plugin is installed correctly to src/site/plugins/…
grafik

but there are some issues with the pluginpath after reloading the site

in vendor/composer/autoload_classmap.php and co. (autoload_psr4.php, autoload_static.php…) is the path from kirby-plugin-path, that contains ‘src’ - but i am already in ‘src’ and so i need to have that a bit more relative - maybe relative to the vendor-dir…

return array(
    'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
    'Beebmx\\KirbyEnv' => $baseDir . '/src/site/plugins/kirby-env/src/KirbyEnv.php',
    'Carbon\\AbstractTranslator' => $vendorDir . '/nesbot/carbon/src/Carbon/AbstractTranslator.php',

furthermore in the autoload_static.php also the basedir has one ‘/…’ to much :frowning:
(i guess that is the path to the plugin from project-root / composer.json, but unfortenetly in my case, that’s one level to much

 array (
        'Beebmx\\' => 
        array (
            0 => __DIR__ . '/../../..' . '/src/site/plugins/kirby-env/src',
        ),

I was able to change some paths manually in ‘autoload_static.php’, so kirby runs again, also with Kirby-Env, but i would like to have that a bit more automaticly…

public static $classMap = array (
        //'Beebmx\\KirbyEnv' => __DIR__ . '/../../..' . '/src/site/plugins/kirby-env/src/KirbyEnv.php',
        'Beebmx\\KirbyEnv' => __DIR__ . '/../..' . '/site/plugins/kirby-env/src/KirbyEnv.php',

Unfortenetly i am not that experienced with composer… and also not with the PluginInstaller by @lukasbestle
So, does anyone knows how to fix that or set the pluginpath for the autoloader more relative to the vendor-dir? That would be very very nice!

Thanks in advance!

Kirby’s Composer installer only provides the custom install path to Composer, the installation itself and the generation of the autoloader is then handled by Composer. So this looks to be a Composer bug.

Which version of Composer are you using?

just upgraded from 2.2.6 to 2.2.7
unfortenetly the same behavior :frowning:

Hm, I tried to test your setup and I didn’t run into those issues, actually.

{
    "require": {
      "getkirby/cms": "^3.0",
        "beebmx/kirby-env": "^3.0"
    },
    "config": {
        "vendor-dir": "src/vendor",
        "optimize-autoloader": true,
        "allow-plugins": {
          "getkirby/composer-installer": true
        }
    },
    "extra": {
      "kirby-cms-path": false,
      "kirby-plugin-path": "src/site/plugins"
    }
}

resulting folder setup

index.php

<?php

include __DIR__ . '/../vendor/autoload.php';

$host = Url::host();
$url  = 'http://' . $host;

$kirby = new Kirby([
    'roots' => [
      'index'   => __DIR__,
      'base'    => $base    = dirname(__DIR__),
      'site'    => $base . '/site',
      'content' => $base . '/storage/content',
      'media'   => $base . '/storage/media',
      'assets'  => $base . '/assets'
    ],
    'urls' => [
      'media'  => $url . '/' . $base . 'storage/media',
      'assets' => $url . '/' . $base . '/assets',
    ],
  ]);

echo $kirby->render();

autoload_classmap.php etc. have the same paths as in your setup.

'Beebmx\\KirbyEnv' => $baseDir . '/src/site/plugins/kirby-env/src/KirbyEnv.php',
'Beebmx\\' => 
array (
    0 => __DIR__ . '/../../..' . '/src/site/plugins/kirby-env/src',
 ),

@texnixe it looks like, your composer.json is inside ‘src’, isn’t it?
the image is not that clear for me.
but if, i don’t understand, why it works anyway.
if i do that, i will get an additional folder src in src - as expected.

if i put my composer.json inside ‘src’, remove the custom vendor-dir and the custom kirby-plugin-path and starts from cd src && composer install, it works - but that would be some kind of emergency solution.

i would really prefer to have the composer.json on the project-root. like all other config files
and i really would like to know, if that works that way on your side.
i just did my setup again, replaced mine with your index.php. same error:

No, the composer.json is in the project folder in my example.

Bildschirmfoto 2022-03-06 um 11.41.42

It just looks wrong in the screenshot of my last post.

ok, that is cool.
i just did a simple test, with a local php-server runs by composer start - thats works also!
maybe i have to dig inside my docker setup this evening!
what is your server?
what happens, if you simulate the build, and copy all of the src to dist?
cause, that would be the next problem, if the plugin-path is hardcoded to ‘src’ :thinking:

Locally, I’m using Valet.

What build process?

this setup should be the base for a more complex structure incl. a build-system, which later copies all php, vendor, compiles frontend-javascript or astro-things to a dist-folder. is not included yet, but can be simulated if you copy the src to dist

grafik

But that will not work, because then the autoloader paths will be wrong.

unfortenetly yes - thats the reason why i wanted to have some kind of relative kiry-plugin-path.
but i guess i have to go with the solution, that the composer.json is inside src - so it works independent of the parent folders… or maybe, i need some kind of composer.build.json or maybe wait for the upcoming composer 2.3… don’t know

But i am still wondering, why that is not working with the docker-setup, but works if i change the path…

however: i thank you very much for your support even on the weekend! :pray:

so, the bug comes indeed from my docker setup.
becaue i mapped the folder ‘src’ to a folder ‘dev’

volumes:
      - ./src:/var/www/web/dev:rw,delegated
      - ./dist:/var/www/web/dist:rw,delegated
 'Beebmx\\' => 
        array (
            0 => __DIR__ . '/../../..' . '/src/site/plugins/kirby-env/src',
        ),

the autoloader cannot find src, if it is not available!

if i change the folder on the docker container, it works…

volumes:
      - ./src:/var/www/web/src:rw,delegated

unfortenetly, that issue is still a bit annoying, because i would like to be independent of the parent folders name, for building to dist and also for some hosting-purposes on the live-systems.
i dont want to always have to add the folder src/dist, so autoloader can go one folder deeper and back to src/dist. thats not cool.
it would be nice, if the kirby-plugin-path can be more relative, like all other vendor-paths are,
or maybe it needs a real-path to copy the files to, and a relative path to load by autoloader.
all other vendor files works that way - they don’t care about the parent-folders name.

 'Beebmx\\' => 
        array (
            //0 => __DIR__ . '/../../..' . '/src/site/plugins/kirby-env/src',
            0 => __DIR__ . '/../..' . '/site/plugins/kirby-env/src',
        ),

but like @lukasbestle already said, i guess thats a problem with composer itself. so i will go and have a deeper look there… :smiling_face_with_tear:

thanks you guys!

i still would like to understand that a bit more and have some more questions:

"getkirby/composer-installer": false

if false, composer installs plugins and their vendors to the vendor-dir by it’s repo/composer.json
If plugins are not in site/plugins, we cannot use them?
Also not, if i call them in index.php or config.php?

require dirname(__DIR__) . '/vendor/autoload.php';

$envpath = dirname(__DIR__, 1);
Beebmx\KirbyEnv::load($envpath);

"getkirby/composer-installer": true

if true, composer copies the plugin also to the kirby-plugin-path and updates the autoloader paths?
This is done by composer after the Kirby\ComposerInstaller\PluginInstaller sets the path in getInstallPath?

Thx again!

Regarding the vendor mode: Plugins should be loaded at a specific point in time during Kirby’s initialization. As Kirby currently picks up all plugins from the plugins folder, every piece of code that should be loaded as a plugin should also be stored there.

With the recent addition of new APIs in Composer we might be able to change that requirement in the future (with Kirby being able to pick up plugins from vendor automatically), but that’s the current status. So the false path only actually works for Kirby itself, not plugins. You always need to define a plugin root.

Regarding the installer behavior: Packages are not copied to the plugin root, they are installed there in the first place. :slightly_smiling_face:

that would be really good. i just tested with 2.3-beta. but the behavior is the same - as expected.
nothing changed in the custom-installer. isn’t it?

would be nice to have a real-plugin-path and an autoloader-plugin path in the future.
plugins directly from the vendor of course would be the best!

unfortenetly for now, the above setup ‘composer-install-plugins-into-custom-dir’ won’t work for me that way. i don’t like to add ‘src’ respectively the ‘dist’ folder into my hosting structure. still think about the process, but thank you for clarify.

No, as I said it’s something we can add in the future to make the installer obsolete for Kirby plugins at least. But it’s a feature we first need to add to the Kirby plugin loader.

Could you please post an idea at https://feedback.getkirby.com with a link to GitHub - composer/installers: A Multi-Framework Composer Library Installer?

To be honest I think this is beyond the scope of Kirby’s Composer installer. The installer can not directly influence autoloader generation.

What you can do in your setup is to create a symlink so that the autoloader path resolves to the real path in the end. Or you can generate the autoloader during the deployment so that Composer already knows the actual paths.

I just came across the very same issue. I wonder if anybody found a fitting solution by now?

My setup looks like this:

project-dir
↳ www (public folder)
↳ src (assets, managed by vite)
↳ composer.json
↳ package.json
↳ vite.config.ts
↳ …

I would like to keep composer.json on the root level of the project, but only deploy the contents of www through cli. Basically my cli does a checkout, then build node deps, build composer, then packs up contents of www and deploys it on the server.

That’s why i’ve config custom dirs in composer.json.

 "extra": {
    "kirby-cms-path": false,
    "kirby-plugin-path": "www/site/plugins"
  },
  "config": {
    "optimize-autoloader": true,
    "vendor-dir": "www/vendor/"
  }

The problem is the same as above, the path for plugins generated like this is:

.../composer/../../../www/site/plugins/...

It does work locally (in valet), but not in production, since the www folder will not be deployed (only the contents).

Appart from symlinks or updated process, I guess there is no other solution then putting composer.json inside www and running the commands with --working-dir=www. But maybe someone has a clever idea :slight_smile:

That’s what I would recommend. It is certainly the most reliable and stable solution.

1 Like

i would also put the composer.json into the custom-dir. unfortenetly!
or maybe go with git submodules.
i posted that issue in the composer-repo, but they closed by 'that have to be done by the custom-installer-devs ’ :speak_no_evil:
i hope kirby is going to include plugins directly from the vendor-folder in future and makes the custom installer obsolete.

Thanks for your replies. It’s not thaaat big of a deal but kinda still bothers me, haha.