Signal slots in Powermail - typo3

I am trying to extend Typo3 powermail 2.X version . My actually requirement is that , I will be creating a set of general field set under a storage folder. I mean , I will only creating entries to 'tx_powermail_domain_model_pages' table and 'tx_powermail_domain_model_fields' .
What I want to achieve is that , I want to reuse the same field set in other forms as well.
`$signalSlotDispatcher = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3 \CMS\Extbase\SignalSlot\Dispatcher');
$signalSlotDispatcher->connect(
'In2code\Powermail\Controller\FormController',
'formActionBeforeRenderView',
'In2code\Powermailextended\Controller\FormController',
'manipulateMailObjectOnCreate',
FALSE
);`
Tried to implement the same with signal shots . But couldn’t crack it down.
`<?php
namespace In2code\Powermailextended\Controller;
/**
* Using a Slot to call a Powermail Signal
*
* Class FormControllerExtended
* #package In2code\Powermailextended\Controller
*/
class FormController {
public function manipulateMailObjectOnCreate($forms, $pObj) {
}
}
Can anyone please advice me how I can implement this requirements ?

using the setting in Extension Manager we can implement this.

Related

TYPO3 Extension: How to make a relation to another extension’s model optional?

I have an events extension (for TYPO3 9 LTS and 10 LTS), say MyVendor\MyEvents and a Locations extension, say MyVendor\MyLocations.
The Model MyVendor\MyEvents\Domain\Model\Events has a property eventLocation which is defined to be an object of MyVendor\MyLocations\Domain\Model\Locations.
Now I want to make the relation to MyVendor\MyLocations\Domain\Model\Locations optional. I have found a way for the TCA to show a different form field in the backend depending on the MyLocations extension being installed. But I have no idea how to make all the type definitions in the Events model conditional. They are crucial for the extension to work:
namespace MyVendor\MyEvents\Domain\Model
class Events extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
{
/**
* #var \MyVendor\MyLocations\Domain\Model\Locations
*/
protected $eventLocation = NULL;
/**
* #return \MyVendor\MyLocations\Domain\Model\Locations $eventLocation
*/
public function getEventLocation()
{
return $this->eventLocation;
}
/**
* #param \MyVendor\MyLocations\Domain\Model\Locations $eventLocation
* #return void
*/
public function setEventLocation(\MyVendor\MyLocations\Domain\Model\Locations $eventLocation)
{
$this->eventLocation = $eventLocation;
}
}
In case MyVendor\MyLocations is loaded it needs to be defined as above, in case it isn’t loaded it should be just an integer.
In the TCA I am using if (TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('my_locations')) for showing a different field in the backend form for an event.
The Locations Model is in a separate extension because I am using it in a third extension as well.
In your events extension you could setup a repository for locations. Then you can map this repository to your location extensions model via TypoScript.

TYPO3 Extbase individual code on backend-deletion of an object

I would like to execute some individual code when one of my Extbase domain objects is deleted from the list view in TYPO3 backend.
Thought that it could / would work by overwriting the remove( $o ) method in the according repository like
public function remove( $object ) {
parent::__remove( $object );
do_something_i_want();
}
, but that won't work I guess. Looks like the repository-methods are only called / used by actions of my extension (e.g. if I had some delete-action in a FE- or BE-plugin) but not when the object is just deleted from list view in the backend? I don't use (up to now) any FE/BE-plugin / -actions - only the simple add/edit/delete functions in the backends list view of my storage folder.
Background: I have e.g. two models with some 1:n relation (let's say singer and song), where one object includes some uploaded file (album_cover > pointing to the file's URL in /uploads/myext/ folder); using #cascade works fine for deleting every song belonging to a singer that is deleted, but it won't touch the file uploaded (only) for song.album_cover - leading to quite some waste over time. So I would love to do some sort of onDeletionOfSinger() { deleteAllFilesForHisSongs(); }-thing.
(Same thing would apply on deletion of let's say a single song and it's album_cover-file.)
Sounds quite easy & common, but I just don't get behind it and found nothing useful - would love some hint / pointing to the right direction :-).
List view uses TCEmain hooks during its operations, so you can use one of them to intersect delete action, i.e.: processCmdmap_deleteAction
Register your hooks class in typo3conf/ext/your_ext/ext_tables.php
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processCmdmapClass'][] = 'VENDORNAME\\YourExt\\Hooks\\ProcessCmdmap';
Create a class with valid namespace and path (according to previous step)
file: typo3conf/ext/your_ext/Classes/Hooks/ProcessCmdmap.php
<?php
namespace VENDORNAME\YourExt\Hooks;
class ProcessCmdmap {
/**
* hook that is called when an element shall get deleted
*
* #param string $table the table of the record
* #param integer $id the ID of the record
* #param array $record The accordant database record
* #param boolean $recordWasDeleted can be set so that other hooks or
* #param DataHandler $tcemainObj reference to the main tcemain object
* #return void
*/
function processCmdmap_postProcess($command, $table, $id, $value, $dataHandler) {
if ($command == 'delete' && $table == 'tx_yourext_domain_model_something') {
// Perform something before real delete
// You don't need to delete the record here it will be deleted by CMD after the hook
}
}
}
Don't forget to clear system cache after registering new hook's class
In addition to biesiors answer I want to point out, that there is also a signalSlot for this. So you can rather register on that signal than hooking into tcemain.
in your ext_localconf.php put:
$signalSlotDispatcher =
\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\SignalSlot\\Dispatcher');
$signalSlotDispatcher->connect(
'TYPO3\CMS\Extbase\Persistence\Generic\Backend',
'afterRemoveObject',
'Vendor\MxExtension\Slots\MyAfterRemoveObjectSlot',
'myAfterRemoveObjectMethod'
);
So in your Slot you have this PHP file:
namespace Vendor\MxExtension\Slots;
class MyAfterRemoveObjectSlot {
public function myAfterRemoveObjectMethod($object) {
// do something
}
}
Note thet $object will be the $object that was just removed from the DB.
For more information, see https://usetypo3.com/signals-and-hooks-in-typo3.html

Symfony 2 - Change entity's field from Admin while keeping validation using SonataAdminBundle

Using:
Symfony 2.5
SonataAdminBundle
I am trying to change one of the entity fields (title) when data is submitted / saved to database by using two fields from associated entites ex.
DocumentRevision <- Document -> CustomEntity [title] = Document[title]+DocumentRevision[number]
But title of CustomEntity has to be unique - this was the problem I was trying to solve and managed with Database constraints and UniqueEntity validation (not quite - more on this later).
Now the issue is that I change the title data on Doctrine preUpdate/Persist effectivly skipping validation for that field since it's empty at validation time. When user puts wrong data Database layer throws an error about duplicate for unique constraint.
/**
* #ORM\PrePersist
* #ORM\PreUpdate
*/
public function setTitleFromDocumentName() {
$this->setTitle($this->getDocument()->getName() . " rev. " . $this->getDocumentRevision()->getRevisionNumber());
}
The entity itself is using UniqueEntity constraint on field title, so custom constraints or validation groups are pointles from my perspective as it would only duplicate the already used constraint.
/**
* #UniqueEntity(
* fields={"title"}
* )
**/
The simplest solution as it seems would be to get somewhere between post Submit before validation, but it would have to be done from Entity.
My question is how can (can it?) be done without overriding SonataCRUD Controller or it's other parts, is it even possible?
It can be done, but there are issues:
I was able to change the title using Form Events like this:
protected function configureFormFields(FormMapper $formMapper) {
...
$builder = $formMapper->getFormBuilder();
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
$data = $event->getData();
$form = $event->getForm();
if (!$data) {
return;
}
$data['title'] = $data['document'] . ' rev. ' . $data['documentRevision'];
$event->setData($data);
}
...
formMapper
->add('title',null,array(
...
);
The current problem is that I am getting the IDs of 'document' and 'documentRevision' and I need their names or __toString() representation at least.
Another issue is that although I can set the title using the event it shows error from DB when it should show Form error since validation should be done on FormEvents::SUBMIT - this one I don't understand.
Last thing to note is that if I try to use callback function:
$builder->addEventListener(FormEvents::PRE_SUBMIT, array($this,'onPreSubmit'))
public function onPreSubmit() {
$entity = $this->getSubject();
$entity->setTitleFromDocumentName();
}
I will get null title and errors if Entity tries to get fields from related entites - Calling function on non object.
Regarding entity data maybe this will help you to get the subject:
https://gist.github.com/webdevilopers/fef9e296e77bb879d138
Then you could use getters to get the desired data for instance:
protected function configureFormFields(FormMapper $formMapper)
{
$subject = $this->getSubject();
$formMapper->getFormBuilder()->addEventListener(FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($subject) {
$document = $subject->getDocument();
// ...
});
}
I also posted this on your issue:
https://github.com/sonata-project/SonataAdminBundle/issues/2273
To solved this when I changed the unique entity validation constraints as ones used by me where not completely valid from conceptual perspective.
Also it's important to note that functions that are marked as #PrePersist, #PreUpdate etc. must be public if they are to be used like that, marking them private will make Doctrine fail.
Note that the methods set as lifecycle callbacks need to be public and, when using these annotations, you have to apply the #HasLifecycleCallbacks marker annotation on the entity class.
See: http://doctrine-orm.readthedocs.org/en/latest/reference/events.html#lifecycle-callbacks (first paragraph after the code sample).

TYPO3 extension "news": Custom fields on Fluid Template

I am using the extension News System, "news", and while changing the templates, I've noticed that while I can use things like {newsItem.datetime} or {newsItem.uid}, I cant use this with the custom fields i have created when extending the table tx_news_domain_model_news, like {newsItem.mycustomfield}
Edit: I have been pointed to this url and I've followed the instructions, but it's not working. This is my code
News.php
<?php
class Tx_WedoExtendnews_Domain_Model_News extends Tx_News_Domain_Model_News {
/**
* #var string
*/
protected $txWedoextendnewsLocation;
public function getTxWedoextendnewsLocation() {
return "this";
return $this->txWedoextendnewsLocation;
}
public function getWedoextendnewsLocation() {
return "that";
return $this->txWedoextendnewsLocation;
}
}
?>
Since I wasn't getting anything, I changed the returning values to string literals, to see if the problem was in the class and method names, or the property. Im still not getting anything. I think the underscored might be playing tricks on my code.
My extension key is wedo_extendnews and the new field is tx_wedoextendnews_location. Any ideas where the error lies?
Yes. To be able to access an object in fluid, you need the according setters in your model and maybe (not sure right now) an entry in the TCA.
If you want to access {newsItem.mycustomfield} you need an according setter in the model, like public function getMycustomfield() (note the get in get<Myfuncname>, it is mandatory).

doctrine odm set random value generated by js Math.random() on pre persist

i'm trying to implement this pattern http://cookbook.mongodb.org/patterns/random-attribute/ in doctrine odm.
i would like to set this attribute on the pre-persist lifecycle event. To achieve the best results, i would like to use a native javascript function Math.random() because php cannot generate random floats and i would like to avoid writing a custom function for that.
is there a way to achieve this?
i tried:
/** #PrePersist */
public function generateRandom()
{
$this->random = new \MongoCode('Math.random()');
}
but it always sets the attribute to 1, no matter the code of the function
I'm not sure that it's best solution but, it works for me:
/**
* #MongoDB\PrePersist()
* #MongoDB\PreUpdate()
*/
public function generateRandom() {
$this->random = rand();
}