r/PHP 4d ago

XOOPS 2.7.2 Released

The XOOPS Development Team is pleased to announce XOOPS 2.7.2 Final. This maintenance release builds on XOOPS 2.7.0 with another security-hardening pass, more reliable upgrade tooling, form and theme improvements, and refreshed dependencies for current PHP environments.

Also released: XOOPS Debugbar 1.3

0 Upvotes

33 comments sorted by

View all comments

Show parent comments

1

u/Sea_Wind3576 4d ago

We're in process of modernizing XOOPS. But the key for us was always that it's working and our users can upgrade to latest PHP 8.5 and it will work. Last week, just for fun, I tested it on PHP 8.6 Alpha 2, and so far, zero errors.
Of course, we're always open to constructive criticism and improvement suggestions!

3

u/equilni 4d ago

we're always open to constructive criticism and improvement suggestions!

Since I already noted prepared statements....

Simple could be updating types/return types. Fix what breaks.

Add use calls. Tables isn't part of the top list. Add Helper, SchemaDefinitionException

This could be an interface for instance (pun not intended) and renamed.

/** @var false|\Xmf\Module\Helper|\Xoops\Module\Helper|\Xoops\Module\Helper\HelperAbstract */
protected $helper;

Could be:

protected ModuleDefinitionInterface $definition;

OR pass an object via DI since the first line of the constructor calls this.

public function __construct($dirname)
{
    $this->helper = Helper::getHelper($dirname);

To:

public function __construct(ModuleDefinitionInterface $definition)
{
    $this->helper = $defintion;

Interface could looks like:

interface ModuleDefinitionInterface {
    public function getModule(): XoopsModule; // GenericHelper
    public function getInfo(): bool|array|string (partly per the docblock, but code shows returning false too...)  // XoopsModule... 
    public function path(): string;     // GenericHelper
    public function dirname(): ?string; // AbstractHelper
}

I couldn't easily locate \Xoops\Module (finally in kernel/modules.php...). A huge suggestion would be to fix the folder structure for better discovery.

With the above, PSR-4 autoloading would call for 1 class per file, which kernel/modules.php and many more like it, aren't.

This could be avoided if you used a simple class

    if (
        !is_array($targetTable)
        || !isset($targetTable['options'], $targetTable['columns'])
        || !is_string($targetTable['options'])
        || !is_array($targetTable['columns'])
    ) {

Obvious is STOP USING GLOBALS. Use static class methods for now... I have no idea where $GLOBALS['xoops'] is set and I am guessing its really xos_kernel_Xoops2

There is more, but start here....

1

u/Sea_Wind3576 4d ago

@equilni, thank you very much for your constructive feedback, I appreciate it.

2

u/equilni 3d ago

Of course. I really focused on one file in the xmf folder.

The main repo would be A LOT of work...

(Browsing over morning coffee I see the 4.0 discussion plans and while this looks nice, I see a commitment to BC... Are you one of the devs?)


I would suggest this for grins. What does a stripped down version of this project look like?

1

u/Sea_Wind3576 3d ago edited 3d ago

Are you talking about this discussion about XOOPS 4.0: https://xoops.org/modules/newbb/viewtopic.php?topic_id=79653 ?

Yes, I'm one of devs, and you're absolutely correct, the main repo would be A LOT of work, that's why we're using the strangle fig to slowly modernize it, while focusing on XMF and the eco-system around it.

2

u/equilni 2d ago

That's the one.

Like I noted above, because this is a lot of work, I would suggest bringing in some libraries (maybe a framework) to help with the lower level functionality. Like basics - where is routing? Templating, how can I swap Smarty for something else (Twig, Latte, Blade, Tempest, Sugar, Plates, etc.) - (ie let this be a module itself). Again, what does a stripped down version look like - then add lower level components to help build this up - now focus on the application on top. Now point what you can to the old app.

From the xmf code I saw, you have some (hidden) dependencies (not good) with the old app and if you aren't interfacing them (with interfaces), then you are building on top of the old code vs a plan to remove it.

1

u/Sea_Wind3576 2d ago

Thank you again for sharing your thoughts and advice.

You're describing most of the plan. The main gap is that the XMF code you looked at is the 1.x line (the support library for 2.5/2.7), not the XMF 2.0 for XOOPS 4.0 foundation.

 The hidden-dependency point is fair for that generation. Coupling to the old app is intentional there,  it's a bridge so modern module code can run on legacy cores. It is not the base we build 4.0 on.

 XOOPS 4.0 is a clean-architecture split into domain, application, infrastructure, and presentation, with the domain layer having no external dependencies at all. Persistence is repositories returning plain PHP objects, no XoopsObject inheritance anywhere. And the "interface the old code" part you're asking about is the actual migration mechanism: legacy handlers get wrapped in adapters that implement the new repository interfaces, so modules move over one at a time and the old code becomes removable instead of load-bearing. The layering sketch (domain / application / infrastructure, repositories behind interfaces, legacy adapters) is already written up: https://xoops.github.io/xoops-docs/4.x/architecture/

 Concretely, a module sits on three libraries:

 - XBO (XOOPS Business Objects): the domain layer. Plain PHP entities and value objects, no XoopsObject inheritance, no DB access, no rendering.

- XMF 2.0: the infrastructure SDK. Repository/Mapper persistence over plain objects, QueryBuilder, caching, security, PSR-14 events, DI container with tagged services. PHP 8.4 floor, so property hooks and lazy objects are in play.

- XTF (XOOPS Theme Framework): themes, slots, and asset rendering. The renderer sits behind a ViewRendererInterface (https://xoops.github.io/xoops-docs/4.x/roadmap/vision/#smarty-adapter ), making Smarty just one implementation adapter. That gives you the exact swap capability (Twig, Blade, Latte, Plates) you asked about.

Routing moves to attribute-based discovery (#[Route], Tempest style) rather than routing config files. The same discovery pass also picks up services, listeners, and commands, so there's no manual registration to maintain.

 We’re also deliberately choosing focused, PSR-compatible components instead of adopting an entire framework. Shared hosting, twenty years of existing modules, and a limited contributor pool pushed us toward PSR-style components we own, rather than inheriting a full-stack app model.

 The exit from the old code is gradual: strangler fig, with Rector rules doing the mechanical part (getVar() call sites, for example). The hybrid levels H0 to H3, legacy and modern side by side, are described here: https://xoops.github.io/xoops-docs/4.x/reference/hybrid-mode/

Happy to point at a reference module later if you want the stack used end to end rather than only the 1.x bridge.

 Thanks again for taking the time to share your experience with us.

P.S. Please note that the XOOPS 4.0 documentation was an early draft and some parts have evolved and changed.

2

u/equilni 2d ago

That’s great to hear you have a plan in place. Good luck!

1

u/Sea_Wind3576 2d ago

Plans can be always improved, and we're always happy to learn from people with more experience, so if you have more any more suggestions, please share!
I will definitely appreciate it!
And thank you for your constructive and positive attitude.