I am using plantuml to generate to UML figures and have a problem about the comments style.
Steps to reproduce my problem:
I create a file called mainpage.dox and write these contents:
/** \mainpage Sender class
* Sender class. Can be used to send a command to the server.
* The receiver will acknowledge the command by calling Ack().
* \startuml
* Sender->Receiver : Command()
* Sender<--Receiver : Ack()
* \enduml
*/
Then, I create doxyfile to set output optimized java or C#, has_dot and PLANTUML_JAR_PATH. The UML figure could be generated after running doxygen.
However, there is no any contents of mainpage and warning message when I change comment style into C#:
/// \mainpage Sender class
/// Sender class. Can be used to send a command to the server.
/// The receiver will acknowledge the command by calling Ack().
/// \startuml
/// Sender->Receiver : Command()
/// Sender<--Receiver : Ack()
/// \enduml
///
But the main page is generated (Show the text below) when I remove the uml comments
/// \mainpage Sender class
/// Sender class. Can be used to send a command to the server.
/// The receiver will acknowledge the command by calling Ack().
Does \startuml have to use C style comments? Thanks for any suggestion.
This is my DoxyFile: http://pastebin.com/hjEFz8b0
EDIT:
I just tested again with another style of comment. \startuml is working with this style
/*! \mainpage Sender class
Sender class. Can be used to send a command to the server.
The receiver will acknowledge the command by calling Ack().
\startuml
Sender->Receiver : Command()
Sender<--Receiver : Ack()
\enduml
*/
I'm afraid you found a bug.
In the meantime I've published the following fix for it:
https://github.com/doxygen/doxygen/commit/4df52916170bb81179697d0fa78c7d81fd95415f
Related
In the Struts documentation, it says:
Another common workflow stategy is to first render a page using an alternate method, like input and then have it submit back to the default execute method.
https://struts.apache.org/core-developers/action-configuration.html#post-back-default
How to do it using annotation only? It seems that only the execute() method is called.
In the documentation it's said to render a page can be used an alternate method like input. This means that when you submit a form on the page it can return back with the input result. Usually it happens automatically during validation process if the validation fails or it hasErrors. Then you can submit the form back to the default action's execute method. You don't need to specify a method in the action configuration. Also if you didn't specify the action attribute in the form tag then the same action will execute which was used to render a page.
Configuring actions you can use the same page for success result when rendering a page using GET method and input when POST method is requested.
To use annotations to configure actions mapping you can use a Convention Plugin.
Also note, to map a class method to the action you should put #Action annotation directly on this method rather than on the class.
More detailed explanation and documentation you can find here.
#Namespace("/")
public class ProductAction extends ActionSupport {
public String execute() {
return SUCCESS;
}
#Action(value="product",
results=#Result(location="/product-list.jsp")
)
public String search() {
return SUCCESS;
}
}
Notice, that the method execute is not mapped, so it will not execute. If you need that method execute you should create mapping to it. For this purpose you could place annotation on class or on method execute.
Backpack controllers do not contain Rest methods as is typical with Laravel, but use traits to implement CRUD operations, and occasionally (but not always - delete does not for example) setup methods (setupListOperation for example).
For authorization, for the rest of my app I use Gate declarations in AppServiceProvider, and declare $this->authorize() to check authorization in each of my controllers.
Where can I use authorize() to check each of the operations I implement from Backpack? I couldn't find a method that seemed appropriate to override in order to run that authorization before proceeding.
You will normally do this in your FormRequest classes, see https://backpackforlaravel.com/docs/4.1/crud-tutorial#the-request
Example:
<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
use Illuminate\Foundation\Http\FormRequest;
class TagRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
// only allow updates if the user is logged in
return backpack_auth()->check();
}
}
Then you'd set the request as a validator for the given opperation:
Example
protected function setupCreateOperation()
{
$this->crud->setValidation(TagRequest::class);
// TODO: remove setFromDb() and manually define Fields
$this->crud->setFromDb();
}
NOTE: While its not clear in the documentation or generated controllers (if you use the command line generator) you can in fact set a setup method for ALL opperations:
If you look at the packages allin.com/vendor/backpack/crud/src/app/Http/Controllers/CrudController.php file, in the setupConfigurationForCurrentOperation method you'll find:
/**
* Load configurations for the current operation.
*
* Allow developers to insert default settings by creating a method
* that looks like setupOperationNameOperation (aka setupXxxOperation).
*/
protected function setupConfigurationForCurrentOperation()
{
$operationName = $this->crud->getCurrentOperation();
$setupClassName = 'setup'.Str::studly($operationName).'Operation';
//.....
/*
* THEN, run the corresponding setupXxxOperation if it exists.
*/
if (method_exists($this, $setupClassName)) {
$this->{$setupClassName}();
}
}
This means that if your controller defines a setupDeleteOperation function, it WILL be called during the setup of the delete route for your CRUD.
After making use of #Wesley Smith's answer, I discovered a one-step approach to this.
As Wesley mentions, you can create setup methods for all of the crud operations, and this works as an excellent place to pass an auth. However, it does not update the other operation's links. For example, list will still contain a link to "edit," even if it's unauthorized. You can remove these with individual lines, but there's an easier way.
Instead, you can use the Setup method to pass allow/deny methods. Here's what my setup() now appears as.
public function setup()
{
CRUD::setModel(Workshop::class);
CRUD::setRoute(config('backpack.base.route_prefix') . '/workshop');
CRUD::setEntityNameStrings('workshop', 'workshops');
if (Gate::denies('admin.workshop.list'))
$this->crud->denyAccess('list');
if (Gate::denies('admin.workshop.show'))
$this->crud->denyAccess('show');
if (Gate::denies('admin.workshop.create'))
$this->crud->denyAccess('create');
if (Gate::denies('admin.workshop.update'))
$this->crud->denyAccess('update');
if (Gate::denies('admin.workshop.delete'))
$this->crud->denyAccess('delete');
}
This will not only deny access to the methods, but update each method with the appropriate #can blade directives, meaning unauthorized methods won't appear as links.
I've configured monolog to send errors via email as described in the symfony docs here: https://symfony.com/doc/4.3/logging/monolog_email.html
Works well with all errors happing during a request, as well as console command errors.
But it does not send emails for errors which occurred during the handling of a messenger message.
Errors are shown when running the consumer bin/console messenger:consume async -vv and they also show up in prod.log like this:
[2020-01-10 12:52:38] messenger.CRITICAL: Error thrown while handling message...
Thanks for any hints on how to set up monolog to get messenger errors emailed too.
In fact monolog swift_mailer type use SwiftMailerHandler
wish also implements reset interface and use memory spool by default wish keep all emails in buffer until it is destructed, so till the end of request :
onKernelTerminate
onCliTerminate
OR till reset method is called, which means that for messenger worker no emails will be send ever because ther's no instant flush - all of them will be kept in in-memory buffer, and probably lost if the process will be killed.
To solve this, you can just disable the default spool memory setting for swiftmailer.
Another solution is to flush your emails after WorkerMessageFailedEvent event gets fired, you can implement an event subscriber to do it for this.
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Messenger\Event\WorkerMessageFailedEvent;
use Symfony\Component\Messenger\Event\WorkerMessageHandledEvent;
use Symfony\Contracts\Service\ResetInterface;
/**
* Class ServiceResetterSubscriber.
*/
class ServiceResetterSubscriber implements EventSubscriberInterface
{
protected ResetInterface $servicesResetter;
public function __construct(ResetInterface $servicesResetter)
{
$this->servicesResetter = $servicesResetter;
}
public function resetServices(): void
{
$this->servicesResetter->reset();
}
public static function getSubscribedEvents(): array
{
return [
WorkerMessageFailedEvent::class => ['resetServices', 10],
];
}
}
Register your service with the right argument:
App\EventSubscriber\ServiceResetterSubscriber:
arguments: ['#services_resetter']
By the way without this (and without buffer limit) your app will leak and no emails will be sent ever.
Another trick:
Make sure that your message implements \JsonSerializable to get the message content in your logs, because messenger uses his monolog directly and its context serializer wish use json_encode for seriliazation.
That's why we need to customize their JSON representation when encoded is done with json_encode.
My User_model have a public method called is_unique_email($email). This method checks if a user has a uniqe mail adress with some status flag checks. This is also the reason why I can't use the standard is_unique validation rule from CodeIgniter.
I'm using a form_validation.php with config array for my validation rule groups. My question is: How can I call the model method for checking the new user's e-mail address? I searched and tried so many things, but nothing work. My preferred call would be with | pipe separator.
Like: trim|required|max_length[70]|valid_email|<~ here comes the model callback ~>
Is there any solution for this callback or is there no way and I have to extend the Form_validation system library?
I'm using CodeIgniter 3.1.7.
Thanks in advance!
UPDATE:
Because I've always done things via extending the form_validation library I forgot about this:
https://codeigniter.com/user_guide/libraries/form_validation.html#callbacks-your-own-validation-methods
and this (anonymous functions):
https://codeigniter.com/user_guide/libraries/form_validation.html#callable-use-anything-as-a-rule
Might be better for you. When in doubt, always read the docs ;)
Yes you can extend the form_validation library. In application/library make a MY_Form_validation.php and have it extend CI's as such:
class MY_Form_validation extends CI_Form_validation {
then in it you can do something like this:
/**
* Checks to see if bot sum is valid
* e.g. equals the session stored values
*
* #param int $sum
* #return boolean
*/
public function valid_bot_sum($sum) {
$generated = $this->CI->session->bot_first_number + $this->CI->session->bot_second_number;
if ($generated !== intval($sum)) {
$this->set_message('valid_bot_sum', 'Invalid bot sum.');
return false;
} else {
return true;
}
}
and now your function can be accessed via pipe separators as any native form_validation validation function. Just be sure to set the message on false as I've done, otherwise you will get an error. You can access the CI instance like so $this->CI.
In your case you can either migrate the function from the model into this file, or you can call it by loading the model in the function and calling the function and just testing to see if it evaluates to true/false and handling as above.
I'm using the MVVM Light Toolkit. I could not find any Ctor of Messenger or Notification class to send a empty message.
ViewModel1:
private int _selectedWeeklyRotation;
public int SelectedWeeklyRotation
{
get { return _selectedWeeklyRotation; }
set
{
if(_selectedWeeklyRotation == value)
return;
_selectedWeeklyRotation = value;
this.OnPropertyChanged("SelectedWeeklyRotation");
if(value > 1)
Messenger.Default.Send();
}
}
ViewModel2:
Ctor:
Messenger.Default.Register(this, CreateAnotherTimeTable);
private void CreateAnotherTimeTable()
{
}
I just need to send a Notification to another ViewModel, no sending of data at all.
Is that possible with MVVM Light Toolkit library?
Unless I'm misunderstanding something, couldn't you accomplish this by creating and sending a custom "signal message" type via the Messenger?
public class WeeklyRotationSignal {}
Messenger.Default.Send(new WeeklyRotationSignal());
Then register to that in another view model:
Messenger.Default.Register<WeeklyRotationSignal>(this, msg => doWork);
You can try sending a simple message with a string tag and receive that message by matching the string tag. Something like this:
Sender portion of the code located possibly in something like ViewModel1.cs
Messenger.Default.Send<string>("Dummy text message", "String_ToHelpMatchTheMsg");
Receiving end portion of the code responding to that message above, possibly located in some other file, something like ViewModel2.cs
...
Messenger.Default.Register<string>(this, "String_ToHelpMatchTheMsg", executeThisFunction);
private void executeThisFunction(string strMsg)
{
//your code would go here to run upon receiving the message
// The following line will display: "Dummy text message"
System.Windows.Browser.HtmlPage.Window.Alert("msg passed: " + strMsg);
}
Please note that you dont have to do anything with the text message that is passed around with the messaging code above. Just one part of the code sending some ping to another part of the code to ask some other section to execute some code. The important string is the one where I used "String_ToHelpMatchTheMsg" because that is the key used to match the sender and the receiver. Almost like creating your own quasi-event, once the Send method runs, the Register method is notified and fire its own function to run also.
I used this with a Close button on a Child Window to close it. The Close button on the View of the Child Window binds to a relay command on its childWindowViewModel. That relay command has the code above to send a message to the ParentViewModel. The Register portion on the ParentViewModel responds to that message by firing a method that closes the ChildWindow which was initially instantied from that parentViewModel.
Once you get more familiar with messaging, there are more attributes that you will be able to use so that the receiver can call back the sender to give a status or some data back. Look for Delegates and lambda function to achieve this.
All this to avoid placing code in the code behind to close the child window! :-)
Use as you see fit.
Cheers.
Mario
There really isn't a way to accomplish this and in someways defies the point of the messenger class. I didn't want to write a your doing it wrong post, but I feel I am stuck. The way the messenger class works is that you have two parties that both subscribe to the same concept, its an observer model. Without that similar concept or message there really isn't a way to tie the two objects together. The generic message whether a simple string or custom message act as the meeting point of the Subscribing and Publishing classes.
If the ViewModel publishing knows the type of ViewModel its trying to Send to it could...
Messenger.Default.Send<Type>(typeof(ViewModelToSendTo);
This would act as a very simple interaction point, you also wouldn't have to create a custom class. Some purist may have an issue with this approach as it couples the publishing class to the subscriber.
I don't think that it is possible and frankly I don't see the point of having that kind of message. You could just as well send a string "SelectedWeeklyRotation". It seems strange to have an empty message that has some kind of meaning as you increase the number of broadcast messages - and receivers in your application.
In the version of MVVM Light that I'm using it is not even possible to send an empty message.
However I did see a method in the ViewModelBase that is :
// Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging
RaisePropertyChanged(MyPropertyPropertyName, oldValue, value, true);
This might be of interest for you.