Sending ResetPassword notification using queue in Laravel 6 - error property 'view' - notifications

I want to override default notifications for password reset and email verification in laravel 6 to use queue in a simplest way as possible. So I add methods in User.php model:
use App\Notifications\ResetPasswordNotification;
use App\Notifications\EmailVerificationNotification;
...
public function sendPasswordResetNotification($token)
{
$this->notify(new ResetPasswordNotification($token));
}
public function sendEmailVerificationNotification()
{
$this->notify(new EmailVerificationNotification);
}
and create new notifications
ResetPasswordNotification
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Auth\Notifications\ResetPassword;
class ResetPasswordNotification extends ResetPassword implements ShouldQueue
{
use Queueable;
}
EmailVerificationNotification
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Auth\Notifications\VerifyEmail;
class EmailVerificationNotification extends VerifyEmail implements ShouldQueue
{
use Queueable;
}
Now email verification is sending queued, but in url as a host name is generating http://localhost/... In default notification it is generated correctly, the same one like a domain name in browser (without changing it in .env file).
The second problem is with password reset notification, which is not sending at all. It gives me an error
Trying to get property 'view' of non-object at vendor/laravel/framework/src/Illuminate/Notifications/Channels/MailChannel.php:92
and I don't understand why it is happening and don't working as expected.
Searching the problem I even found this (question) where fakemeta mention about it that should work.

I figured it out. First, when using queue, in my case I am running artisan queue:work with supervisor daemon, jobs are running under the console, so there is no SERVER['HTTP_HOST'] var available which mean than this value must be read from .env file. Second, when You change code overriding methods like I did, you must restart this queue:work to re-read changes. So those were my main problems.

Related

Two way databinding to singleton service Blazor Serverside

I have been playing with Blazor on the client using Webassembly quite a bit. But I thought I would try the serverside version now and I had a simple idea I wanted to try out.
So my understading was that Blazor serverside uses SignalR to "push" out changes so that the client re-renders a part of its page.
what I wanted to try was to databind to a property on a singleton service like this:
#page "/counter"
#inject DataService dataService
<h1>Counter</h1>
<p>Current count: #currentCount ok</p>
<p> #dataService.MyProperty </p>
<p>
#dataService.Id
</p>
<button class="btn btn-primary" #onclick="IncrementCount">Click me</button>
#code {
int currentCount = 0;
void IncrementCount()
{
currentCount++;
dataService.MyProperty += "--o--|";
}
}
Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton<WeatherForecastService>();
services.AddSingleton<DataService>();
}
Service:
namespace bl1.Services
{
public class DataService
{
public DataService()
{
this.Id = System.Guid.NewGuid().ToString();
}
public string Id {get;set;}
public string MyProperty { get; set; }
}
}
So my question is this. Why, if I open up this page in two tabs, do I not immediately see the value being updated for the property MyProperty with SignalR when I am changing the value on the property in one tab in the other tab? Is there a reason that is not supposed to work or am I just simply doing it wrong?
I thought the upside of using Blazor on the serverside was that you could easily use the fact that SignalR is available and get live updates when values change on the server.
I do get the latest value from the singleton service in the other tab but only after I click the button there.
Sorry you didn't get a better answer earlier Ashkan (I just read your question now). What you were attempting is actually something Blazor does very well and you are correct it is the perfect architecture for problems like this. Using SignalR directly, like the above answer suggested, would be correct for a Blazor WASM solution, but that doesn't address your question, which was about using Server-side Blazor. I will provide the solution below.
The important point is to understand that a blazor component does not "poll" for changes in its bound properties. Instead, a component will automatically re-render itself (to an internal tree) if say a button is clicked on that component. A diff will then be performed against the previous render, and server side blazor will only send an update to the client (browser) if there is a change.
In your case, you have a component that uses an injected singleton for its model. You then open the component in two tabs and, as expected (given Blazor's architecture), only the component in the tab where you clicked the button is re-rendering. This is because nothing is instructing the other instance of the component to re-render (and Blazor is not "polling" for changes in the property value).
What you need to do is instruct all instances of the component to re-render; and you do this by calling StateHasChanged on each component.
So the solution is to wire up each component in OnInitialized() to an event you can invoke by calling Refresh() after you modify a property value; then un-wiring it in Dispose().
You need to add this to the top of your component to correctly clean up:
#implements IDisposable
Then add this code:
static event Action OnChange;
void Refresh() => InvokeAsync(StateHasChanged);
override protected void OnInitialized() => OnChange += Refresh;
void IDisposable.Dispose() => OnChange -= Refresh;
You can move my OnChange event into your singleton rather than having it as a static.
If you call "Refresh()" you will now notice all components are instantly redrawn on any open tabs. I hope that helps.
See the documentation here
A Blazor Server app is built on top of ASP.NET Core SignalR. Each
client communicates to the server over one or more SignalR connections
called a circuit. A circuit is Blazor's abstraction over SignalR
connections that can tolerate temporary network interruptions. When a
Blazor client sees that the SignalR connection is disconnected, it
attempts to reconnect to the server using a new SignalR connection.
Each browser screen (browser tab or iframe) that is connected to a
Blazor Server app uses a SignalR connection. This is yet another
important distinction compared to typical server-rendered apps. In a
server-rendered app, opening the same app in multiple browser screens
typically doesn't translate into additional resource demands on the
server. In a Blazor Server app, each browser screen requires a
separate circuit and separate instances of component state to be
managed by the server.
Blazor considers closing a browser tab or navigating to an external
URL a graceful termination. In the event of a graceful termination,
the circuit and associated resources are immediately released. A
client may also disconnect non-gracefully, for instance due to a
network interruption. Blazor Server stores disconnected circuits for a
configurable interval to allow the client to reconnect. For more
information, see the Reconnection to the same server section.
So in your case the client in another tab is not notified of the changes made on another circuit within another ConnectionContext.
Invoking StateHasChanged() on the client should fix the problem.
For the problem you describe you better use plain SignalR, not Blazor serverside.
Just to add a little more to D. Taylor's answer:
I believe in most instances you'd want to move that OnChange action into the service.
In your services .cs you should add:
public event Action OnChange;
private void NotifyDataChanged() => OnChange?.Invoke();
private int myProperty; //field
public int MyProperty // property
{
get { return myProperty; }
set
{
myProperty= value;
NotifyDataChanged();
}
}
Every time that value is changed, it will now invoke that Action.
Now adjusting what D. Taylor did in the actual .razor file, in the #code{} section now just bind the refresh method to that Action in your service...
void Refresh() => InvokeAsync(StateHasChanged);
override protected void OnInitialized() => MyService.OnChange += Refresh;
void IDisposable.Dispose() => OnChange -= Refresh;
This should now push updates to the client!

How and where to instantiate a custom class that extends the WP_REST_Controller

I have a plugin that I created and I want to use the WP rest api controller pattern in order to extend the api.
<?php
/**
* Plugin Name: myplugin
* Plugin URI: h...
* Description: A simple plugin ...
* Version: 0.1
* Author: Kamran ...
* Author ....
* License: GPL2
function myplugin_register_endpoints(){
require_once 'server/controllers/my_ctrl.php';
$items=new items();
$items->register_routes();
}
add_action('rest_api_init','myplugin_register_endpoints');
.
.
I created a class a folder called server/controllers and inside it my_ctrl.php file with a class that extends WP_REST_Controller that looks like this
// server/controllers/my_ctrl.php
class items extends WP_REST_Controller {
/**
* Register the routes for the objects of the controller.
*/
public function register_routes() {
.....
}
}
However I am receiving the following error in sublime xdebuge call stack:
[Fatal error] Class 'myplugin\WP_REST_Controller' not found
I am not sure how to solve this issue, where to put the files for my custom controller, where to create the instance of the custom class etc?
Stumbled upon this and thought I'd provide my solution in case someone else encounters this.
The idea is to postpone the instantiation of the class extending WP_REST_Controller by not instantiating it until the actual rest_api_init hook is called.
Code example:
add_action( 'rest_api_init', function () {
require_once(plugin_dir_path(__FILE__) . '/VideoImageApi.php');
VideoImageApi::instance()->register_routes();
});
Note the require_once from within the callback.
I have manged to solve the issue,
I checked the wp-content\plugins folder and I couldn't find the \rest-api folder and although I found the folder inside \wp-includes\rest-api it seems that this folder that integrates the "wp rest api" into core doesn't include all the classes that the api can expose (it includes only 3 php files), So it didn't include \wp-content\plugins\rest-api\lib\endpoints\class-wp-rest-controller.php . I installed the "wp rest api" plugin and it was added to wp-content\plugins and now I don't have the error anymore. (It was strange because I don't know when it was deleted from my project)
Thank you Dan your comments really helped me to recheck everything and scan the folders included in my wordpress and realize that the plugin is missing and that the folder \wp-includes\rest-api doesnt contain all the needed classes.

Override and use front controller features in a prestashop module [1.6.x.x]

I would like to edit and add features to the prestashop Store Locator page.
Prestashop's documentation isn't really clear, and i would like to know if it's possible to implement a Controller in a custom module.
I would like to create a module which is able to extends StoreFrontController and it's features without starting from scratch.
Is it possible ? Have you some documentation for me ?
A beginner,
Best.
As you have many requirements, you will have to go with an override of class StoresController.php.
Your module folder should look like this:
/mymodule
/mymodule.php
/config.xml
/override
/controllers
/front
StoresController.php
/views
/templates
/front
stores.tpl
In StoresController.php you will have to override initContent():
<?php
class StoresController extends StoresControllerCore
{
/**
* Assign template vars related to page content
* #see FrontController::initContent()
*/
public function initContent()
{
parent::initContent();
// here add any smarty variables you want
$this->setTemplate(_PS_MODULE_DIR_.'mymodule/views/templates/front/stores.tpl');
}
}
Now you can add as many variables as you want in this controller and customized its template in your own module.
We you create an override in a module, it will be only parsed once at installation. If your module is already installed you will have to uninstall it and install it again. Then your override file will be copied to the root /override folder.
Any change made in your module override will not be reflected to the root override folder. So you will have to uninstall and install your module each time you want to make a change.
So I advise you to make all your changes directly in the root override folder, and when you're done copy this file back into your module folder. And if you don't want to uninstall your module and install it again to declare this file, you can put it directly in the root override folder and delete the file /cache/class_index.php so that Prestashop knows that an overrides has been added.
If you have any questions :)
You can start by overriding front controller like
`"/modules/mymodule/override/controllers/front/StoresController.php" and in this fine add class "class StoresControllerCore extends FrontController {
public function initContent()
{
parent::initContent();
//here do whatever you like
}
}"
though you must know coding to proceed further.

Ninject intercept throwing error. Dynamic proxy

I have a class which I use to bootstrap.
as part of the object creation I use by convention to bind to interfaces.
All works OK until I try to add an interceptor.
public class ContainerBootstrapper : IDisposable
{
StandardKernel _c;
public ContainerBootstrapper()
{
_c =new StandardKernel();
_c.Bind(b => b.FromAssembliesMatching("Facade*.*").SelectAllClasses().BindDefaultInterfaces());
_c.Bind(b => b.FromAssembliesMatching("Object*.*").SelectAllClasses().BindDefaultInterfaces());
_c.Bind(b => b.FromAssembliesMatching("Logger*.*").SelectAllClasses().BindDefaultInterfaces());
//even using the built in ActionInterceptor like this:
_c.Intercept(c => true)
.With(new ActionInterceptor(invocation =>
Console.Write(invocation.Request.Method.Name)));
When this line is hit, I get an error - Error loading Ninject component IAdviceFactory
No such component has been registered in the kernel's component container.
Suggestions:
1) If you have created a custom subclass for KernelBase, ensure that you have properly
implemented the AddComponents() method.
2) Ensure that you have not removed the component from the container via a call to RemoveAll().
3) Ensure you have not accidentally created more than one kernel.
I have at the top:
using Ninject.Extensions.Conventions;
using Ninject.Extensions.Interception.Injection.Dynamic;
using Ninject.Extensions.Interception.Infrastructure.Language;
using Ninject.Extensions.Interception;
and used NuGet for packages. Tried both Dynamic Proxies and LinFu. Both gave same error.
Anyone have any ideas to try?
Thanks in advance.
Turns out that even though I had a reference to the project doing the bootstrapping and I thought all my dlls for ninject where being copied over automatically this was not the case. After moving them manually it worked.

Shared base controller between modules

I am setting up a multi-module application, so far I have it setup like this example http://docs.phalconphp.com/en/latest/reference/applications.html.
But I was wandering if its possible to have shared base controller that both the backend and frontend controllers extend from. This is so I can have a single ACL in the base controller. How would I set that up?
According to the docs I can create a controllerbase anywhere and then just require this file directly in the bootstrap file or cause to be loaded using any autoloader. So I created a folder called apps/shared/controllers/ControllerBase.php and required this file directly in the bootstrap file but this does not work.
If I try to load a controller like so:
class AdminController extends ControllerBase
{
public function indexAction()
{
echo "<h1>Hello admin!</h1>";
}
}
I get an error ...Backend\Controllers\ControllerBase' not found in......
So how do I cause to be loaded using any autoloader as per the docs? Do I need to register it as its own namespace or something?
You not using the full namespace path for your base controller so the autoloader attempts to find it under in the same namespace of the child class.
Try something like this:
namespace MyApp\Backend\Controllers;
use MyApp\Shared\Controllers\ControllerBase;
class AdminController extends ControllerBase
{
public function indexAction()
{
echo "<h1>Hello admin!</h1>";
}
}
This answer consider that you have applied the PSR-0 and PSR-4 properly.