Skip to content
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

Composer plugin v3 #63

Draft
wants to merge 19 commits into
base: main
Choose a base branch
from

Conversation

justinbeaty
Copy link
Contributor

@justinbeaty justinbeaty commented Dec 5, 2024

I made a couple more changes to improve the autoloading in Maho, feedback is welcome!

Cleanup app/Mage.php

First, I migrated the "startup" code over to app/bootstrap.php, so that app/Mage.php is a pure class file.

I also removed the libxml_disable_entity_loader stuff as it's been fixed since 2014. To quote a comment from 2020 in the linked PHP bug report: "If you're still using libxml < 2.9.0, better change that."

Finally, I created a lib/Maho.php class instead of using functions defined in functions.php. So for example: Maho::findFile($file) instead of mahoFindFileInIncludePath($path).

Pure autoloading

Everything can now be autoloaded by Composer like any other modern codebase, and you no longer need to require app/bootstrap.php and app/Mage.php.

This makes public/index.php (and any other custom scripts) much simpler. Just require the autoloader, then you can use any class or function. For example:

<?php # public/myscript.php

require '../vendor/autoload.php';

Mage::init();
Mage::helper('core')->uniqHash(); // It works!

For legacy scripts you can still do it the old way, but if you require the autoloader AND require app/Mage.php you'll get an error: "Cannot declare class Mage, because the name is already in use". Simply changing the require 'app/Mage.php' to a require_once will fix that, but this scenario should be pretty rare.

New utility functions

There's some new helper functions for working with installed modules:

# Glob packages
foreach (Maho::globPackages('/app/etc/modules/*.xml') as $file) {
    // $file is an absolute path
}

# Find file (already existed, but improved)
$file = Maho::findFile('app/code/core/Mage/Core/Helper/Data.php'); 
// $file = '/home/www/maho/vendor/mahocommerce/maho/app/code/core/Mage/Core/Helper/Data.php'

# Convert back to relative path
$file = Maho::toRelativePath('/home/www/maho/vendor/mahocommerce/maho/app/code/core/Mage/Core/Helper/Data.php');
// $file = 'app/code/core/Mage/Core/Helper/Data.php';

# See more at lib/Maho.php

Performance improvements

We gain a modest 1-2 ms as we don't need to build paths or scan app/etc/includes/*.php at runtime. These are pre-scanned during the composer dump command.

I believe there's also a possibly significant performance gain to be had with loading phtml files, but that's for another PR...

Modman support

I added modman support to the composer plugin. For example assume you install Cm_Diehard via composer.

By default, you'll end up with files such as vendor/colinmollenhour/cm_diehard/code/etc/config.xml, but this isn't going to work with Maho.

With modman support, the composer plugin will create symlinks in a special folder vendor/mahocommerce/maho-modman-symlinks/$packageName, for example:

vendor/mahocommerce/maho-modman-symlinks/colinmollenhour/cm_diehard/app/code/community/Cm/Diehard/etc/config.xml
# is symlinked to ↓
vendor/colinmollenhour/cm_diehard/code/etc/config.xml

Then, if the composer plugin detects this folder, we'll use it as the module's install path instead. The feature will avoid creating symlinks if there's no actual difference in the source vs target files. For example modman files created with generate-modman don't need symlinks.

It even supports modman's @import feature which was never supported in the OM plugin. That means you can define multiple modules in a single repo.

I created some more test modules. Add the composer repo, then run: composer require modman/testpage modman/simple modman/complex modman/nolink modman/composermap

Here's how the symlinks look -- Click to expand

$ tree vendor/mahocommerce/maho-modman-symlinks/
vendor/mahocommerce/maho-modman-symlinks/
└── modman
    ├── complex
    │   └── app
    │       ├── code
    │       │   └── local
    │       │       └── Modman
    │       │           ├── ComplexA -> ../../../../../../../../modman/complex/modules/mod_a/code
    │       │           └── ComplexB -> ../../../../../../../../modman/complex/modules/mod_b/code
    │       ├── etc
    │       │   └── modules
    │       │       ├── Modman_ComplexA.xml -> ../../../../../../../modman/complex/modules/mod_a/module.xml
    │       │       └── Modman_ComplexB.xml -> ../../../../../../../modman/complex/modules/mod_b/module.xml
    │       └── locale
    │           ├── en_US
    │           │   ├── Modman_ComplexA.csv -> ../../../../../../../modman/complex/locale/en_US/Modman_ComplexA.csv
    │           │   └── Modman_ComplexB.csv -> ../../../../../../../modman/complex/locale/en_US/Modman_ComplexB.csv
    │           └── it_IT
    │               ├── Modman_ComplexA.csv -> ../../../../../../../modman/complex/locale/it_IT/Modman_ComplexA.csv
    │               └── Modman_ComplexB.csv -> ../../../../../../../modman/complex/locale/it_IT/Modman_ComplexB.csv
    ├── composermap
    │   ├── lib
    │   │   ├── bar.php -> ../../../../../modman/composermap/lib/bar.php
    │   │   └── foo.php -> ../../../../../modman/composermap/lib/foo.php
    │   ├── public
    │   │   └── js
    │   │       ├── bar.js -> ../../../../../../modman/composermap/js/bar/bar.js
    │   │       └── foo.js -> ../../../../../../modman/composermap/js/foo/foo.js
    │   └── README.md -> ../../../../modman/composermap/README.md
    ├── simple
    │   └── app
    │       ├── code
    │       │   └── local
    │       │       └── Modman
    │       │           └── Simple -> ../../../../../../../../modman/simple/code
    │       ├── design
    │       │   └── frontend
    │       │       └── base
    │       │           └── default
    │       │               └── template
    │       │                   └── modman
    │       │                       └── simple -> ../../../../../../../../../../../modman/simple/templates
    │       └── etc
    │           └── modules
    │               └── Modman_Simple.xml -> ../../../../../../../modman/simple/module.xml
    └── testpage
        └── app
            ├── code
            │   └── local
            │       └── Modman
            │           └── Testpage -> ../../../../../../../../modman/testpage/code
            └── etc
                └── modules
                    └── Modman_Testpage.xml -> ../../../../../../../modman/testpage/module.xml

40 directories, 13 files

In addition to modman support, it also supports composer.json extra.map.

I also had written a package.xml parser, but I believe it's useless since I don't think you can define any custom mappings there. In other words, app/code/local/My/Module always links to the same location, which already works.

Bug fixes

  • Before if you had simply created a folder like app/code/core/Mage/Core/sql/core_setup in a module or starter pack, it would have prevented the files in mahocommerce/maho from running. This is fixed now. Technically you could override a single setup script, but of course that's not recommended.

  • I'm pretty sure there was a discrepancy in the order that module's etc/config.xml files were loaded vs models, blocks, phtml files, etc. I didn't confirm this but it should be fixed now anyway. This would only cause problems if two composer packages define the same module like some 3rd party modules do (i.e AW_Core) but one version was outdated and they weren't compatible.

Other comments

  • The new composer plugin would need to be released as v3, as Maho 24.11.0 won't work with it.

  • Besides the possibility of the "Cannot declare class Mage" error, and the removal of the mahoFindFileInIncludePath(), etc functions, I don't believe there are any other breaking changes.

  • I think app/code/core/Mage/Core/functions.php really should be at lib/Mage/functions.php, but it's not really a big deal where it is now. Maybe eventually we can remove a lot of those functions anyway...

  • Instead of lib/Maho.php we could put it somewhere like lib/Maho/Core.php and have it loaded via PSR-4. So instead of Maho::findFile() it would be \Maho\Core::findFile(). Might be useful in the long term if we want to split the file up into \Maho\Core, \Maho\ErrorHandler, \Maho\Whatever, etc.

@justinbeaty justinbeaty marked this pull request as draft December 5, 2024 22:25
@justinbeaty justinbeaty force-pushed the topic-composer-plugin-v3 branch from ea560a2 to 9339f89 Compare December 6, 2024 21:33
@justinbeaty justinbeaty force-pushed the topic-composer-plugin-v3 branch from 19f86b8 to 6f603e9 Compare December 6, 2024 21:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants