Set up filters inside a package - laravel

I'm developing a package that registers some filters which the user can add to their routes if they wish.
eg.
\Route::filter('myPackage.hasSomething', 'Panthro\MyPackage\MyPackage#hasSomethingFilter');
I'm just concerned where I should place these in my package.
At the minute they are in my service provider class under register. Is this a good place for them? Is there a common practice where these should go?
I've read some blogs which places custom filters inside a filters folder, the only issue with this is that this is for the actually filter method and not for the code that registers the filter with the router.

You should not place that code into your package as end user should be able to assign a custom name to your filter. Think the may have already another existing filter with a conflicting name.
Just create your package as normal, with the only particulariry being you must make sure you class MyPackage has a method filter. The end user then could install the package with:
composer require "panthro/mypackage:dev-master"
Then edit app/config/app.php and add the service provider within the providers array:
'providers' => array(
'Panthro\MyPackage\ServiceProvider',
And finally add the filter to the bottom of the app/filters.php file:
Route::filter('hasSomething', 'Panthro\MyPackage\MyPackage');
For more info read the official docs Registering A Class Based Filter.

Related

How to attach middleware to an existing named route from a package in laravel 5?

I'm trying to extend an existing application without modifying its source code.
The application has a named route called wizard-add.
Is there a way to register \MyPackage\MyMiddleware with the existing route?
I tried attaching it via Route::getRoutes()->getByName('wizard-add')->middleware(\MyPackage\MyMiddleware::class); but since packages are registered before the routes are read, Route::getRoutes() returns an empty collection.
Thank you!
Since I didn't find a way to solve this, I extended the app's controllers and put my logic inside.
namespace MyPackage\Controllers;
use App\Controllers\WizardController;
class MyPackageWizardController extends WizardController { ... }
and then in my service provider's register() method:
$this->app->bind(WizardController::class, MyPackageWizardController::class);
So everytime the app attempts to instantiate WizardController, it instantiates MyPackageWizardController instead. I don't know if there are any drawbacks but so far this has been working perfectly for me.

How to mock User model within composer package development tests?

I started creating a laravel 5.8 based modular API framework for our company which should be extended using composer packages.
Now I stumbled over the problem to test each package by itself (each package has it's own GIT project of course) if the package needs to have access to the User model given in the base framework (App/Models/User).
There will be various packages naturally depending on the User model such as specific auth modules.
Unfortunately testing also gets more complex because we are using GraphQL (Lighthouse).
So how should this be done? I tried mocking App/Models/User with a User model contained in the tests folder of my package, but this did not work as expected:
$this->userMock = \Mockery::mock('CompanyName\\PackageName\\Tests\\User');
$this->app->instance('App\\Models\\User', $this->userMock);
When, after that, posting a GraphQL request the resolver method throws a Class App\Models\User does not exist error.
I am quiet new to testing with phpunit so maybe I am just missing something here?
Edit:
I just found out that the error message above is displayed because the User model is also referenced within the GraphQL schema file.
So I there is any solution out there it has to somehow "emulate" the not existing User model class for the whole request lifecycle I guess...
Ok I finally solved my problem which was more conceptual wise I guess. As the user model is pretty strongly tied to the (core) package I want to test, I have now moved the model into the package itself and removed it from the base project.
This has the advantage that the "end user developer" doesn't even see and has to cope with the user model which is handles by the package anyway.
Now I can test the package independently and only have to put a line of documentation into the README to tell, that a user has to change the auth.providers.users.modelvalue to let laravel use the appropriate model (e.g. CompanyName\\PackageName\\Models).
If there will be other packages extending the user model, they will have to depend on the core package (which they should either way) and can extend the model class and tell the user to update auth.providers.users.model again. This way it is also quiet transparent to see which user model is used currently.
For the GraphQL / Lighthouse part I have added the following code to the boot method of the package's service provider to make lighthouse know about new models within the package automatically:
$lighthouseModels = config('lighthouse.namespaces.models');
array_push($lighthouseModels, 'CompanyName\\PackageName\\Models');
config([
'lighthouse.namespaces.models' => $lighthouseModels
]);
This can be repeated for every package adding models as well so lighthouse knows about all of them.

Access Puppet Module variables from custom provider

I'm writing a custom provider and I'm only going to use it in the context of the module it's attached to. The module will already define things for the resource which I need to act on (e.g. username, password, IP Address). What I'm trying to do is access a variable in scope in the puppet manifest from the custom provider.
Is this possible?
init.pp:
class mymodule(
$username = 'admin',
-- snip --
}
provider.rb:
class Puppet::Provider::MyProvider < Puppet::Provider
def self.configure
#can I get to $mymodule::username here?
Some context:
I'm writing a set of types that will configure a server via an API. I want to have a type like:
mymodule_mail_settings { 'current':
server => 'mail.server.com'
mailuser => 'mail'
}
What I'm trying to avoid is having to pass the username/password/ip to access the server's API passed into all of these different types.
The variables are only meaningful in the context of evaluating the manifest code and creating a catalog. They don't become part of the catalog. This is why your type/provider code cannot work with them directly.
To avoid passing redundant info to lots of resources that share it, you can use some "clever" tricks. In a patch I wrote some time ago, I added this kind of meta-information to Puppet's resources type. You cannot do this in a module, but you can add your own meta-type to carry such hints.

Laravel 4 packages register "app:after" filter

I am developing a package for laravel 4 ("workbench"), and i would like to bind the "app:after" filter, to manipulate the http response.
Does anybody know how could i take control over the "app:after" filter within my package? is it possible at all?
Thanks for all
If you write a ServiceProvider, you can use the $this->app->after method inside the ServiceProvider's register method.
The users who pull in your package only need to register your serviceprovider in the app.providers config array.

Where does one place Models in a Laravel Package?

I'm currently following the Laravel Package documentation, which uses the workbench tool to create a standard package tree consisting of controller, config, views, etc. folders. Basically, most folders you would get in a standard Laravel app tree.
However, I had a couple of questions:
Why is the models folder absent here? (though the same goes for tests and commands)
Should I just create the folder myself and add it to the composer.json autoload classmap?
What classes should live inside src/<Namespace>/<PackageName>? I have noticed that a ServiceProvider is automatically created here, but I can imagine most other files just existing in the standard package directories.
Wockbench represents just a tool for creating other tools, that is triggered through CLI. Workbench is very abstract concept.
Model folder is absent simply because you don't need model in every new package. For example, if you are creating middleware package or you own filter package.
Every new class can be added to package dependent on its purpose and responsibility. It can be done in more then one way.
Classes that are general enough to go into every package are:
Package Service Provider
Facade
Basic Class
But it is not a black box. Consider for example request class - it is bound very early in the application life cycle, so no provider is needed.

Resources