How to Fix Breaking 5.7.4 Namespace Change?

Permalink 2 users found helpful
Hi All,

So I must be daft. How do I fix the 5.7.4 namespace breaking change?

According to frz this is a "one or two line fix" and he points to the documentation athttp://www.concrete5.org/documentation/developers/5.7/environment/a... . He also says Andrew has been posting detailed responses in the forums, which I guess refers tohttp://www.concrete5.org/developers/pro-accounts/community-leaders-... but I'm still having issues and don't have enough time for developing by trial-and-error.

I'm getting a whole slew of errors from the linter:

lerteco_membership/models/checkout_session.php
Invalid segment 'Model' in namespace: namespace Concrete\Package\LertecoMembership\Model;
....
lerteco_membership/tools/txns/manual_edit.php
Invalid segment 'Tools' in namespace: namespace Concrete\Package\LertecoMembership\Tools\Txns;


What are the minimum changes I can make to get this working?

I thought about just registering an autoloader function, but I doubt that the linter is smart enough to check for that? Is an autoloader function plus a marketplace exemption all that's needed here? If so, does anybody have any examples?

Otherwise it looks like (based off of andrew's response to someone else's problem):

a) I need to move the [helpers|models|tools|libraries] directories into [package root]/src
b) Change all references to Concrete\Package\LertecoMembership\Src\Model
--> This contradicts Andy's post, but I can't see how it'd work if I were to name it Concrete\Package\LertecoMembership\Model\Src

Is that it?

jshannon
 
mesuva replied on at Permalink Reply
mesuva
Your a) and b) sound correct to me. I think Andrew typo'd the order of the Src\Model in his original post.

The only thing I'm not 100% sure if model/models is a special case and whether there is some automatic renaming between the folder name models and the singular 'model' in the namespace path.

My understanding though is that everything in the src directory (including concrete5's core) doesn't change between singular and plural between the namespace and the folder names.

The exceptions are places outside of the src folder where there are folder names that have come from 5.6 - folders named as plurals (controllers, blocks, tools). In these cases, to keep this convention, but (I think) conform to PSR4 naming rules, there is a bit of automagic going on. controllers->Controller, blocks->Block, etc.

So my suggestion would be to keep everything singular folder name wise in your package src directory and have all the name spaces matching the folders.

In Vivid's recently open sourced ecommerce package for 5.7 there are lots of namespacing examples, perhaps that will help pattern wise -https://github.com/VividWeb/vivid_store...
exchangecore replied on at Permalink Reply
exchangecore
This should work:
protected $pkgAutoloaderRegistries = array(
        'models' => 'Concrete\\Package\\LertecoMembership\\Model'
    );


I think this essentially registers the 'models' directory (relative to the package) to 'Concrete\Package\LertecoMemeber\Model' namespace. Hope this helps.

Ideally you really should move things to Src if/when you can (I think the linter will still flag your package if you use this method but prb admins should be able to override that). This is simply a bandaid.
RadiantWeb replied on at Permalink Reply
RadiantWeb
/models is not registered anymore. you either need to A) register /models in your package controller, or B) simply move them into your packages /src folder.

For example: I moved /packages/problog/models/problog_list.php to

/packages/problog/src/Problog/ProblogList.php (note caps)

Once inside your /src you need strict PSR4 naming.

The namespace for this is \Concrete\Packages\Problog\Src\Problog\ProblogList

One bug with src is composer. Some composer references are not routed correctly. Such as target types - They currently are incorrectly using \Concrete\Package\src\..... instead of \Concrete\Package\Src\.... So you end up having to register a bogus namespace to trick it. (dumb)

You could just as well register a custom namespace in your package controller with:

$psr4_loader = new Psr4ClassLoader(); 
$psr4_loader->addPrefix('\\Concrete\\Package\\Problog\\Custom', __DIR__ . '/custom'); 
$psr4_loader->register();


ChadStrat
jshannon replied on at Permalink Reply
jshannon
Thanks exchangecore and chad.

Have you tried to submit anything to the MP with this setup?

I want to keep my Models / Tools / Libraries directories, and the linter has flagged them. I can't imagine the linter is that smart, so is it just matching on the text "models", "tools", etc? Or does it exclude instances where it's after /src?
exchangecore replied on at Permalink Reply
exchangecore
I'm about 99% sure that it has a list of valid "starts with ...", and if you define a namespace that isn't in that list it flags it. So yes It will get flagged if you don't put them under src (but you can put anything you want under the Concrete\Package\PackageHandle\Src namespace), and I think that new stuff going up might get some push back from the PRB if there's not a good reason for you having it there, but anything legacy should get waved through without issue.

Edit: To clarify
namespace Concrete\Package\LertecoMembership\Src\Models

Is completely valid and the preferred way for you to include your own classes that aren't one of them that fall into those special namespace areas (attributes, controllers, authentication, blocks, etc). Note that this requires you put your models directory beneath the src folder.
RadiantWeb replied on at Permalink Reply
RadiantWeb
I put everything, including ajax stuff in either controllers or src. What it's named inside of those is sorta moot. ( I personally would love to see a standardization in that regard...but I gather that's never going to happen.)

ChadStrat
JohntheFish replied on at Permalink Reply
JohntheFish
The Linter runs a whole of load parser stuff for each test (only Korvin knows exactly how). That is why it is much slower than you would expect for simple string matching.

I couldn't get models, libraries etc to work in 5.7.4 and ended up with Chad's solution, everything is beneath controllers or src.

As far as the PRB is concerned with loading, the strategy for anything, new or legacy, has been that as long as it doesn't use include and it works and there is nothing obviously funny about it, then its pretty much OK. The reason is that without any documentation on packages, we don't have anything to judge against.
Korvin replied on at Permalink Reply
Korvin
I did link to the actual code used in this particular test in the prb admin forums when I announced the new test. If you haven't looked at that you should.

Guys these namespaces that you define yourself are simply PSR-4 prefixes, you tell the class loader "'THIS\ARBITRARY\STRING' is mapped to '/this/arbitrary/path'". Later when you try to autoload "\THIS\ARBITRARY\STRING\Some\ClassName", the class loader says "I know that this prefix maps to '/this/arbitrary/path', I know the classname is "ClassName", so I know the class MUST be located within "/this/arbitrary/path/Some/ClassName.php".

There is certainly fancy stuff going on with the namespaces that we register for you, but we've only removed this automatic PSR-4 namespace.
Mnkras replied on at Permalink Reply
Mnkras
The linter does its best, but it will have its false positives in this case.

Make sure your addon works properly in 5.7.4 and then get a hold of me or one of the other admins and we can exempt it.
jshannon replied on at Permalink Reply
jshannon
Ok. Thanks. That was going to be my next question.

It's easy/obvious to ask for an exemption during the PRB process but not after.

In fact, FWIW, the email that Korvin sent out linked to the PRB page which we can't access after it goes live, and the post-approval linter page doesn't even make it obvious which errors have been exempted.
jshannon replied on at Permalink Reply
jshannon
Hi All,

I had some problems just renaming directories because I had other stuff in the same directories that relied on a c5 directory structure to work. So I wrote an autoloader that anybody should be able to use:

public static function autoLoader($class) {
      $masterPrefix = 'Concrete\Package\LertecoMembership\\';
      $mpLen = strlen($masterPrefix);
      $secondaryPrefixes = array(
         'helpers',
         'libraries',
         'models',
         'tools',
      );
      if (substr($class, 0, $mpLen) === $masterPrefix) {
         $classWithoutPrefix = lcfirst(substr($class, $mpLen));
         $segments = explode('\\', $classWithoutPrefix);
         if (in_array($segments[0], $secondaryPrefixes)) {
            $file = preg_replace_callback(
               '/\\\\(\w)/',


Register with

spl_autoload_register('\Concrete\Package\LertecoMembership\Controller::autoLoader', true, true);


@John and @Mike -- I'll be PMing you for exemption because the linter is still catching the references to PackageName\Models\
Korvin replied on at Permalink Reply
Korvin
Please don't recommend doing this, you can register namespaces just fine
without registering your own autoloader. Come into the irc during standard
hours and we can help you with it.

On Wed, Apr 29, 2015, 11:17 PM concrete5 Community <
discussions@concretecms.com> wrote:
JohntheFish replied on at Permalink Reply
JohntheFish
When you help on IRC, you help just one person. Next person with the same problem comes along and you have to do it all over again.

When you write documentation and howtos, you help everyone.
jshannon replied on at Permalink Reply
jshannon
For the record, I copied the idea from the core and just cleaned up the code with preg_replace_callback()s.

https://github.com/concrete5/concrete5-5.7.0/blob/48436f09d85dd02ccc...

In retrospect, I might have wanted to just create one of c5's ModifiedLoaders and set it up with my prefix and basedir, but I was overly focused on having my $secondaryPrefixes list.
Korvin replied on at Permalink Reply
Korvin
Here's an example package that supports the legacy namespaces
https://github.com/Buttress/addon_legacy_package_concepts/...

I simply set up the PSR-4 namespaces here: https://github.com/Buttress/addon_legacy_package_concepts/blob/maste...

This will autoload any classes that start with "\Concrete\Package\LegacySample\Models" (or 'Libraries' or 'Helpers') using the PSR-4 namespace standard.
Korvin replied on at Permalink Reply
Korvin
Also, here's a really good description of PSR-4 namespaces and why they are the way they are: http://www.php-fig.org/psr/psr-4/meta/...
jshannon replied on at Permalink Reply
jshannon
The problem that I can see with that is that you're still using the Psr4ClassLoader() so while the initial directory structure might be "legacy", the files within models, helpers, and libraries (including any subdirectories) must be psr4.

If I were to do it again, I'd look at doing something similar with c5's ModifiedPsr4ClassLoader()

James
Korvin replied on at Permalink Reply
Korvin
That's true, all you have to do is change the classloader implementation you use. Really I wouldn't recommend using the custom autoloader over PSR-0 or PSR-4 moving forward, they are much more intuitive and universal.
Phallanx replied on at Permalink Reply
Phallanx
@jshannon

Slick :)
There is also a way to invoke the Symphony loader to achieve the same thing. But yours will do fine. You're obviously a man after my own heart - find the crack and stick a crowbar in!

Maybe its time to show how to integrate Miser into 5.7 in 3 lines of code.