Get View Output In CakePHP 2.x Model - cakephp

Context: I'm generating a PDF in a model callback (afterSave). I found a library I'm comfortable with called FPDF. I'm adding the FPDF class as a vendor.
So, without going into too much detail, essentially, once all checks have been completed for a particular contract application, the app needs to prepopulate a PDF file and attach it to an email.
I can figure everything out except how to generate the PDF in the model. I want to use a view to pass view vars to so that I can populate the template file and use the FPDF class to save a PDF file.
This file will in turn be attached the automated email and sent to the applicant.
So the flow is:
Once all checks have been complete (via crons and a CakePHP Shell), we trigger a function inside the model afterSave callback.
The function performs some logic and determines whether a declined or approved email should be sent.
If approved, then a PDF is generated using a view file and saved in /Views/pdf/
This file is attached to CakeEmail object and sent.
It's just the view rendering part here that I'm stuck with:
3. If approved, then a PDF is generated using a view file and saved in /Views/pdf/
How can I populate a view file with view variables and return the result into a variable?
For example, think of how the CakeEmail class does it with the CakeEmail->template('example') function......
Any ideas?

The answer is to construct your view class manually:
$view = new View(null, false);
$view->set(compact('variable1', 'variable2'));
$view->viewPath = 'ViewFolder';
$output = $view->render('view_file', 'layout');

Related

CakePHP Behaviors call to behavior method returns error

I've been working with cakephp for personal use. Now I understood that I want to create some functions that will be repeated in many models of my project, so I found out by Cakephp docs that the best way to do it is using Behaviors.
Objective:
Each time a new entity of my project models are created, I want to notice some users(coworkers) by email. Like a new project added, new task added, etc...
What achieved until now
I created a behavior with an afeterSave event listener; I attached it in one of my models.
When I create I add a new task it runs the behaviors methods and send a simple email.
Problem
The problem is to find out witch model has called the event
I read the cake2.x docs and the afterSave event used to receive the event and the model in witch you could call alias to know the model name:
public function afterSave(Model $model,...){
$model_name = $model->alias;
if ($model_name == 'some_model'){
//code for specific model
} else (...)
}
However in cakephp 3.9 we receive Event and EntityInterface:
public function afterSave(Event $event, EntityInterface $model)
{
# I tried $mail_HTMLmessage= $model->_registryAlias;
# I tried $mail_HTMLmessage= $model->_className;
# I tried $mail_HTMLmessage= $model->get('className');
$this->sendMail($mail_HTMLmessage);// this is another method that i defined in my behavior that sends an email to me with the string mail_HTMLmessage as the mail message.
return true;
}
I've tested mail_HTMLmessage=$event->getName() and in my email I received event.afterSave as expected.
However everything I tried to get model/class name it returned an empty string.
Is it possible to get the model name? and what is the best way to do it?
Thanks in advance
I believe what you're looking for is not in the event at all, but the entity. getSource(), to be specific.

How to bind uploaded file with ADAM to entity field correctly in 2sxc module?

I need to create entity object programmatically and fill it with data. One field needs to be of a file type. So I managed to create entity without file, upload file in ADAM using this sample of code. However it seems that I didn't bind it as it is binded when file is uploaded manually.
When a file is uploaded to entity field manually, you can see content like file:421 .../asdf.docx. However when I repeat code sample from link above, field contains that file available to choose and already uploaded, but field value is null. IFile.Url seems to write correct data via App.Data.Update method, but no id is displayed in admin panel.
Dictionary<string, object> fileDict = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase) {
{ "File", file.Url }
}; // file is ToSic.Sxc.Adam.IFile, returned by SaveInAdam
App.Data.Update(entityObj.EntityId, fileDict); // entityObj is ToSic.Eav.Data.IEntity, returned by App.Data.Create
I wonder if that's going to have some bad conscequences if it has no binding like manual upload and how to do that correctly?
To add files, you actually add them to a field (so that the UI can then offer them as if they were added by a normal user). Check out https://docs.2sxc.org/api/dot-net/ToSic.Sxc.Dnn.Web.IDynamicWebApi.html#ToSic_Sxc_Dnn_Web_IDynamicWebApi_SaveInAdam_System_String_System_IO_Stream_System_String_System_String_System_Nullable_System_Guid__System_String_System_String_
BTW: Best check out MobiusForms to see how it's done.
And I forgot to mention: here the docs https://docs.2sxc.org/web-api/custom-web-api-dotnet-saveinadam.html
To further explain:
SaveInAdam will place the file in the ADAM folder of the item. Since it could be that many files are added, it's just assuming that the field will be the library type - which doesn't store anything in the entity, it just automatically finds the folder that belongs to the field.
If you wish to not use the library feature but actually just the single-field with link, then you must also save the term like "file:74" into the value of the field.

How can i delete a session in view in cakephp 2.0?

I have read in the cake book that Session in view uses SessionHelper, but that helper doesn't have method to delete session. Is this really so, could anyone help?
To delete session data, use the Session Component within a Controller, not a View.
//example from the CakePHP book (linked above)
$this->Session->delete('Person');
Or:
The destroy method will delete the session cookie and all session data
stored in the temporary file system. It will then destroy the PHP
session and then create a fresh session:
$this->Session->destroy();
While it's technically possible to delete session data in a view (it's just a PHP file after all), the CakePHP Framework was built with the MVC structure in mind. The "V" (for "view") should only be related to displaying the data provided by the Controller (retrieved from the Model).
The Model deals with accessing the data/database, and the Controller does the application logic. So - the Session Component (components are for controllers) is given a method to delete session data, but the Session Helper (helpers are for views) is not.
Based on what is the situation Custom Flash Messages can be used. Set flash message with custom key, like this
$this->Session->setFlash('my_value', 'default', array(), 'my_key');
and read it in view using flash method (which will automatically delete it)
$value = $this->Session->flash('my_key');
more details in this post http://hashmode.com/cakephp-delete-session-in-view/81
try unset($_SESSION['YOUR_SESSION_KEY']); in your view.
To delete a session variable, you can use the following code (in a Controller).
// same as unset($_SESSION['your_session_varable'])
$this->Session->delete('your_session_varable');
You can destroy all session variables calling the following:
$this->Session->destroy();
If the session data is an array and you want to access it just once just like the setFlash, you can set the array to setFlash with no template = false.
$this->Session->setFlash($arrayData,false,array(),'formData');
And then access it in the view
$data = $this->Session->flash('formData');
pr($data);

Zend Form Object as a string

I have a system which has certain page content stored in the database. Within this text we have the ability to add in custom scripts such as {WIDGET_FORM} which replaces the text with the content of a class named app_resource_widget_form. Up until now this has worked but the form needs to be created by Zend Form. Unfortunately the function which creates this requires a string(html) to be returned as so far i can only return the zend form object. Does any one know if what i am trying to do is possible. At some point the form must get created as html, is there a way to manually call this and then use that?
Thanks in advance
Zend_Form has a __toString() method, so:
$html = str_replace('{WIDGET_FORM}', $form->__toString(), $html);

TCA type input eval user functions don't work properly in IRRE mode

I have a problem with the custom eval functions when the record is called from an IRRE field, in particular with the JavaScript function.
For example I open to edit the base record of "table1", then I click an IRRE field to create a record to the "table2", the fields of the records of "table2" have eval user functions that works Ok in normal editing, but when in IRRE the functions only work after save the form, so the first time when the record is created those functions are not doing them jobs.
I don't understand where is the problem, maybe the Javascript code is not loaded. How can I add that file manually to the backend template? How can I face this situation?
I tried to debug with console and when the functions are called these files are present:
alt_doc.php:765
jsfunc.evalfield-e6a70fd19bf472ef08fa4754aae256b8.js:69
jsfunc.tbe_editor-def45aac90022eed51193264931eefb3.js:660
alt_doc.php:408
alt_doc.php:409
Thanks in advance.
It is a problem with the launch of the JS code. When you open the parent form the JS code of the fields that use eval in the IRRE form is not launched, when you saved the form with the IRRE created, Typo3 reloads the frame and now the JS is accesible.
I don't know a trasparent way to by-pass this, you must save the parent form after create the IRRE form in order to use the JS custom eval code of the IRRE form.

Resources